ECharts中线性图添加图表标线和图表标点以标记最大值和最小值

发布于:2024-12-20 ⋅ 阅读:(14) ⋅ 点赞:(0)

        在ECharts中,可以通过series中的markLine和markPoint属性来分别设置图表的标线和标点。在下面的例子中,markLine用于添加一个标记最大值的标线,而markPoint用于添加标记最大值和最小值的标记点。

        可以根据需要调整markLine和markPoint的data属性,以设置不同的标记类型和名称。

一、测试数据

        以下为此次演示案例的测试数据,代码如下:

[
  {
    "name": "负荷曲线",
    "data": [
      {
        "name": "1:00",
        "value": 14
      },
      {
        "name": "2:00",
        "value": 10
      },
      {
        "name": "3:00",
        "value": 14
      },
      {
        "name": "4:00",
        "value": 12
      },
      {
        "name": "5:00",
        "value": 1
      },
      {
        "name": "6:00",
        "value": 15
      },
      {
        "name": "7:00",
        "value": 11
      },
      {
        "name": "8:00",
        "value": 12
      },
      {
        "name": "9:00",
        "value": 6
      },
      {
        "name": "10:00",
        "value": 1
      },
      {
        "name": "11:00",
        "value": 15
      },
      {
        "name": "12:00",
        "value": 4
      },
      {
        "name": "13:00",
        "value": 924
      },
      {
        "name": "14:00",
        "value": 178
      },
      {
        "name": "15:00",
        "value": 197
      },
      {
        "name": "16:00",
        "value": 345
      },
      {
        "name": "17:00",
        "value": 646
      },
      {
        "name": "18:00",
        "value": 731
      },
      {
        "name": "19:00",
        "value": 780
      },
      {
        "name": "20:00",
        "value": 193
      },
      {
        "name": "21:00",
        "value": 278
      },
      {
        "name": "22:00",
        "value": 318
      },
      {
        "name": "23:00",
        "value": 179
      },
      {
        "name": "24:00",
        "value": 862
      }
    ]
  },
  {
    "name": "预测负荷",
    "data": [
      {
        "name": "1:00",
        "value": 9
      },
      {
        "name": "2:00",
        "value": 13
      },
      {
        "name": "3:00",
        "value": 13
      },
      {
        "name": "4:00",
        "value": 2
      },
      {
        "name": "5:00",
        "value": 8
      },
      {
        "name": "6:00",
        "value": 18
      },
      {
        "name": "7:00",
        "value": 10
      },
      {
        "name": "8:00",
        "value": 19
      },
      {
        "name": "9:00",
        "value": 6
      },
      {
        "name": "10:00",
        "value": 20
      },
      {
        "name": "11:00",
        "value": 4
      },
      {
        "name": "12:00",
        "value": 2
      },
      {
        "name": "13:00",
        "value": 949
      },
      {
        "name": "14:00",
        "value": 477
      },
      {
        "name": "15:00",
        "value": 144
      },
      {
        "name": "16:00",
        "value": 363
      },
      {
        "name": "17:00",
        "value": 213
      },
      {
        "name": "18:00",
        "value": 660
      },
      {
        "name": "19:00",
        "value": 923
      },
      {
        "name": "20:00",
        "value": 812
      },
      {
        "name": "21:00",
        "value": 720
      },
      {
        "name": "22:00",
        "value": 90
      },
      {
        "name": "23:00",
        "value": 994
      },
      {
        "name": "24:00",
        "value": 597
      }
    ]
  }
]

二、绘制图表

        这里直接使用EChart的官方实例进行案例演示了,将基础折线图修改为我们需要的效果。测试地址:Examples - Apache ECharts

        配置项代码如下:

const data = [
  {
    "name": "负荷曲线",
    "data": [
      {
        "name": "1:00",
        "value": 14
      },
      {
        "name": "2:00",
        "value": 10
      },
      {
        "name": "3:00",
        "value": 14
      },
      {
        "name": "4:00",
        "value": 12
      },
      {
        "name": "5:00",
        "value": 1
      },
      {
        "name": "6:00",
        "value": 15
      },

      // 略...

    ]
  },
  {
    "name": "预测负荷",
    "data": [
      // 略...
    ]
  }
]

const seriesData = data.map(item => {
  return {
    data: item.data.map(item => item.value),
    type: 'line',
    smooth: true,
    name: item.name
  }
})

option = {
  legend: {},
  dataZoom: {
    type: 'inside',
    show: true,
    start: 0,
    end: 60
  },
  xAxis: {
    type: 'category',
    data: data[0].data.map(item => item.name),
    splitNumber: 6
  },
  yAxis: {
    type: 'value'
  },
  series: seriesData
};

        查看图表效果,如下图:

三、最大值标记线

        通过MarkLine标记出图例的最大值标记线,通过extraData变量额外追加到图例中,其作用后续再说。配置项代码如下:

// 略...

const seriesData = data.map(item => {
  const extraData = {
    markLine: {
      data: [
        // 最大值标记线
        {name: 'Max', type: 'max'}
      ]
    }
  }
  return {
    data: item.data.map(item => item.value),
    type: 'line',
    smooth: true,
    name: item.name,
    ...extraData
  }
})

option = {
  legend: {},
  dataZoom: {
    type: 'inside',
    show: true,
    start: 0,
    end: 60
  },
  xAxis: {
    type: 'category',
    data: data[0].data.map(item => item.name),
    splitNumber: 6
  },
  yAxis: {
    type: 'value'
  },
  series: seriesData
};

        图表效果如下图:

四、标记最大和最小值

        通过markPoint属性配置出图例中的最大值和最小值,同样写在extraData变量中。配置项代码如下:

// 略...

const seriesData = data.map(item => {
  const extraData = {
    markLine: {
      data: [
        {name: 'Max', type: 'max'}
      ]
    },
    // 最大值和最小值 标记点
    markPoint: {
      data: [
        {name: 'Min', type: 'min'},
        {name: 'Max', type: 'max'}
      ]
    }
  }
  return {
    data: item.data.map(item => item.value),
    type: 'line',
    smooth: true,
    name: item.name,
    ...extraData
  }
})

option = {
  legend: {},
  dataZoom: {
    type: 'inside',
    show: true,
    start: 0,
    end: 60
  },
  xAxis: {
    type: 'category',
    data: data[0].data.map(item => item.name),
    splitNumber: 6
  },
  yAxis: {
    type: 'value'
  },
  series: seriesData
};

        图表效果如下图:

        如上图,对于有些项目到这一步则已完成了,但是有些可能还希望看到的是,多个图列只显示一个最大值和一个最小值,这个则需要通过函数来查询出最大值或最小值分别 在哪个图例中,并且得到结果后通过索引来判定,哪个图例需要添加markPoint或markLine属性。

五、legend监听事件

        在ECharts中,legend图例可能会发生变化(显示/隐藏)。它的变化可以通过监听legendselectchanged事件来捕获,这个事件会在用户切换图例(legend)的选中状态时触发。

        监听事件代码如下:

myChart.on('legendselectchanged', (e) => {
  console.log('legendselectchanged', e)
})

        此时,切换图例legend时,控制台输出结果如下图:

        从图中可以看出,当图例(legend)显示或隐藏时,是通过true或false来标记的。所以,我们切换图例时,可以通过selected内图例名称对应的true或false来判定显示的图例数据,并且通过它筛选出来的数据,判断最大值和最小值所在图例的索引。

六、最大值和最小值查询

        定义getMaxAndMinValue()函数,用于查询每个图例中的最大值和最小值,代码如下:

// 获取最大和最小值
const getMaxAndMinValue = (arr) => {
  let maxValue = 0
  let minValue = 0
  // 循环获取最大和最小值
  arr.forEach(item => {
    if (item.value) minValue = item.value
    if (item.value > maxValue) maxValue = item.value
  })
  return {
    maxValue,
    minValue
  }
}
// 监听图例事件
myChart.on('legendselectchanged', (e) => {
  const chartData = data.filter(item => e.selected[item.name]) // 筛选数据
  chartData.forEach(item => {
    const { maxValue, minValue } = getMaxAndMinValue(item.data)
    console.log(maxValue, minValue)
  })
  console.log('legendselectchanged', chartData)
})

        此时,切换图例(legend)查看控制台,如下图:

七、判断最大值和最小值所在图例

        上面已经将最大值和最小值查询出来了,现在我们需要将功能函数再修改下,判断出最大值和最小值所在的图例索引。

        新增getMaxAndMinIndex()函数,用来获取最大值和最小值所在图例的索引,代码如下:

let maxIndex = 0
let minIndex = 0
// 获取最大和最小值
const getMaxAndMinValue = (arr) => {
  let maxValue = 0
  let minValue = 0
  // 循环获取最大和最小值
  arr.forEach(item => {
    if (item.value) minValue = item.value
    if (item.value > maxValue) maxValue = item.value
  })
  return {
    maxValue,
    minValue
  }
}
// 判断最大值和最小值所在的图例
const getMaxAndMinIndex = (arr) => {
  let max = 0
  let min = 0
  // 获取最大值和最小值索引
  arr.forEach((item, index) => {
    const { maxValue, minValue } = getMaxAndMinValue(item.data)
    if (minValue < min) {
      min = minValue
      minIndex = index
    }
    if (maxValue > max) {
      max = maxValue
      maxIndex = index
    }
  })
  console.log(maxIndex, minIndex)
}
// 监听图例事件
myChart.on('legendselectchanged', (e) => {
  const chartData = data.filter(item => e.selected[item.name]) // 筛选数据
  getMaxAndMinIndex(chartData) // 查询索引
  myChart.setOption(chartOptions(chartData))
})

        查看控制台,可以看到在图例切换后,索引也跟着发生变化。

        此时,页面始终显示一个最大值和一个最小值了,如下图:

        当预测负荷隐藏后,则会显示负荷曲线的最大值数据,如下图:

八、完成代码

        以下为配置项,以及图例监听事件的完整代码。代码如下:

const data = [
  {
    "name": "负荷曲线",
    "data": [
      {
        "name": "1:00",
        "value": 14
      },
      {
        "name": "2:00",
        "value": 10
      },
      {
        "name": "3:00",
        "value": 14
      },
      {
        "name": "4:00",
        "value": 12
      },
      {
        "name": "5:00",
        "value": 1
      },
      {
        "name": "6:00",
        "value": 15
      },
      {
        "name": "7:00",
        "value": 11
      },
      {
        "name": "8:00",
        "value": 12
      },
      {
        "name": "9:00",
        "value": 6
      },
      {
        "name": "10:00",
        "value": 1
      },
      {
        "name": "11:00",
        "value": 15
      },
      {
        "name": "12:00",
        "value": 4
      },
      {
        "name": "13:00",
        "value": 924
      },
      {
        "name": "14:00",
        "value": 178
      },
      {
        "name": "15:00",
        "value": 197
      },
      {
        "name": "16:00",
        "value": 345
      },
      {
        "name": "17:00",
        "value": 646
      },
      {
        "name": "18:00",
        "value": 731
      },
      {
        "name": "19:00",
        "value": 780
      },
      {
        "name": "20:00",
        "value": 193
      },
      {
        "name": "21:00",
        "value": 278
      },
      {
        "name": "22:00",
        "value": 318
      },
      {
        "name": "23:00",
        "value": 179
      },
      {
        "name": "24:00",
        "value": 862
      }
    ]
  },
  {
    "name": "预测负荷",
    "data": [
      {
        "name": "1:00",
        "value": 9
      },
      {
        "name": "2:00",
        "value": 13
      },
      {
        "name": "3:00",
        "value": 13
      },
      {
        "name": "4:00",
        "value": 2
      },
      {
        "name": "5:00",
        "value": 8
      },
      {
        "name": "6:00",
        "value": 18
      },
      {
        "name": "7:00",
        "value": 10
      },
      {
        "name": "8:00",
        "value": 19
      },
      {
        "name": "9:00",
        "value": 6
      },
      {
        "name": "10:00",
        "value": 20
      },
      {
        "name": "11:00",
        "value": 4
      },
      {
        "name": "12:00",
        "value": 2
      },
      {
        "name": "13:00",
        "value": 949
      },
      {
        "name": "14:00",
        "value": 477
      },
      {
        "name": "15:00",
        "value": 144
      },
      {
        "name": "16:00",
        "value": 363
      },
      {
        "name": "17:00",
        "value": 213
      },
      {
        "name": "18:00",
        "value": 660
      },
      {
        "name": "19:00",
        "value": 923
      },
      {
        "name": "20:00",
        "value": 812
      },
      {
        "name": "21:00",
        "value": 720
      },
      {
        "name": "22:00",
        "value": 90
      },
      {
        "name": "23:00",
        "value": 994
      },
      {
        "name": "24:00",
        "value": 597
      }
    ]
  }
]
let maxIndex = 0
let minIndex = 0
// 获取最大和最小值
const getMaxAndMinValue = (arr) => {
  let maxValue = 0
  let minValue = 0
  // 循环获取最大和最小值
  arr.forEach(item => {
    if (item.value) minValue = item.value
    if (item.value > maxValue) maxValue = item.value
  })
  return {
    maxValue,
    minValue
  }
}
// 判断最大值和最小值所在的图例
const getMaxAndMinIndex = (arr) => {
  let max = 0
  let min = 0
  // 获取最大值和最小值索引
  arr.forEach((item, index) => {
    const { maxValue, minValue } = getMaxAndMinValue(item.data)
    if (minValue < min) {
      min = minValue
      minIndex = index
    }
    if (maxValue > max) {
      max = maxValue
      maxIndex = index
    }
  })

}
// 获取配置项参数
function chartOptions(chartData) {
  const seriesData = chartData.map((item, index) => {
    const extraData = {
      markLine: {
        data: []
      },
      markPoint: {
        data: []
      }
    }
    // 通过索引判断该图例中是否有最大值
    if (maxIndex == index) {
      extraData.markLine.data.push({name: 'Max', type: 'max'})
      extraData.markPoint.data.push({name: 'Max', type: 'max'})
    }
    if (minIndex == index) {
      extraData.markPoint.data.push({name: 'Min', type: 'min'})
    }
    return {
      data: item.data.map(item => item.value),
      type: 'line',
      smooth: true,
      name: item.name,
      ...extraData
    }
  })
  return {
    legend: {},
    dataZoom: {
      type: 'inside',
      show: true,
      start: 0,
      end: 60
    },
    xAxis: {
      type: 'category',
      data: chartData.length > 0 ? chartData[0].data.map(item => item.name) : [],
      splitNumber: 6
    },
    yAxis: {
      type: 'value'
    },
    series: seriesData
  }
}
getMaxAndMinIndex(data)
// 配置项
option = chartOptions(data);

// 监听图例事件
myChart.on('legendselectchanged', (e) => {
  const chartData = data.filter(item => e.selected[item.name]) // 筛选数据
  getMaxAndMinIndex(chartData) // 查询索引
  myChart.setOption(chartOptions(chartData))
})

       从完整代码中可见,chartOptions函数中之所以单独定义extraData变量,是方便通过索引来定位哪项数据中存在最大值或最小值,来动态绑定对应的markPoint或marLine属性。

        此篇就先讲到这了,希望对大家有所帮助~


网站公告

今日签到

点亮在社区的每一天
去签到