一个动态echarts仪表盘

效果如下图:

代码:

引用部分:
 <GaugeV1
    height={150}
    pieName={'showtemp'}
    pieData={92}
 />

组件GaugeV1:

import React, { useEffect} from 'react';
// 引入 ECharts 主模块
import * as echarts from 'echarts';
// 引入柱状图,折线图
import 'echarts/lib/chart/line';
import 'echarts/lib/chart/bar';
import 'echarts/lib/chart/pie';
// 引入提示框和标题组件
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/legend';

const GaugeV1 = ({
  pieData,
  pieName,
  height = 150,
}) => {
  let interval = null;

  //获取圆上面某点的坐标(x0,y0表示坐标,r半径,angle角度)

  const showPie = (pieData) => {
    let angle = 0; //角度,用来做简单的动画效果的
    let value = pieData;
    var colorSet = [
      [value / 100, '#05d5ff'],
      [1, '#2d3d45'],
    ];

    var loadChart = echarts.init(document.getElementById(pieName));

    var option = {
      backgroundColor: 'transparent',
      title: {
        text: '{a|' + (value >= 1 ? value : ' ' + value) + '}{c| %}',
        x: 'center',
        y: 'center',
        textStyle: {
          rich: {
            a: {
              fontSize: 18,
              color: '#29EEF3',
            },

            c: {
              fontSize: 12,
              color: '#ffffff',
              // padding: [5,0]
            },
          },
        },
      },
      legend: {
        type: 'plain',
        orient: 'vertical',
        right: 0,
        top: '10%',
        align: 'auto',
        data: [],
        textStyle: {
          color: 'white',
          fontSize: 16,
          padding: [10, 1, 10, 0],
        },
        selectedMode: false,
      },
      series: [
        {
          name: 'ring5',
          type: 'custom',
          coordinateSystem: 'none',
          renderItem: function (params, api) {
            return {
              type: 'arc',
              shape: {
                cx: api.getWidth() / 2,
                cy: api.getHeight() / 2,
                r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.5,
                startAngle: ((0 + angle) * Math.PI) / 180,
                endAngle: ((90 + angle) * Math.PI) / 180,
              },
              style: {
                stroke: '#0CD3DB',
                // stroke: 'red',
                fill: 'transparent',
                lineWidth: 1.5,
              },
              silent: true,
            };
          },
          data: [0],
        },
        {
          name: 'ring5',
          type: 'custom',
          coordinateSystem: 'none',
          renderItem: function (params, api) {
            return {
              type: 'arc',
              shape: {
                cx: api.getWidth() / 2,
                cy: api.getHeight() / 2,
                r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.5,
                startAngle: ((180 + angle) * Math.PI) / 180,
                endAngle: ((270 + angle) * Math.PI) / 180,
              },
              style: {
                stroke: '#0CD3DB',
                fill: 'transparent',
                lineWidth: 1.5,
              },
              silent: true,
            };
          },
          data: [0],
        },
        {
          name: 'ring5',
          type: 'custom',
          coordinateSystem: 'none',
          renderItem: function (params, api) {
            return {
              type: 'arc',
              shape: {
                cx: api.getWidth() / 2,
                cy: api.getHeight() / 2,
                r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
                startAngle: ((270 + -angle) * Math.PI) / 180,
                endAngle: ((40 + -angle) * Math.PI) / 180,
              },
              style: {
                stroke: '#0CD3DB',
                fill: 'transparent',
                lineWidth: 1.5,
              },
              silent: true,
            };
          },
          data: [0],
        },
        {
          name: 'ring5',
          type: 'custom',
          coordinateSystem: 'none',
          renderItem: function (params, api) {
            return {
              type: 'arc',
              shape: {
                cx: api.getWidth() / 2,
                cy: api.getHeight() / 2,
                r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
                startAngle: ((90 + -angle) * Math.PI) / 180,
                endAngle: ((220 + -angle) * Math.PI) / 180,
              },
              style: {
                stroke: '#0CD3DB',
                fill: 'transparent',
                lineWidth: 1.5,
              },
              silent: true,
            };
          },
          data: [0],
        },
        {
          name: 'ring5',
          type: 'custom',
          coordinateSystem: 'none',
          renderItem: function (params, api) {
            let x0 = api.getWidth() / 2;
            let y0 = api.getHeight() / 2;
            let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6;
            let point = getCirlPoint(x0, y0, r, 90 + -angle);
            return {
              type: 'circle',
              shape: {
                cx: point.x,
                cy: point.y,
                r: 2,
              },
              style: {
                stroke: '#0CD3DB', //粉
                fill: '#0CD3DB',
              },
              silent: true,
            };
          },
          data: [0],
        },
        {
          name: 'ring5', //绿点
          type: 'custom',
          coordinateSystem: 'none',
          renderItem: function (params, api) {
            let x0 = api.getWidth() / 2;
            let y0 = api.getHeight() / 2;
            let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6;
            let point = getCirlPoint(x0, y0, r, 270 + -angle);
            return {
              type: 'circle',
              shape: {
                cx: point.x,
                cy: point.y,
                r: 2,
              },
              style: {
                stroke: '#0CD3DB', //绿
                fill: '#0CD3DB',
              },
              silent: true,
            };
          },
          data: [0],
        },

        {
          type: 'gauge',
          radius: '87%',
          startAngle: '225',
          endAngle: '-45',
          pointer: {
            show: false,
          },

          //data: [value],
          title: {
            show: false,
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: colorSet,
              width: 10,
              // shadowBlur: 15,
              // shadowColor: '#B0C4DE',
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              opacity: 1,
            },
          },
          axisTick: {
            show: false,
          },
          splitLine: {
            show: false,
          },
          axisLabel: {
            show: false,
          },
        },

        {
          name: '表盘',
          type: 'gauge',
          radius: '115%',
          center: ['50%', '50%'],
          startAngle: '-180',
          endAngle: '180',
          splitNumber: 50,
          hoverAnimation: true,
          axisTick: {
            show: false,
          },
          splitLine: {
            length: 14,
            lineStyle: {
              width: 5,
              color: '#1E2C3B',
              // color: "red",
            },
          },
          axisLabel: {
            show: false,
          },
          pointer: {
            show: false,
          },
          axisLine: {
            lineStyle: {
              opacity: 0,
            },
          },
          detail: {
            show: false,
          },
          data: [
            {
              value: 0,
              name: '',
            },
          ],
        },
      ],
    };

    function getCirlPoint(x0, y0, r, angle) {
      let x1 = x0 + r * Math.cos((angle * Math.PI) / 180);
      let y1 = y0 + r * Math.sin((angle * Math.PI) / 180);
      return {
        x: x1,
        y: y1,
      };
    }

    function draw() {
      angle = angle + 3;
      loadChart.setOption(option);
    }

    interval = setInterval(function () {
      //用setInterval做动画
      draw();
    }, 100);
  };

  useEffect(() => {
    if (typeof pieData != 'undefined') {
      showPie(pieData);
    }
  }, [pieData]);
  useEffect(() => {//dom卸载时,停止Interval
    return () => {
      if (interval) {
        clearInterval(interval);
      }
    };
  }, []);
  return (
    <div
      id={pieName}
      style={{
        width: '100%',
        height: height,
        background: 'transparent',
      }}
    ></div>
  );
};

export default GaugeV1;

需要注意,如果一个页面引用多个GaugeV1,要保证引用时,pieName的唯一性。

题外话:如果出现闪动情况,大概率是因为pieData值出现了变动。因此要控制引用时pieData的确定性。最好等pieData赋值之后,再加载GaugeV1。

例如:

import React, { useEffect, useState } from 'react';

import GaugeV1 from './GaugeV1';

const App= () => {

  const [tempPassRate, setTempPassRate] = useState();

 useEffect(() => {

//此处可通过接口获取数据

    setTempPassRate(92);

  }, []);

return (

<div>

{typeof tempPassRate != 'undefined' && (

                      <GaugeV1

                        height={150}

                        pieName={'showtemp'}

                        pieData={tempPassRate}

                      />

                    )}

</div>

)

}

export default Home;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值