在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属性。
此篇就先讲到这了,希望对大家有所帮助~