效果如下图:
代码:
引用部分:
<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;