完成第一屏幕页面基本布局以及TheHeader和DigitalFlop的UI界面

master
叶志超 2021-11-09 15:28:13 +08:00
parent 957b112736
commit 82aff8188a
15 changed files with 1447 additions and 1208 deletions

View File

@ -1,13 +1,13 @@
<!DOCTYPE html>
<html>
<html class="w-h-full">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<body class="w-h-full">
<div id="app" class="w-h-full text-white"></div>
<script type="module" src="/src/render/main.ts"></script>
</body>
</html>

View File

@ -1,27 +1,24 @@
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
<full-screen-container>
<TheHeader />
<div class="main-content flex flex-1 flex-col">
<DigitalFlopContainer />
<div class="block-left-right-content flex flex-1 mt-5">
<div class="block-left-content w-1/5 flex flex-col">
<div class="bg-red-100 flex-1"></div>
<div class="bg-green-100 flex-1"></div>
<div class="bg-blue-100 flex-1"></div>
</div>
<div class="block-right-content pl-5 flex flex-1 bg-yellow-100"></div>
</div>
</div>
</full-screen-container>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
export default defineComponent({
name: 'App',
components: {
HelloWorld
}
})
<script lang="ts" setup>
import FullScreenContainer from './components/Layout/FullScreenContainer.vue'
import TheHeader from './components/Layout/TheHeader.vue'
import DigitalFlopContainer from './components/DigitalFlopContainer.vue';
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

27
src/render/api/util.js Normal file
View File

@ -0,0 +1,27 @@
export function filterNonNumber (array) {
return array.filter(n => typeof n === 'number')
}
export function mulAdd (nums) {
nums = filterNonNumber(nums)
return nums.reduce((all, num) => all + num, 0)
}
export function getTwoPointDistance (pointOne, pointTwo) {
const minusX = Math.abs(pointOne[0] - pointTwo[0])
const minusY = Math.abs(pointOne[1] - pointTwo[1])
return Math.sqrt(minusX * minusX + minusY * minusY)
}
export function getPolylineLength(points) {
const lineSegments = new Array(points.length - 1)
.fill(0)
.map((foo, i) => [points[i], points[i + 1]])
const lengths = lineSegments.map(item => getTwoPointDistance(...item))
return mulAdd(lengths)
}

View File

@ -0,0 +1,9 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.w-h-full {
@apply w-full h-full m-0 p-0 overflow-hidden;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

View File

@ -0,0 +1,14 @@
<template>
<div class="digital-flop text-3xl font-bold" :style="style">
{{ value }}
</div>
</template>
<script lang="ts" setup>
import Vue from 'vue'
const props = defineProps({
value: Number,
style: String
})
</script>

View File

@ -0,0 +1,71 @@
<template>
<div class="digital-flop-container h-1/6 relative flex flex-shrink-0 justify-between items-center">
<div class="digital-flop-item w-1/6 h-4/5 flex flex-col justify-center items-center"
v-for="item in digitalFlopData"
:key="item.title"
>
<div class="digital-flop-title text-2xl mb-5">{{ item.title }}</div>
<div class="digital-flop flex">
<DigitalFlop
:value="item.value"
:style="item.style"
/>
<div class="unit ml-2.5 leading-10">{{ item.unit }}</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import DigitalFlop from './DigitalFlop.vue'
const digitalFlopData = reactive([
{
title: '日  期',
value: 28,
style: 'color: #4d99fc',
unit : '座'
}, {
title: '时  间',
value: 28,
style: 'color: #f46827',
unit : '座'
}, {
title: '经  度',
value: 28,
style: 'color: #40faee',
unit : '座'
}, {
title: '纬  度',
value: 28,
style: 'color: #4d99fc',
unit : '座'
}, {
title: '海  拔',
value: 28,
style: 'color: #f46827',
unit : '座'
}, {
title: '定位卫星数目',
value: 28,
style: 'color: #40faee',
unit : '座'
}
])
const update = console.log
defineExpose({ update })
</script>
<style scoped>
.digital-flop-container {
background-color: rgba(6,30,93,.5);
}
.digital-flop-item {
border-left: 3px solid #061e5d;
border-right: 3px solid #061e5d;
}
</style>

View File

@ -1,65 +0,0 @@
<template>
<h1>{{ msg }}</h1>
<p>
Recommended IDE setup:
<a href="https://code.visualstudio.com/" target="_blank">VSCode</a>
+
<a
href="https://marketplace.visualstudio.com/items?itemName=octref.vetur"
target="_blank"
>Vetur</a>
or
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
(if using
<code>&lt;script setup&gt;</code>)
</p>
<p>See <code>README.md</code> for more information.</p>
<p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Vite Docs</a> |
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Docs</a>
</p>
<button @click="count++">count is: {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test hot module replacement.
</p>
</template>
<script lang="ts">
import { ref, defineComponent } from 'vue'
export default defineComponent({
name: 'HelloWorld',
props: {
msg: {
type: String,
required: true
}
},
setup: () => {
const count = ref(0)
return { count }
}
})
</script>
<style scoped>
a {
color: #42b983;
}
label {
margin: 0 0.5em;
font-weight: bold;
}
code {
background-color: #eee;
padding: 2px 4px;
border-radius: 4px;
color: #304455;
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<div class="decoration-5" ref="dom">
<svg :width="width" :height="height">
<polyline
fill="transparent"
:stroke="stroke"
stroke-width="3"
:points="line1.points"
>
<animate
attributeName="stroke-dasharray"
attributeType="XML"
:from="`0, ${line1.length / 2}, 0, ${line1.length / 2}`"
:to="`0, 0, ${line1.length}, 0`"
:dur="`${dur}s`"
begin="0s"
calcMode="spline"
keyTimes="0;1"
keySplines="0.4,1,0.49,0.98"
repeatCount="indefinite"
/>
</polyline>
<polyline
fill="transparent"
:stroke="stroke"
stroke-width="2"
:points="line2.points"
>
<animate
attributeName="stroke-dasharray"
attributeType="XML"
:from="`0, ${line2.length / 2}, 0, ${line2.length / 2}`"
:to="`0, 0, ${line2.length}, 0`"
:dur="`${dur}s`"
begin="0s"
calcMode="spline"
keyTimes="0;1"
keySplines=".4,1,.49,.98"
repeatCount="indefinite"
/>
</polyline>
</svg>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue'
import { getPolylineLength } from '../../api/util'
const stroke = '#3f96a5'
const dur = 1.2
const dom = ref(null)
const width = ref(0)
const height = ref(0)
onMounted(() => {
width.value = dom.value.clientWidth
height.value = dom.value.clientHeight
calcSVGData()
})
const line1 = reactive({ points: [], length: 0})
const line2 = reactive({ points: [], length: 0})
const calcSVGData = () => {
line1.points = [
[0, height.value * 0.2], [width.value * 0.18, height.value * 0.2], [width.value * 0.2, height.value * 0.4], [width.value * 0.25, height.value * 0.4],
[width.value * 0.27, height.value * 0.6], [width.value * 0.72, height.value * 0.6], [width.value * 0.75, height.value * 0.4],
[width.value * 0.8, height.value * 0.4], [width.value * 0.82, height.value * 0.2], [width.value, height.value * 0.2]
]
line2.points = [
[width.value * 0.3, height.value * 0.8], [width.value * 0.7, height.value * 0.8]
]
line1.length = getPolylineLength(line1.points)
line2.length = getPolylineLength(line2.points)
line1.points = line1.points.map(point => point.join(',')).join(' ')
line2.points = line2.points.map(point => point.join(',')).join(' ')
}
</script>

View File

@ -0,0 +1,45 @@
<template>
<div class="decoration-8" ref="dom">
<svg :width="width" :height="height">
<polyline
:stroke="stroke"
stroke-width="2"
fill="transparent"
:points="`${xPos(0)}, 0 ${xPos(30)}, ${height / 2}`"
/>
<polyline
:stroke="stroke"
stroke-width="2"
fill="transparent"
:points="`${xPos(20)}, 0 ${xPos(50)}, ${height / 2} ${xPos(width)}, ${height / 2}`"
/>
<polyline
:stroke="stroke"
fill="transparent"
stroke-width="3"
:points="`${xPos(0)}, ${height - 3}, ${xPos(200)}, ${height - 3}`"
/>
</svg>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
const stroke = '#3f96a5'
const dom = ref(null)
const width = ref(0)
const height = ref(0)
onMounted(() => {
width.value = dom.value.clientWidth
height.value = dom.value.clientHeight
})
const props = defineProps({
reverse: Boolean
})
const xPos = (val: number) => props.reverse ? width.value - val : val
</script>

View File

@ -0,0 +1,33 @@
<template>
<div class="full-screen-container w-h-full fixed flex flex-col top-0 left-0 origin-top-left" ref="container">
<slot></slot>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
const { width, height } = screen
const container = ref(null)
const onResize = () => {
const currentWidth = document.body.clientWidth
container.value.style.transform = `scale(${currentWidth / width})`
}
onMounted(() => {
container.value.style.width = `${width}px`
container.value.style.height = `${height}px`
window.addEventListener('resize', onResize)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', onResize)
})
</script>
<style scoped>
.full-screen-container {
background-image: url('../../assets/img/bg-full.png');
}
</style>

View File

@ -0,0 +1,13 @@
<template>
<div class="the-header h-28 flex justify-between flex-shrink-0">
<Decoration8 class="w-1/4 h-16" />
<Decoration5 class="w-2/5 h-16 m-12" />
<Decoration8 class="w-1/4 h-16" :reverse="true" />
<div class="absolute left-1/2 transform -translate-x-2/4 text-3xl font-bold top-8 text-white">卫星数据监控平台</div>
</div>
</template>
<script lang="ts" setup>
import Decoration5 from './Decoration5.vue'
import Decoration8 from './Decoration8.vue'
</script>

View File

@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -1,5 +1,6 @@
import { createApp } from 'vue'
import App from './App.vue'
import './main.css'
import './assets/css/main.css'
createApp(App).mount('#app')

2242
yarn.lock

File diff suppressed because it is too large Load Diff