echarts實現(xiàn)工廠機器狀態(tài)圖
React中使用echart-for-react 實現(xiàn),前置準備
npm install echarts echarts-for-react -S
yarn add echarts echarts-for-react -S
案例中使用了ant,(阿里UI框架) 可裝可不裝
yarn add antd -S
實現(xiàn)如下:

WX20210722-145038@2x.png
index.tsx
// import './index.css';
import React, { Component, useState, useEffect, useRef } from 'react';
import { Card, Row, Col, Space } from 'antd';
import ReactEcharts from 'echarts-for-react';
//圖表函數(shù)
import {
dataAssembly,
formattered,
formatters,
formateText,
renderItem,
} from './data';
const D = (props: any) => {
//三種狀態(tài)的顏色
const colors: string[] = ['#2f4554', '#d48265', '#c23531'];
//三種狀態(tài)
const state: string[] = ['待機', '運行', '宕機'];
const actionRef = useRef(null);
useEffect(() => {
// 獲取圖表實例
const echarts_instance = actionRef.current.getEchartsInstance();
//定時器 繪圖
const t = setInterval(() => {
const arrData = dataAssembly();
echarts_instance.setOption({
series: [
// 用空bar來顯示三個圖例
{ name: state[0], type: 'bar', data: [] },
{ name: state[1], type: 'bar', data: [] },
{ name: state[2], type: 'bar', data: [] },
{
type: 'custom',
renderItem: renderItem,
encode: {
x: [1, 2], // data 中『維度1』和『維度2』對應到 X 軸
y: 0, // data 中『維度0』對應到 Y 軸
},
data: arrData,
},
],
});
}, 5000);
return () => {
clearInterval(t);
};
}, []);
//繪制圖表
const echartsDemo = (): {} => {
//獲取data
const arrData = dataAssembly();
return {
color: colors,
tooltip: {
//提示框
formatter: (params) => {
//數(shù)據(jù)格式化
let stateText = formateText(params.color);
let startTimer = formatters(params.value[1]);
let endTimer = formatters(params.value[2]);
//tips展示
return (
params.name +
' ' +
`${stateText}時間:` +
startTimer +
'~' +
endTimer
);
},
},
legend: {
//圖例
data: state,
bottom: '1%',
selectedMode: false, // 圖例設為不可點擊
textStyle: {
color: '#000',
},
},
grid: {
//繪圖網(wǎng)格
left: '3%',
right: '4%',
top: '1%',
bottom: '2%',
containLabel: true,
height: 500,
},
xAxis: {
type: 'time',
// interval: 1000, //以一個小時遞增
min: new Date().getTime() - 1000 * 60 * 60 * 2, //將data里最小時間的整點時間設為min,否則min會以data里面的min為開始進行整點遞增
splitNumber: 12, //分割段數(shù)
axisLabel: {
// margin: 1,
rotate: 340, //刻度標簽旋轉(zhuǎn)的角度,在類目軸的類目標簽顯示不下的時候可以通過旋轉(zhuǎn)防止標簽之間重疊。
formatter: formatters(new Date().getTime()),
},
},
yAxis: {
data: ['設備1', '設備2', '設備3', '設備4'],
},
series: [
// 用空bar來顯示三個圖例
{ name: state[0], type: 'bar', data: [] },
{ name: state[1], type: 'bar', data: [] },
{ name: state[2], type: 'bar', data: [] },
{
type: 'custom',
renderItem: renderItem,
encode: {
x: [1, 2], // data 中『維度1』和『維度2』對應到 X 軸
y: 0, // data 中『維度0』對應到 Y 軸
},
data: arrData,
},
],
};
};
return (
<div>
<Row gutter={24}>
<Col span={20}>
<Card title="設備狀態(tài)圖" className="shadowBox">
<ReactEcharts
ref={actionRef}
option={echartsDemo()}
style={{ height: '550px' }}
/>
</Card>
</Col>
</Row>
</div>
);
};
export default D;
data.ts
import * as echarts from 'echarts';
//數(shù)據(jù)組裝函數(shù)
const dataAssembly = (): void => {
const assArray: any[] = [];
//三種狀態(tài)
const typesStatus = [
{
name: '運行',
color: '#2f4554',
},
{
name: '待機',
color: '#d48265',
},
{
name: '宕機',
color: '#c23531',
},
];
//定義設備
const categories: string[] = ['設備1', '設備2', '設備3', '設備4'];
//獲取當前時間
const nowData: number = new Date().getTime();
//設置開始時間為過去兩個小時
const inThePastTime: number = nowData - 1000 * 60 * 60 * 2;
//組裝基本數(shù)據(jù)
//時間
const timerArr: number[] = [];
//狀態(tài)
const stateArr: string[] = [];
const baseAssData = (timer?: number): void => {
for (let index = 0; index < 24; index++) {
stateArr.push(typesStatus[Math.floor(Math.random() * 3)]['name']);
timerArr.push(timer as number + (1000 * 60 * 5) * index);
}
};
// console.log(stateArr);
// console.log(timerArr);
baseAssData(inThePastTime);
//組裝對象數(shù)據(jù)
const assvalue = () => {
for (let idx = 0; idx < 4; idx++) {
for (let i = 0; i < 24; i++) {
assArray.push({
//設備名稱
name: categories[idx],
value: [
//設備索引 作為y軸
idx,
//狀態(tài)開始時間
timerArr[i],
//狀態(tài)結(jié)束時間 i===23時候 ,timerArr[i+1] 不存在的
i === 23 ? (timerArr[23] + 1000 * 60 * 5) : timerArr[i + 1],
],
//狀態(tài)顏色
itemStyle: {
normal: {
color: typesStatus[Math.floor(Math.random() * 3)]['color']
}
}
})
}
}
return assArray
}
return assvalue();
// console.log(assArray);
}
// 時間格式化
const formattered = (val: number): number => {
if (parseInt(val) < 10) {
val = '0' + val;
}
return val;
};
const formatters = (value: number) => {
const date = new Date(value);
return (
formattered(date.getHours()) +
':' +
formattered(date.getMinutes()) +
':' +
formattered(date.getSeconds())
)
}
//狀態(tài)格式化
const formateText = (params: string) => {
switch (params) {
case '#2f4554':
return '運行';
case '#d48265':
return '待機';
case '#c23531':
return '宕機';
default:
break;
}
}
//坐標封裝函數(shù)抽取 //echarts自己封裝的方法
const renderItem = (params, api) => {
//開發(fā)者自定義的圖形元素渲染邏輯,是通過書寫 renderItem 函數(shù)實現(xiàn)的
const categoryIndex = api.value(0); //這里使用 api.value(0) 取出當前 dataItem 中第一個維度的數(shù)值。
const start = api.coord([api.value(1), categoryIndex]); // 這里使用 api.coord(...) 將數(shù)值在當前坐標系中轉(zhuǎn)換成為屏幕上的點的像素值。
const end = api.coord([api.value(2), categoryIndex]);
const height = api.size([0, 1])[1] * 0.6;
return {
type: 'rect', // 表示這個圖形元素是矩形。還可以是 'circle', 'sector', 'polygon' 等等。
shape: echarts.graphic.clipRectByRect(
{
// 矩形的位置和大小。
x: start[0],
y: start[1] - height / 2,
width: end[0] - start[0],
height: height,
},
{
// 當前坐標系的包圍盒。
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height,
},
),
style: api.style(),
};
}
export {
dataAssembly, formattered, formatters, formateText, renderItem
}