本文中Echarts的版本为5.5.0

        首先说一下我们的项目背景,就是需要一个横坐标为时间轴折线型数据。折线分为数值类型和枚举类型,也就是说Y坐标为数值型或者枚举型的数据;然后数据的缩放是这样的,把请求到的数据,一次性的全部显示在折线中,并且需要支持鼠标滚轮和鼠标拖拽式,缩放查看局部的数据。效果如图所示:

        项目中的难点主要是三部分。1、查询的到的数据,比如查询的是今天的数据,但是今天的话,只有在10点和11点有数据,其他的时间没有数据;2、横坐标下面的显示的当前缩放完成之后的时间范围;3、需要线断开连接,具体的规则是,当数据中有flage:start的时候,就认为这是一个新的曲线了,需要和前面的数据断开显示;

1、正确显示数据

配置dataZoom

        针对于第一个问题,采用的是dataZoom中配置,startValue和endValue,而不是配置start和end;

    dataZoom: [
      {
        type: "inside",
        // start: 50, // 不能使用百分比,因为搜索的时间和数据的时间不一定能对应上
        // end: 100,
        startValue: zoomStartValue,
        endValue: zoomEndValue,
        filterMode: "filter",
      },
    ],

        其中zoomStartValue和zoomEndValue就是第一条数据和最后一条数据的时间;例如刚刚说的上面的例子。搜索今天的全部数据,但是只有10点和11点之间是有数据。那么zoomStartvalue="2024-04-10 10:00:00",则zoomEndValue可能就是"2024-04-10 11:30:00"。这里不需要使用时间戳,直接使用字符串类型的时间就可以;但是因为搜索的是今天,所以在用户拖动的时候,应该是能拖动到今天的0点的。结束时间应该是查询的时候的时间。所以这个时候的x轴需要单独的配置;

配置xAxis

        在xAxis中,需要配置min和max两个参数,用于让x轴能滑动到今天的0点的时刻,虽然那个时间点并没有数据;

    xAxis: {
      type: "time", // 这里需要明确为“time”
      min: searchBeginTime,
      max: searchEndTime,
      axisLine: {
        show: true,
        lineStyle: {
          color: "#C0C0C0",
        }
      },
      axisTick: {
        show: true
      },
      axisLabel: {
        color: "#676767"
      },
      data: xdata, //  这里比较关键,需要传个数据,要不然直接靠server得到的数据,缩放有问题
    },

        其中的min和max对应的数据,就是搜索传给后台的数据。比如我搜索的今天的数据,那么searchBeginTime应该是"2024-04-10 00:00:00",searchEndTime应该是当前的搜索的结束时间:"2024-4-10 11:49:02";

        其中还有一个问题是我在实际开发中发现的。就是xAxis中的data数据也是需要传递的。要不然直接靠server中的横坐标的数据,下面缩放以后获取到的时间就有问题了。xdata的数据,就是后台给的数据中,所有数据的时间的数组:['2024-04-10 10:00:00','2024-04-10 10:15:00',2024-04-10 10:30:00,'2024-04-10 10:45:00',……'2024-04-10 11:30:00']

2、缩放显示当前的时间区间

监听dataZoom事件

        使用on("dataZoom")的方法,来监听Echats进行了缩放,而且这里面会有对应的,当前缩放的横坐标开始的百分比,和结束的百分比;

        具体的方法如下:

  myChart.off("dataZoom");
  myChart.on("dataZoom", (params) => {
    var optionData = myChart.getOption();
    var min = optionData.xAxis[0].min;
    var max = optionData.xAxis[0].max;
    var minT = new Date(min).getTime();
    var maxT = new Date(max).getTime();
    var len = maxT - minT;// 计算出时间的差额。使用的是时间戳计算~
    var start = params.batch[0].start; // 横坐标左侧的百分比
    var end = params.batch[0].end; // 横坐标右侧的百分比
    var startIndex = Math.round((len * start) / 100);
    var endIndex = Math.round((len * end) / 100);
    var xTextContent = `${moment(minT + startIndex).format("YYYY-MM-DD HH:mm:ss")} -- ${moment(minT + endIndex).format("YYYY-MM-DD HH:mm:ss")}`; // 使用moment插件,格式化成具体的时间
    xText.value = xTextContent;
  });

其中,start和end就是Echats缩放之后,获取的开始百分比和结束百分比;start的最小值为0,end的最大值为100。然后根据横坐标的min和max获取到整体的时间戳。然后计算出来差额,再根据百分比就能获取到当前的横坐标显示的时间了。

3、断开曲线

        项目中需要把数据中,含有flags:true的,就认为是一个新的曲线。当时我们想到的断开方法是给一个数据,只传时间,然后对应的值传空,这样就能断开了。但是由于我们的数据横坐标对应都是有值的。上面的方法就不可用了。所以我们采用的了第二种方法,就是在Echats中绘制了两条曲线,这两条曲线互不干扰。

        首先说一下,我们的数据:

var chartRowData = [{
  timestamp: "2024-4-10 11:20:00",
  value: 12,
  status: "null",
  flags: true,
},{
  timestamp: "2024-4-10 11:21:00",
  value: 19,
  status: "ok",
},{
  timestamp: "2024-4-10 11:22:00",
  value: 20,
  status: "alarm",
},{
  timestamp: "2024-4-10 11:23:00",
  value: 22,
  status: "ok",
},{
  timestamp: "2024-4-10 11:24:00",
  value: 8,
  status: "ok",
  flags: true,
},{
  timestamp: "2024-4-10 11:25:00",
  value: 15,
  status: "ok",
},{
  timestamp: "2024-4-10 11:26:00",
  value: 12,
  status: "ok",
},{
  timestamp: "2024-4-10 11:27:00",
  value: 14,
  status: "ok",
}]

        所以我采用下面的方法整理数据

var xdata = [], seriesData = [], seriesArr=[]; // 横坐标;一段横线的小数组;全部数据的数组
  var chartRowDataLength = chartRowData.length;
  chartRowData.forEach((item, i) => {
    xdata.push(item.timestamp);
    // 如果是flags的值为start的话,就重新添加一条线
    if(item.hasOwnProperty("flags") && item.flags == "start" && seriesData.length) {
      seriesArr.push({
        name: historyName,
        data: seriesData.slice(0),
        type: "line",
        smooth: true,
        showSymbol: false,
        emphasis: { // 关闭鼠标高亮
          disabled: true
        }
      })
      seriesData.splice(0);
    }
    seriesData.push([item.timestamp, item.value, item.status]);
    if (i == 0) {
      zoomStartValue = item.timestamp;
    }
    if (i == chartRowDataLength - 1) {
      zoomEndValue = item.timestamp;
      // 数据最后一条,也要添加到大数组中。
      seriesArr.push({
        name: historyName,
        data: seriesData.slice(0),
        type: "line",
        smooth: true,
        showSymbol: false,
        emphasis: { // 关闭鼠标高亮
          disabled: true
        }
      })
    }
  })

4、其他的小问题

设置语言

        做完了发现时间显示的有问题。就是不是按照咱们写的年月日时分秒显示的。所以需要在初始化Echats的时候,指定一下语言;

var chartDom = document.getElementById("chartDom");
myChart = echarts.init(chartDom, null, { locale: "ZH" });

一天中仅有一条数据

        测试提出,如果查询今天只有一条数据的话,就会发现,缩放有问题;经过查询代码发现,是因为zoomStartValue和zoomEndValue相等,导致了出现了横坐标显示的不是今天的数据。所以有了以下的一个判断:

    // 如果之有一个数据的话,zoomStartValue和zoomEndValue的值是一样的。这样Echarts的zoom就有问题了~
    // 所以需要单独处理一下
    if(chartRowData.length == 1) { 
      zoomStartValue = searchBeginTime;
      zoomEndValue = searchEndTime;
    }

        如有需要,可以查看资源。里面的代码可以直接运行,因为没有请求,所以里面很多内容都是直接写死的。

Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐