167 lines
4.1 KiB
Vue
167 lines
4.1 KiB
Vue
|
|
<template>
|
||
|
|
<div v-resize="resizeHandler" class="dv-decoration-9">
|
||
|
|
<svg width="100" height="100" :style="`transform: scale(${scaleRota[0]}, ${scaleRota[1]})`">
|
||
|
|
<defs>
|
||
|
|
<polygon :id="polygonId" points="15, 46.5, 21, 47.5, 21, 52.5, 15, 53.5" />
|
||
|
|
</defs>
|
||
|
|
|
||
|
|
<circle
|
||
|
|
cx="50"
|
||
|
|
cy="50"
|
||
|
|
r="45"
|
||
|
|
fill="transparent"
|
||
|
|
:stroke="mergedColor[1]"
|
||
|
|
stroke-width="10"
|
||
|
|
stroke-dasharray="80, 100, 30, 100"
|
||
|
|
>
|
||
|
|
<animateTransform
|
||
|
|
attributeName="transform"
|
||
|
|
type="rotate"
|
||
|
|
values="0 50 50;360 50 50"
|
||
|
|
:dur="`${dur}s`"
|
||
|
|
repeatCount="indefinite"
|
||
|
|
/>
|
||
|
|
</circle>
|
||
|
|
|
||
|
|
<circle
|
||
|
|
cx="50"
|
||
|
|
cy="50"
|
||
|
|
r="45"
|
||
|
|
fill="transparent"
|
||
|
|
:stroke="mergedColor[0]"
|
||
|
|
stroke-width="6"
|
||
|
|
stroke-dasharray="50, 66, 100, 66"
|
||
|
|
>
|
||
|
|
<animateTransform
|
||
|
|
attributeName="transform"
|
||
|
|
type="rotate"
|
||
|
|
values="0 50 50;-360 50 50"
|
||
|
|
:dur="`${dur}s`"
|
||
|
|
repeatCount="indefinite"
|
||
|
|
/>
|
||
|
|
</circle>
|
||
|
|
|
||
|
|
<circle
|
||
|
|
cx="50"
|
||
|
|
cy="50"
|
||
|
|
r="38"
|
||
|
|
fill="transparent"
|
||
|
|
:stroke="mergedColor[1]"
|
||
|
|
stroke-width="1"
|
||
|
|
stroke-dasharray="5, 1"
|
||
|
|
/>
|
||
|
|
|
||
|
|
<use
|
||
|
|
v-for="(foo, i) in new Array(20).fill(0)"
|
||
|
|
:key="i"
|
||
|
|
:xlink:href="`#${polygonId}`"
|
||
|
|
:stroke="mergedColor[1]"
|
||
|
|
:fill="Math.random() > 0.4 ? 'transparent' : mergedColor[0]"
|
||
|
|
>
|
||
|
|
<animateTransform
|
||
|
|
attributeName="transform"
|
||
|
|
type="rotate"
|
||
|
|
values="0 50 50;360 50 50"
|
||
|
|
:dur="`${dur}s`"
|
||
|
|
:begin="`${(i * dur) / 20}s`"
|
||
|
|
repeatCount="indefinite"
|
||
|
|
/>
|
||
|
|
</use>
|
||
|
|
|
||
|
|
<circle
|
||
|
|
cx="50"
|
||
|
|
cy="50"
|
||
|
|
r="26"
|
||
|
|
fill="transparent"
|
||
|
|
:stroke="mergedColor[1]"
|
||
|
|
stroke-width="1"
|
||
|
|
stroke-dasharray="5, 1"
|
||
|
|
/>
|
||
|
|
</svg>
|
||
|
|
<div>{{ dataValue }}{{ unit }}</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup lang="ts">
|
||
|
|
import type { CustomComponent } from 'open-data-v/base'
|
||
|
|
import { useEventBus, useProp } from 'open-data-v/base'
|
||
|
|
import { onMounted, ref } from 'vue'
|
||
|
|
|
||
|
|
import { http } from '@/utils/http'
|
||
|
|
|
||
|
|
import type { Gauge } from './type'
|
||
|
|
|
||
|
|
const props = defineProps<{
|
||
|
|
component: CustomComponent
|
||
|
|
}>()
|
||
|
|
|
||
|
|
const propChange = (propKeys: Array<string>, value: any) => {
|
||
|
|
if (propKeys.length !== 2) return
|
||
|
|
if (propKeys[0] === 'attr' && propKeys[1] === 'color1') mergedColor.value[0] = value
|
||
|
|
if (propKeys[0] === 'attr' && propKeys[1] === 'color2') mergedColor.value[1] = value
|
||
|
|
if (propKeys[0] === 'attr' && propKeys[1] === 'unit') unit.value = value
|
||
|
|
}
|
||
|
|
const { propValue } = useProp<Gauge>(props.component, propChange)
|
||
|
|
const mergedColor = ref<string[]>([propValue.attr.color1, propValue.attr.color2])
|
||
|
|
|
||
|
|
const polygonId = `decoration-9-polygon`
|
||
|
|
const dur = ref<number>(3)
|
||
|
|
const dataValue = ref<number>(0)
|
||
|
|
const scaleRota = ref<number[]>([1, 1])
|
||
|
|
|
||
|
|
const unit = ref<string>(propValue.attr.unit || '')
|
||
|
|
|
||
|
|
const resizeHandler = (entry: ResizeObserverEntry) => {
|
||
|
|
const rect: DOMRectReadOnly = entry.contentRect
|
||
|
|
const rate = Math.min(rect.width / 100, rect.height / 100)
|
||
|
|
scaleRota.value = [rate, rate]
|
||
|
|
}
|
||
|
|
|
||
|
|
const handler = (event) => {
|
||
|
|
const item: Record<string, any> = event as Record<string, any>
|
||
|
|
|
||
|
|
if (propValue.data.datatag && item.TagName === propValue.data.datatag) {
|
||
|
|
dataValue.value = Number(item.TagValue)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
onMounted(async () => {
|
||
|
|
await initData()
|
||
|
|
})
|
||
|
|
|
||
|
|
const initData = async () => {
|
||
|
|
if (propValue.data.history) {
|
||
|
|
try {
|
||
|
|
const resp = await http.post({
|
||
|
|
url: propValue.data.history,
|
||
|
|
data: [propValue.data.datatag]
|
||
|
|
})
|
||
|
|
if (resp.status === 200) {
|
||
|
|
dataValue.value = Number(resp.data.TagValue)
|
||
|
|
}
|
||
|
|
} catch (err: any) {
|
||
|
|
console.log(err.message || err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
useEventBus('actual', handler)
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style lang="less" scoped>
|
||
|
|
.dv-decoration-9 {
|
||
|
|
position: relative;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
svg {
|
||
|
|
position: absolute;
|
||
|
|
left: 0;
|
||
|
|
top: 0;
|
||
|
|
transform-origin: left top;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|