背景

由于要实现一个施工状态和时间段关联展示的总览图,可以看到一个整体,也可以看局部某一个阶段的,普通的柱状图无法满足需求,要根据时间段绘制不同的区间,柱状图的高度一致,宽度随着时间区间的大小去绘制。

实现方法

custom自定义系列里面使用了一个renderItem的方法,可以绘制不同的形状。
数据格式参考: https://echarts.apache.org/zh/option.html#series-custom.data

实现代码

<!DOCTYPE html>
<html lang="">

<head>
  <title>ECharts Custom 自定义渲染</title>
  <meta charset="utf-8">
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
</head>

<body>
  <div id="myChart" style="width: 600px;height: 400px;"></div>
  <script type="text/javascript">
    // 数据格式,也可根据文档里面自定义
    const dataList = [
      {
        "value": [
          "2023-04-03 16:00:00",
          "2023-04-03 18:30:00"
        ],
        "status": "a",
        "duration": 2.5
      },
      {
        "value": [
          "2023-04-03 18:30:00",
          "2023-04-04 00:00:00"
        ],
        "status": "b",
        "duration": 5.5
      },
      {
        "value": [
          "2023-04-04 00:00:00",
          "2023-04-04 03:00:00"
        ],
        "status": "b",
        "duration": 3
      },
      {
        "value": [
          "2023-04-04 03:00:00",
          "2023-04-04 04:00:00"
        ],
        "status": "d",
        "duration": 1
      },
      {
        "value": [
          "2023-04-04 04:00:00",
          "2023-04-04 06:00:00"
        ],
        "status": "a",
        "duration": 2
      },
      {
        "value": [
          "2023-04-04 06:00:00",
          "2023-04-04 14:00:00"
        ],
        "status": "c",
        "duration": 8
      },
      {
        "value": [
          "2023-04-04 14:00:00",
          "2023-04-04 14:30:00"
        ],
        "status": "b",
        "duration": 0.5
      },
      {
        "value": [
          "2023-04-04 14:30:00",
          "2023-04-04 16:30:00"
        ],
        "status": "d",
        "duration": 2
      },
      {
        "value": [
          "2023-04-04 16:30:00",
          "2023-04-04 17:15:00"
        ],
        "status": "f",
        "duration": 0.75
      },
      {
        "value": [
          "2023-04-04 17:15:00",
          "2023-04-04 17:30:00"
        ],
        "status": "a",
        "duration": 0.25
      }
    ]
    function addOneMinuteToDateTime(dateTimeString) {
      // 解析字符串到Date对象
      var date = new Date(dateTimeString);
      // 转换为时间戳
      var timestamp = date.getTime();
      // 加上1分钟
      var newTimestamp = timestamp + 1 * 60 * 1000;
      // 创建新的Date对象
      var newDate = new Date(newTimestamp);
      // 格式化新的日期时间
      var year = newDate.getFullYear();
      var month = ('0' + (newDate.getMonth() + 1)).slice(-2); // 月份是从0开始的,所以需要+1
      var day = ('0' + newDate.getDate()).slice(-2);
      var hours = ('0' + newDate.getHours()).slice(-2);
      var minutes = ('0' + newDate.getMinutes()).slice(-2);
      var seconds = ('0' + newDate.getSeconds()).slice(-2);
      // 返回格式化的字符串
      return (
        year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
      );
    }

    function getXValues() {
      const start = dataList[0].value[0];
      const end = dataList[dataList.length - 1].value[1];
      const datesArray = [];
      currentDate = new Date(start).getTime();
      const endDate = new Date(end).getTime();
      datesArray.push(start);
      while (currentDate <= endDate) {
        // 格式化当前日期时间
        datesArray.push(addOneMinuteToDateTime(currentDate));
        // 增加一分钟
        currentDate += 1000 * 60;
      }
      return datesArray;
    }
    let option = {
      dataZoom: { show: true },
      grid: [
        {
          top: '60%',
          height: '20%'
        }
      ],
      tooltip: {
        trigger: 'item',
        formatter: (params) => {
          return params.data.status;
        },
      },
      xAxis: {
        type: 'category',
        data: getXValues()
      },
      yAxis: {
        type: 'value',
      },
      series: [
        {
          name: '时长',
          type: 'custom',
          clip: true,  //超出裁剪
          animation: false, //关闭动画
          label: {
            show: false
          },
          renderItem: function (params, api) {
            let dataItem = dataList[params.dataIndex];
            let xStartValue = dataItem.value[0];
            let xEndValue = dataItem.value[1];
            let startIndex = option.xAxis.data.findIndex(
              (item) => item === xStartValue
            );
            let endIndex = option.xAxis.data.findIndex(
              (item) => item === xEndValue
            );
            let xStart = api.coord([startIndex, 0])[0];
            let xEnd = api.coord([endIndex, 0])[0];
            let width = xEnd - xStart;
            let y = api.coord([0, 0.5])[1];
            let height = api.size([0, 1])[1];
            const barLength = xEnd - xStart;
            var colorList = ['#C33531', '#EFE42A', '#64BD3D', '#EE9201', '#29AAE3'];
            return {
              type: 'rect',
              shape: {
                x: xStart,
                y: y - height / 2,
                width: width,
                height: height
              },
              style: api.style({ fill: colorList[params.dataIndex % colorList.length] }),
            };
          },
          data: dataList,
        }
      ]
    };
    let myChart = echarts.init(document.getElementById('myChart'));
    myChart.setOption(option);
  </script>
</body>

</html>

实现效果

image.png

image.png


fuGUI
1.6k 声望1.9k 粉丝

The best time to plant a tree is ten years ago, and the second,let us start