echarts实例:雷达图做出时钟效果

0 阅读1分钟

记录下工作中使用echarts做出的特殊组件

image.png

import { defineComponent } from 'vue'
import { FONT_SIZE, COLOR_LIGHT_ORG } from './createChart'


const props = {
  propData: {
    type: Array,
    default: () => [
      { name: 'A相电压相角', value: -110 },
      { name: 'B相电压相角', value: -130 },
      { name: 'C相电压相角', value: 15 },
    ],
  },
  showLegend: {
    type: Boolean,
    default: true,
  },
  lineColorArray: {
    type: Array,
    default: () => ['#00C7FA', '#F7C948', COLOR_LIGHT_ORG],
  },

}



export default defineComponent({
  props,
  data() {
    return {}
  },
  created() {},
  mounted() {
    this.init()
    this.$watch(
      () => this.$props, // 监听整个 props 对象
      () => {
        this.init()
      },
      { deep: true, immediate: false },
    )
  },
  beforeDestroy() {
    this.chart?.dispose?.()
  },
  methods: {
    init() {
      const indicator = this.generateMainIndicators()
      const option = {
        legend: [
          {
            show: this.showLegend,
            left: 'center',
            itemWidth: 40,
            itemHeight: 10,
            icon: 'rect',
            itemGap: 50,
            data: this.propData.map((item, index) => ({
              name: item.name,
              itemStyle: {
                color: this.lineColorArray[index] || '#FFf',
              },
            })),
            itemStyle: {
              borderWidth: 0,
              borderColor: 'transparent',
            },
            textStyle: {
              fontSize: FONT_SIZE,
              color: '#fff',
              padding: [0, 10],
            },
          },
        ],
        tooltip: {
          show: true,
          trigger: 'item',
          axisPointer: {
            type: 'none',
          },
          appendToBody: true,
          formatter: () => {
            let content = ''
            this.propData.map((item, index) => {
              content += `${item.name}: <span style="color:${this.lineColorArray[index] || '#FFf'}">${item.value}</span><br/>`
            })
            return content
          },
          textStyle: {
            fontSize: 50,
            color: '#fff',
            padding: [20, 100, 20, 100],
          },
          backgroundColor: '#0C3E5F',
          borderColor: '#0CB6FF',
          borderWidth: 4,
        },
        radar: [
          {
            // 第一个雷达:显示内圈
            radius: '60%',
            splitNumber: 3,
            startAngle: 90, // 添加开始角度配置
            center: ['50%', '50%'],
            axisLine: {
              show: true,
              lineStyle: {
                color: '#387892',
                type: 'dashed',
                width: 2,
              },
            },
            splitLine: {
              lineStyle: {
                color: '#387892',
                type: 'dashed',
                width: 2,
              },
            },
            splitArea: {
              show: true,
              areaStyle: {
                // 单色背景
                color: 'rgba(29, 65, 90, 0.5)',
                opacity: 1,
              },
            },
            axisName: {
              show: true, // 确保显示名称
              color: '#ffffff', // 名称颜色
              fontSize: 40,
            },
            indicator,
          },
          {
            // 第二个雷达:只显示最外圈
            radius: '60%',
            splitNumber: 1, // 只显示最外圈
            startAngle: 90, // 添加开始角度配置
            center: ['50%', '50%'],
            axisLine: {
              show: false,
            },
            axisName: {
              show: false, // 确保显示名称
            },

            splitLine: {
              lineStyle: {
                color: '#387892',
                type: 'solid', // 实线
                width: 5, // 粗线
              },
            },
            splitArea: {
              show: false,
            },
            axisLabel: {
              show: false,
            },
            indicator,
          },
          {
            // 第二个雷达:只显示最外圈
            radius: '60%',
            splitNumber: 1, // 只显示最外圈
            startAngle: 90, // 添加开始角度配置
            center: ['50%', '50%'],
            axisLine: {
              show: false,
            },
            axisName: {
              show: false, // 确保显示名称
            },

            splitLine: {
              show: false,
            },
            splitArea: {
              show: false,
            },
            axisLabel: {
              show: false,
            },

            indicator: this.generateContinuousIndicators(),
          },
        ],

        series: this.getSeries(),
      }
      this.draw(option)

    },
    draw(option) {
      const dom = this.$refs.chart
      if (!this.chart) {
        this.chart = echarts.init(dom, null, {
          renderer: 'canvas',
        })
      }
      this.chart.setOption(option, true)
    },
    getSeries() {
      return this.propData.map((item, index) => {
        return {
          name: item.name,
          type: 'radar',
          radarIndex: 2,
          symbolSize: 0,

          data: [
            {
              value: this.createDirectionData(item.value),
              name: item.name,
              lineStyle: {
                color: this.lineColorArray[index] || '#fff',
                width: 10,
              },
            },
          ],
        }
      })
    },
    generateContinuousIndicators() {
      const indicators = []
      for (let angle = 0; angle < 180; angle++) {
        indicators.push({
          name: angle.toString(),
          max: 100,
        })
      }
      for (let angle = -179; angle < 0; angle++) {
        indicators.push({
          name: angle.toString(),
          max: 100,
        })
      }
      return indicators
    },
    createDirectionData(angle) {
      const indicators = this.generateContinuousIndicators()
      const index = indicators.findIndex((item) => +item.name === +angle)
      return indicators.map((_, findex) => {
        return index === findex ? 95 : 0
      })
    },
    generateMainIndicators() {
      const targetAngles = [0, 30, 60, 90, 120, 150, 180, -150, -120, -90, -60, -30]
      const mainIndicators = []
      for (const angle of targetAngles) {
        mainIndicators.push({
          name: angle.toString(),
          max: 100,
        })
      }
      return mainIndicators
    },
  },
})