echarts设置多条折线不是你想的那样简单

简单的多条折线图

小伙伴写过多条折线图的都知道,
常见的折线图是  xAxis 配置项下的 data属性上设置时间或者日期。
series配置项下是对应的 legend中的数据以及该条折线的数据。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>多条折线图</title>
  <script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
</head>

<body>
  <div style="width: 900px;height: 400px;"></div>
</body>
<script>
  let myChart = echarts.init(document.querySelector('div'))
  // 设置X轴的时间
  let dataXTime = [
    '2023-12-04 09:45:07', '2023-12-04 09:50:07','2023-12-04 09:55:07', '2023-12-04 10:00:07', '2023-12-04 10:05:07',
    '2023-12-04 11:05:07','2023-12-04 12:05:07','2023-12-04 13:05:07','2023-12-04 14:05:07','2023-12-04 15:05:07',
  ]
  let option = {
    // 设置的是标题
    title: {
      text: '折线图'
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      data: ['Email', 'Union Ads']
    },
    // 网格间距设置
    grid: {
      left: '30px',
      right: '60px',
      bottom: '3%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: dataXTime,
    },
    yAxis: {
      type: 'value'
    },
    // 数据
    series: [
      {
        name: 'Email',
        type: 'line',
        data: [120, 132, 101, 134, 90, 230, 210,90, 230, 210]
      },
      {
        name: 'Union Ads',
        type: 'line',
    
        data: [220, 182, 191, 234, 290, 330, 310,9, 30, 110]
      }
    ]
  };
  myChart.setOption(option);
</script>
</html>

发现多条折线共享一个时间

通过上面的小例子,我们发现一个问题:
多条折线共享的是一个时间(时间与数据是1对多的关系)
第一个时间匹配第一个数据,第2个时间匹配第2个数据。
也就是第n个时间匹配第n个数据。
我们不仅会提出这样一个问题:
有没有可能让每一条折线拥有自己的时间呢?
时间不同,也可以显示在一个实例上。

多条折线拥有数据自己的时间

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>多条折线图</title>
  <script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
</head>

<body>
  <div style="width: 900px;height: 400px;"></div>
</body>
<script>
  let myChart = echarts.init(document.querySelector('div'))
  let option = {
    // 设置的是标题
    title: {
      text: '折线图'
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      data: ['邮件', '短信']
    },
    // 网格间距设置
    grid: {
      left: '30px',
      right: '60px',
      bottom: '3%',
      containLabel: true
    },
    xAxis: {
      // xAxis的下不在设置data属性共享时间
      type: 'category',
      splitLine: { show: false },
      lineStyle: {
        width: 2
      },
      axisTick: {
        show: false
      },
      axisLabel:{
        // 更改x轴文字颜色的配置
        textStyle: {
          color: '#717782'
        },
        showMaxLabel: true // 固定显示X轴的最后一条数据
      },
      // 更改x轴线的颜色
      axisLine: {
        lineStyle: {
          color: '#D2DBE6;',
          width: 1 // x轴线的宽度
        }
      },
    },
    yAxis: {
      type: 'value'
    },
    // 数据
    series: [
      { 
        "name": "邮件", 
        "type": "line", 
        "symbol": "rect",
        "connectNulls": true,
        "showAllSymbol": true, 
        // 让每一条折线拥有数据自己的时间
        "data": [ 
          [ "2023-12-04 09:50:07", "0.137"],
          [ "2023-12-04 09:55:07", "0.147"],
          [ "2023-12-04 10:00:07", "0.137"],
          [ "2023-12-04 10:05:07", "0.163"],
          [ "2023-12-04 10:10:07", "0.150"], 
          [ "2023-12-04 10:15:07", "0.143"], 
          [ "2023-12-04 10:20:07", "0.133"],
          [ "2023-12-04 10:25:07", "0.147"], 
          [ "2023-12-04 10:30:07", "0.147"],
          [ "2023-12-04 10:35:07", "0.143"],
          [ "2023-12-04 10:40:07", "0.140"], 
          [ "2023-12-04 10:45:07", "0.150"], 
          [ "2023-12-04 10:50:07", "0.143"],
        ], 
        "unit": "%", 
        "markPoint": { 
          "symbol": "rect",
          "symbolSize": "12",
          "label": { "show": false },
          "tooltip": { "triggerOn": "click", "trigger": "item" }, 
        }
      },
      { 
        "name": "短信", 
        "type": "line", 
        "symbol": "rect", 
        "connectNulls": true, 
        "showAllSymbol": true, 
          "data": [ 
            [ "2023-12-04 10:35:07", "0.123"],
            [ "2023-12-04 10:40:07", "0.140"], 
            [ "2023-12-04 10:45:07", "0.150"], 
            [ "2023-12-04 10:50:07", "0.143"],
          ], 
          "unit": "%", 
          "markPoint": { 
            "symbol": "circle",
            "symbolSize": "12", 
            "label": { "show": false } 
          } 
      } 
    ]
  };
  myChart.setOption(option);
</script>
</html>

成功了吗?多条折线拥有数据自己的时间

根据上面的图片,我们发现。
好像确实是每一条折线都拥有数据自己的时间了。
但是如果你只细看的话。你就会发现端倪
结束时间都是一样的,但是折线却是在不同的时间上结束的。
很明显不正确的。

多条折线他们必须有一样的开始时间和结束时间?

上面我们发现了问题:结束时间都是一样的,但是折线却是在不同的时间上结束的。
有的机智的小伙伴可能会说:
是因为:多条折线他们必须有一样的开始时间和结束时间。
这样echarts在渲染的时候就不会出现上面这样的情况。
需要有相同的起始点和结束点
感觉有点道理,我们尝试一下

 series: [
  { 
    "name": "邮件", 
    "data": [ 
      [ "2023-12-04 09:50:07", "0.137"],
      [ "2023-12-04 09:55:07", "0.147"],
      [ "2023-12-04 10:00:07", "0.137"],
      [ "2023-12-04 10:05:07", "0.163"],
      [ "2023-12-04 10:10:07", "0.150"], 
      [ "2023-12-04 10:15:07", "0.143"], 
      [ "2023-12-04 10:20:07", "0.133"],
      [ "2023-12-04 10:25:07", "0.147"], 
      [ "2023-12-04 10:30:07", "0.147"],
      [ "2023-12-04 10:35:07", "0.143"],
      [ "2023-12-04 10:40:07", "0.140"], 
      [ "2023-12-04 10:45:07", "0.150"], 
      [ "2023-12-04 10:50:07", "0.143"],
    ], 
  },
  { 
    "name": "短信", 
    "data": [ 
      [ "2023-12-04 09:50:07", "0.8"],
      [ "2023-12-04 10:40:07", "0.140"], 
      [ "2023-12-04 10:45:07", "0.150"], 
      [ "2023-12-04 10:50:07", "0.143"],
    ], 
  } 
]
现在都有相同的起始点(2023-12-04 09:50:07)和结束点(2023-12-04 10:50:07)。

如果每条折线的时间都没有交集会怎么样?

我们发现只要有相同的起始点和结束点;
就会可以达到我们的预期效果。
此时,有的小伙伴说:
"如果他们的时间如果没有交集会怎么样(有相同的起始点和结束点)"
"data": [ 
  [ "2023-12-04 09:50:07", "0.137"],
  [ "2023-12-04 09:55:07", "0.147"],
  [ "2023-12-04 10:00:07", "0.137"],
  [ "2023-12-04 10:05:07", "0.163"],
  [ "2023-12-04 10:10:07", "0.150"], 
  [ "2023-12-04 10:15:07", "0.143"], 
  [ "2023-12-04 10:20:07", "0.133"],
  [ "2023-12-04 10:25:07", "0.147"], 
  [ "2023-12-04 10:30:07", "0.147"],
  [ "2023-12-04 10:35:07", "0.143"],
  [ "2023-12-04 10:40:07", "0.140"], 
  [ "2023-12-04 10:45:07", "0.150"], 
  [ "2023-12-04 10:50:07", "0.143"],
], 

"data": [ 
  [ "2023-12-04 09:50:07", "0.8"],
  [ "2023-12-04 09:52:07", "1.23"],
  [ "2023-12-04 10:41:07", "0.140"], 
  [ "2023-12-04 10:49:07", "0.150"], 
  [ "2023-12-04 10:50:07", "0.143"],
], 

xAxis 的 type值设置time

时间绘制的折线图不对,怎么会有返回去的折线?
怎么去解决这个问题呢?
有些小伙伴又提出了。我们可以将 xAxis 的 type值设置time。
就可以解决这个问题。

在 ECharts 中,type的值是 time 和 category 的区别

1.数据类型:'time' 表示时间类型的数据,适用于连续的时序数据。
通常返回的是时间戳。我们为了方便这里写的是yyyy-mm-dd hh:mm:ss
而 'category' 表示类目类型的数据,适用于离散的类目数据。

2.显示方式:在 'time' 类型下,
ECharts 会根据时间跨度自动切换显示的时间粒度,例如从月、星期、日到小时等。
而在 'category' 类型下,坐标轴只会显示类目列表,并且坐标轴内仅包含这些指定类目的坐标。

时间格式又不对

有眼尖的小伙伴发现了一个小问题。
我们给的时间是 yyyy-mm-dd hh:mm:ss的格式
但是刚刚发现展示的是 hh:ss mm-dd
格式和我们预期的不符合

xAxis 配置项 axisLabel下的formatter 转换时间格式

通过查询echarts的文档。
我们发现 xAxis.axisLabel.formatter 可以做到对格式进行转换。
formatter:刻度标签的内容格式器,支持字符串模板和回调函数两种形式。 

对于时间轴(type: 'time'),formatter 的字符串模板支持3种形式:
1.字符串模板:简单快速实现常用日期时间模板,string 类型
2.回调函数:自定义 formatter,可以用来实现复杂高级的格式,Function 类型
3.分级模板:为不同时间粒度的标签使用不同的 formatter,object 类型
我发现使用 字符串模板 模板是不行的。分级模板没有试过。
官网推荐使用字符串模板,如果可以使用成功。
我们就不需要在写一个方法进行转化了。
但是很遗憾,失败了。可能是用的方式错误吧

字符串模板是失败的

字符串模板是失败的原因

本来我已经失望了。
结果小脑袋灵光一闪,猜测有没有可能是版本的原因。
我果断去切换到5的版本
<script src="https://cdn.staticfile.org/echarts/5.3.0/echarts.min.js"></script>
果然字符串模板显示正常了
模板字符串的详细使用地址是:https://echarts.apache.org/zh/option.html#xAxis.axisLabel.formatter

字符串模板转化时间格式【推荐】

 xAxis: {
  // xAxis的下不在设置data属性共享时间`
  type: 'time',
  splitLine: { show: false },
  lineStyle: {
    width: 2
  },
  axisTick: {
    show: false
  },
  axisLabel:{
    // 更改x轴文字颜色的配置
    textStyle: {
      color: '#717782'
    },
    // 设置坐标轴上的时间格式 --使用的是模板字符串
    // formatter: "{yyyy}-{MM}-{dd}", 得到的 label 形如:'2020-12-02'
    formatter: '{yyyy}-{MM}-{dd} \n{HH}:{mm}:{ss}',

    showMinLabel: true,
    showMaxLabel: true // 固定显示X轴的最后一条数据
  },
  // 更改x轴线的颜色
  axisLine: {
    lineStyle: {
      color: '#D2DBE6;',
      width: 1 // x轴线的宽度
    }
  },
},

使用回调函数转化时间格式

function backTime(value){
  let date = new Date(value);  
  // 获取年份、月份和日期  
  let year = date.getFullYear();  
  let month = date.getMonth() + 1; // 月份从 0 开始,需要加 1  
  let day = date.getDate();  

  let hours = date.getHours();  
  let minutes = date.getMinutes();  
  let seconds = date.getSeconds(); 
    
  // 格式化月份和日期为两位数(不足两位时补零)  
  month = month < 10 ? '0' + month : month;  
  day = day < 10 ? '0' + day : day;  

  hours = hours < 10 ? '0' + hours : hours;  
  minutes = minutes < 10 ? '0' + minutes : minutes;  
  seconds = seconds < 10 ? '0' + seconds : seconds;  
  
  // 返回格式化后的字符串  
  return year + '-' + month + '-' + day + ' ' +
         hours + ':' + minutes + ':' + seconds;
}

xAxis: {
  // xAxis的下不在设置data属性共享时间
  type: 'time',
  splitLine: { show: false },
  lineStyle: {
    width: 2
  },
  axisTick: {
    show: false
  },
  axisLabel:{
    // 更改x轴文字颜色的配置
    textStyle: {
      color: '#717782'
    },
    // 设置坐标轴上的时间格式
    formatter: function (value) {  
      console.log('时间戳',value )
      // 将时间转换为 我们需要的格式 ,这里的value是一个时间戳
      return backTime(value)
    },
    showMinLabel: true,
    showMaxLabel: true // 固定显示X轴的最后一条数据
  },
  // 更改x轴线的颜色
  axisLine: {
    lineStyle: {
      color: '#D2DBE6;',
      width: 1 // x轴线的宽度
    }
  },
},

特别提醒: type: 'time'的时候,
formatter : function (value) { }
中的value是一个时间戳

更改tooltip的时间格式

tooltip: {
  trigger: 'axis',
  formatter: (c) => {
    let str = ''
    let temp = {
      showTime: '', // 时间
      marker: '', // 颜色
      seriesName: '', // legend名称
      valueData: '', // 数值
      setWidthSpan: '',
    }
    c.forEach((item) => {
      temp.showTime = item.data[0]
      temp.marker = item.marker
      temp.seriesName = item.seriesName 
      temp.valueData = item.value[1] 
      temp.setWidthSpan = '<span style="display:inline-block;width:10px;height:10px;"></span>'
      str += temp.marker + temp.seriesName + temp.setWidthSpan + temp.valueData + '<br />'
    })
    return temp.showTime + '<br />' + str
  },
},

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>多条折线图</title>
  <script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
</head>

<body>
  <div style="width: 900px;height: 400px;"></div>
</body>
<script>

  function backTime(value){
    let date = new Date(value);  
    // 获取年份、月份和日期  
    let year = date.getFullYear();  
    let month = date.getMonth() + 1; // 月份从 0 开始,需要加 1  
    let day = date.getDate();  

    let hours = date.getHours();  
    let minutes = date.getMinutes();  
    let seconds = date.getSeconds(); 
      
    // 格式化月份和日期为两位数(不足两位时补零)  
    month = month < 10 ? '0' + month : month;  
    day = day < 10 ? '0' + day : day;  

    hours = hours < 10 ? '0' + hours : hours;  
    minutes = minutes < 10 ? '0' + minutes : minutes;  
    seconds = seconds < 10 ? '0' + seconds : seconds;  
    
    // 返回格式化后的字符串  
    return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
  }
  let myChart = echarts.init(document.querySelector('div'))
  let option = {
    // 设置的是标题
    title: {
      text: '折线图'
    },
    tooltip: {
      trigger: 'axis',
      formatter: (c) => {
        let str = ''
        let temp = {
          showTime: '', // 时间
          marker: '', // 颜色
          seriesName: '', // legend名称
          valueData: '', // 数值
          setWidthSpan: '',
        }
        c.forEach((item) => {
          temp.showTime = item.data[0]
          temp.marker = item.marker
          temp.seriesName = item.seriesName 
          temp.valueData = item.value[1] 
          temp.setWidthSpan = '<span style="display:inline-block;width:10px;height:10px;"></span>'
          str += temp.marker + temp.seriesName + temp.setWidthSpan + temp.valueData + '<br />'
        })
        return temp.showTime + '<br />' + str
      },
    },
    legend: {
      data: ['邮件', '短信']
    },
    // 网格间距设置
    grid: {
      left: '30px',
      right: '60px',
      bottom: '3%',
      containLabel: true
    },
    xAxis: {
      // xAxis的下不在设置data属性共享时间`
      type: 'time',
      splitLine: { show: false },
      lineStyle: {
        width: 2
      },
      axisTick: {
        show: false
      },
      axisLabel:{
        // 更改x轴文字颜色的配置
        textStyle: {
          color: '#717782'
        },
        // 设置坐标轴上的时间格式
        formatter: function (value) {  
          console.log('时间戳',value )
          // 将时间转换为 JavaScript 日期对象  
          return backTime(value)
        },
        showMinLabel: true,
        showMaxLabel: true // 固定显示X轴的最后一条数据
      },
      // 更改x轴线的颜色
      axisLine: {
        lineStyle: {
          color: '#D2DBE6;',
          width: 1 // x轴线的宽度
        }
      },
    },
    yAxis: {
      type: 'value'
    },
    // 数据
    series: [
      { 
        "name": "邮件", 
        "type": "line", 
        "symbol": "rect",
        "connectNulls": true,
        "showAllSymbol": true, 
        // 让每一条折线拥有数据自己的时间
        "data": [ 
          [ "2023-12-04 09:50:07", "0.137"],
          [ "2023-12-04 09:55:07", "0.147"],
          [ "2023-12-04 10:00:07", "0.137"],
          [ "2023-12-04 10:05:07", "0.163"],
          [ "2023-12-04 10:10:07", "0.150"], 
          [ "2023-12-04 10:15:07", "0.143"], 
          [ "2023-12-04 10:20:07", "0.133"],
          [ "2023-12-04 10:25:07", "0.147"], 
          [ "2023-12-04 10:30:07", "0.147"],
          [ "2023-12-04 10:35:07", "0.143"],
          [ "2023-12-04 10:40:07", "0.140"], 
          [ "2023-12-04 10:45:07", "0.150"], 
          [ "2023-12-04 10:50:07", "0.143"],
        ], 
        "unit": "%", 
        "markPoint": { 
          "symbol": "rect",
          "symbolSize": "12",
          "label": { "show": false },
          "tooltip": { "triggerOn": "click", "trigger": "item" }, 
        }
      },
      { 
        "name": "短信", 
        "type": "line", 
        "symbol": "rect", 
        "connectNulls": true, 
        "showAllSymbol": true, 
          "data": [ 
            [ "2023-12-04 09:50:07", "0.8"],
            [ "2023-12-04 09:52:07", "1.23"],
            [ "2023-12-04 10:41:07", "0.140"], 
            [ "2023-12-04 10:42:07", "0.140"], 
            [ "2023-12-04 10:45:07", "0.140"], 
            [ "2023-12-04 10:49:07", "0.150"], 
            [ "2023-12-04 10:50:07", "0.143"],
          ], 
          "unit": "%", 
          "markPoint": { 
            "symbol": "circle",
            "symbolSize": "12", 
            "label": { "show": false } 
          } 
      } 
    ]
  };
  myChart.setOption(option);
</script>
</html>