echarts实现工厂机器状态图(模拟)

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

实现如下:

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';
//图表函数
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
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容