echarts实现工厂机器状态图
React中使用echart-for-react 实现,前置准备
npm install echarts echarts-for-react -S
yarn add echarts echarts-for-react -S
案例中使用了ant,(阿里UI框架) 可装可不装
yarn add antd -S
实现如下:
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';
//图表函数
import {
dataAssembly,
formattered,
formatters,
formateText,
renderItem,
} from './data';
const D = (props: any) => {
//三种状态的颜色
const colors: string[] = ['#2f4554', '#d48265', '#c23531'];
//三种状态
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) => {
//数据格式化
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: {
//绘图网格
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, //分割段数
axisLabel: {
// margin: 1,
rotate: 340, //刻度标签旋转的角度,在类目轴的类目标签显示不下的时候可以通过旋转防止标签之间重叠。
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="设备状态图" className="shadowBox">
<ReactEcharts
ref={actionRef}
option={echartsDemo()}
style={{ height: '550px' }}
/>
</Card>
</Col>
</Row>
</div>
);
};
export default D;
data.ts
import * as echarts from 'echarts';
//数据组装函数
const dataAssembly = (): void => {
const assArray: any[] = [];
//三种状态
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;
//组装基本数据
//时间
const timerArr: number[] = [];
//状态
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);
//组装对象数据
const assvalue = () => {
for (let idx = 0; idx < 4; idx++) {
for (let i = 0; i < 24; i++) {
assArray.push({
//设备名称
name: categories[idx],
value: [
//设备索引 作为y轴
idx,
//状态开始时间
timerArr[i],
//状态结束时间 i===23时候 ,timerArr[i+1] 不存在的
i === 23 ? (timerArr[23] + 1000 * 60 * 5) : timerArr[i + 1],
],
//状态颜色
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())
)
}
//状态格式化
const formateText = (params: string) => {
switch (params) {
case '#2f4554':
return '运行';
case '#d48265':
return '待机';
case '#c23531':
return '宕机';
default:
break;
}
}
//坐标封装函数抽取 //echarts自己封装的方法
const renderItem = (params, api) => {
//开发者自定义的图形元素渲染逻辑,是通过书写 renderItem 函数实现的
const categoryIndex = api.value(0); //这里使用 api.value(0) 取出当前 dataItem 中第一个维度的数值。
const start = api.coord([api.value(1), categoryIndex]); // 这里使用 api.coord(...) 将数值在当前坐标系中转换成为屏幕上的点的像素值。
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
}