自定义ECharts图表-设备运行状态图


翻笔记看到两年前一个当时耗费挺长时间的看板页面,现在看来写的有些弱智,不过也侧面说明相较于之前有所成长吧(至少我觉得🤭)

需求

一个机台对应一个柱形图,柱形图反映机台从白班(当天早8点到晚8点)到夜班(当天晚8点到次日早8点)的运行状态,用不同颜色表示,每个柱形图后面还需要标注改机台的相关参数

问题

当时遇到的两个主要问题:

  1. 运行状态是变化的,所以不能用常规的柱状图表示,它的效果类似于堆叠条形图

  2. 按照需求机台名称和参数应该显示成双 Y 轴的样子,但是机台参数有多列

解决

对于问题1,当时恰好看到官网提供的性能分析图很适配,所以照着模拟出来了

对于问题2,当时想到的办法是把所有参数写在同一 Y 轴,用转义字符 \t 格式(现在想来有点蠢🤦🏻,后面知道了其实 ECharts 是支持多 Y 轴的)

option 配置如下

let option = {
    tooltip: {
        formatter: function(params) {
            const start = Math.floor(params.value[1] / interval) + 8 > 24 ? Math.floor(params.value[1] /
                interval) - 16 : Math.floor(params.value[1] / interval) + 8
            const end = Math.floor(params.value[1] / interval) + 9 > 24 ? Math.floor(params.value[1] /
                interval) - 15 : Math.floor(params.value[1] / interval) + 9
            return '时间段:' + start + '时 - ' + end + '时<br/>' + params.marker + params.name + ':' + Math
                .round(params.value[3] / 100 * 60) + ' 分钟';
        }
    },
    grid: {
        left: '120',
        right: '300',
        bottom: '10'
    },
    xAxis: {
        name: `设备运行状态`,
        nameLocation: 'center',
        nameGap: 30,
        nameTextStyle: {
            color: '#FFF',
            fontSize: 20,
            fontWeight: 'bold'
        },
        position: 'top',
        interval,
        max: interval * hours,
        axisLabel: {
            color: '#FFF',
            formatter: function(value, index) {
                return Math.floor(value / interval) + 8 > 24 ? Math.floor(value / interval) - 16 : Math
                    .floor(value / interval) + 8;
            }
        },
        axisPointer: {
            show: true,
            triggerTooltip: false,
            label: {
                show: false
            }
        },
        splitLine: false
    },
    yAxis: [{
            name: `机台编号  \n产品编号  `,
            nameLocation: 'start',
            nameGap: 50,
            nameTextStyle: {
                verticalAlign: 'top',
                align: 'right',
                color: '#FFF',
                fontSize: 20,
                fontWeight: 'bold',
                lineHeight: 24,
            },
            inverse: true,
            data: [],
            axisLine: {
                show: false
            },
            axisTick: true,
            axisLabel: {
                color: '#FFF',
                fontSize: window.screen.availHeight > 1000 ? 16 : 12,
                formatter: function (value, index) {
                    return value.split(' ')[0] + '\n' + value.split(' ')[1];
                }
            }
            data: machineList,
        },
        {
            name: `平均成型周期\t\t\t合模数\t\t\t达成率`,
            nameLocation: 'start',
            nameGap: 30,
            nameTextStyle: {
                align: 'left',
                color: '#FFF',
                fontSize: 20,
                fontWeight: 'bold'
            },
            inverse: true,
            axisLine: {
                show: false
            },
            axisTick: true,
            axisLabel: {
                color: '#FFF',
                fontSize: 20,
            },
            data: infoList,
        },
    ],
    series: [{
        type: 'custom',
        name: 'custom',
        labelLine: {
            show: true
        },
        renderItem,
        encode: {
            x: [1, 2],
            y: 0
        },
        data: machineItemList
    }]
}

renderItem 函数

custom 系列需要开发者自己提供图形渲染的逻辑。这个渲染逻辑一般命名为 renderItem

function renderItem(params, api) {
    let categoryIndex = api.value(0);
    let start = api.coord([api.value(1), categoryIndex]);
    let end = api.coord([api.value(2), categoryIndex]);
    let height = api.size([0, 1])[1] * 0.4;
    let rectShape = 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
    });
    return (
        rectShape && {
            type: 'rect',
            transition: ['shape'],
            shape: rectShape,
            style: api.style()
        }
    )
}

数据的格式类似这样

/* 变量说明
    * machineList:机台列表数组
    * infoList:[[平均成型周期,合模数,达成率],...]
    * machineItemList: [{
        * name	状态
        * value	[machineList.index,起始x坐标,结束x坐标,差值]
        * itemStyle	{
        * normal: {color} green:正常;yellow:待机;red:异常;orange:修模;gray:关机
        * }
    * }]
*/

{
    "machineList": [
        "机台1 ",
        // ...
    ],
    "infoList": [
        "         0.00           0      0.00%",
        // ...
    ],
    "machineItemList": [
        { "name": "正常", "value": [ 0, 0, 0, 0 ], "itemStyle": { "normal": { "color": "green" } } }, 
        { "name": "异常", "value": [ 0, 0, 0, 0 ], "itemStyle": { "normal": { "color": "red" } } }, 
        { "name": "待机", "value": [ 0, 0, 0, 0 ], "itemStyle": { "normal": { "color": "yellow" } } }, 
        { "name": "停机", "value": [ 0, 0, 100, 100 ], "itemStyle": { "normal": { "color": "gray" } } },
        // 此处省略了92个对象,每100个对象为一个机台数据,因为后端传回的数据即一个小时一种状态,一天24个小时,每一个小时存在4种状态可能,差值为100表示该时段状态
        { "name": "正常", "value": [ 1, 2400, 2400, 0 ], "itemStyle": { "normal": { "color": "green" } } },
        { "name": "异常", "value": [ 1, 2400, 2400, 0 ], "itemStyle": { "normal": { "color": "red" } } }, 
        { "name": "待机", "value": [ 1, 2400, 2400, 0 ], "itemStyle": { "normal": { "color": "yellow" } } }, 
        { "name": "停机", "value": [ 1, 2400, 2500, 100 ], "itemStyle": { "normal": { "color": "gray" } } }, 
        { "name": "正常", "value": [ 2, 0, 0, 0 ], "itemStyle": { "normal": { "color": "green" } } }, 
        { "name": "异常", "value": [ 2, 0, 0, 0 ], "itemStyle": { "normal": { "color": "red" } } }, 
        { "name": "待机", "value": [ 2, 0, 100, 100 ], "itemStyle": { "normal": { "color": "yellow" } } }, 
        { "name": "停机", "value": [ 2, 100, 100, 0 ], "itemStyle": { "normal": { "color": "gray" } } },
        // ...
    ]
}

效果


文章作者: April-cl
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 April-cl !
  目录