|
@@ -0,0 +1,127 @@
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import * as echarts from 'echarts'
|
|
|
|
|
+import { GaugeChart } from 'echarts/charts'
|
|
|
|
|
+import { LabelLayout, UniversalTransition } from 'echarts/features'
|
|
|
|
|
+import { CanvasRenderer } from 'echarts/renderers'
|
|
|
|
|
+import {
|
|
|
|
|
+ onUnmounted,
|
|
|
|
|
+ onMounted, ref, watch
|
|
|
|
|
+} from 'vue'
|
|
|
|
|
+
|
|
|
|
|
+echarts.use([ GaugeChart, LabelLayout, UniversalTransition, CanvasRenderer ])
|
|
|
|
|
+const props = withDefaults(defineProps<{
|
|
|
|
|
+ value: number,
|
|
|
|
|
+ gears?: string
|
|
|
|
|
+}>(), {
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ gears: '前进'
|
|
|
|
|
+})
|
|
|
|
|
+const chartDom = ref()
|
|
|
|
|
+const chart = ref(null as any)
|
|
|
|
|
+const option = ref({
|
|
|
|
|
+ series: {
|
|
|
|
|
+ name: 'Pressure',
|
|
|
|
|
+ type: 'gauge',
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#FFFFFF'
|
|
|
|
|
+ },
|
|
|
|
|
+ startAngle: 180,
|
|
|
|
|
+ max: 60,
|
|
|
|
|
+ endAngle: 0,
|
|
|
|
|
+ axisLine: {
|
|
|
|
|
+ lineStyle: {
|
|
|
|
|
+ width: 1
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ axisTick: {
|
|
|
|
|
+ distance: 0,
|
|
|
|
|
+ length: 10,
|
|
|
|
|
+ lineStyle: {
|
|
|
|
|
+ color: '#FFFFFF'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ splitLine: {
|
|
|
|
|
+ length: 15,
|
|
|
|
|
+ distance: 0,
|
|
|
|
|
+ lineStyle: {
|
|
|
|
|
+ color: '#FFFFFF'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ axisLabel: {
|
|
|
|
|
+ distance: 8,
|
|
|
|
|
+ color: '#FFFFFF'
|
|
|
|
|
+ },
|
|
|
|
|
+ progress: {
|
|
|
|
|
+ show: true
|
|
|
|
|
+ },
|
|
|
|
|
+ radius: '190%',
|
|
|
|
|
+ center: [ '50%', '98%' ],
|
|
|
|
|
+ detail: {
|
|
|
|
|
+ offsetCenter: [ 0, -25 ],
|
|
|
|
|
+ valueAnimation: true,
|
|
|
|
|
+ formatter: (value: number) => `{value|${value.toFixed(0)}}{unit|km/h}\n{num|${props.gears}}`,
|
|
|
|
|
+ rich: {
|
|
|
|
|
+ value: {
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ fontWeight: 'bolder',
|
|
|
|
|
+ color: '#FFFFFF'
|
|
|
|
|
+ },
|
|
|
|
|
+ unit: {
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ color: '#FFFFFF',
|
|
|
|
|
+ padding: [ 0, 0, 0, 10 ]
|
|
|
|
|
+ },
|
|
|
|
|
+ num: {
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ color: '#FFFFFF',
|
|
|
|
|
+ padding: [ 0, 0, 0, 10 ]
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ pointer: {
|
|
|
|
|
+ show: false
|
|
|
|
|
+ },
|
|
|
|
|
+ data: [ 0 ]
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+function resetChart() {
|
|
|
|
|
+ if (!chart.value) return
|
|
|
|
|
+ chart.value.resize()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+watch(() => props.value, (v: number) => {
|
|
|
|
|
+ if (!chart.value) return
|
|
|
|
|
+ if (v >= 60) v = 60
|
|
|
|
|
+ if (v <= 0) v = 0
|
|
|
|
|
+ option.value.series.data[0] = v
|
|
|
|
|
+ chart.value.setOption(option.value)
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+watch(() => props.gears, () => {
|
|
|
|
|
+ if (!chart.value) return
|
|
|
|
|
+ chart.value.setOption(option.value)
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+onMounted(() => {
|
|
|
|
|
+ chart.value = echarts.init(chartDom.value)
|
|
|
|
|
+ chart.value.setOption(option.value)
|
|
|
|
|
+ window.addEventListener('resize', resetChart, false)
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ window.removeEventListener('resize', resetChart, false)
|
|
|
|
|
+})
|
|
|
|
|
+</script>
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div
|
|
|
|
|
+ id="charts"
|
|
|
|
|
+ ref="chartDom"
|
|
|
|
|
+ />
|
|
|
|
|
+</template>
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+#charts {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|