前言
上一篇文章分享了自动轮播的简单版实现,对于大多数图表来说已经可以满足功能需求,但是总有一小部分的图表需求比较突出,比如双y轴图表。
有句老话说:简单的问题总是不多,而困难的问题总是接踵而来。其实单以自动轮播的功能需求来说,简单版的实现在双y轴图标上也可以使用,但是当牵扯到另一个功能的时候,就很难满足要求了,这个功能就是图例点击。
当自动轮播和图例点击功能双双向你奔来的时候,脑壳真的是疼的要命。而且双y轴双数据(一条y轴对应一条数据)还是比较简单的,可怕的是双y轴多数据(一条y轴对应多条数据)。这一次,我们分享的内容就是—双y轴图例点击+自动轮播进阶版
功能分析
多y轴多数据的情况下,有几个难点需要克服:
- 轮播提示框内容动态渲染问题
- series中的数据有些不需要轮播,如饼图中因为效果实现而插入的空格数据
- 剩一个y轴的时候,y轴位置重置问题
- y轴对应多数据时,图例点击之后轮播数据提示问题
图例点击
echarts图表库的图例点击功能是有默认效果的,不过也是针对于普通单y轴图表足以使用,多y轴图表的话效果也有,但是有一些缺点:
- 仅隐藏对应y轴刻度值,不会隐藏y轴轴线
- 不会隐藏y轴单位文字
- 轮播难以实现
所以,要想达到我们的要求,默认效果是远远不能够的,需要我们对图例点击事件进行自定义处理,这就需要用到图例点击事件legendselectchanged。简单使用如下:
myChart.on("legendselectchanged", function (params) {
// xxx
})
自动轮播进阶
进阶版的实现其实和简单版的原理一样,只是对于数据的处理有修改和优化。针对于最开始我们提出的问题,在轮播时候要做特殊处理
- 对于饼图中有不需要轮播的数据,可以将轮播数据的seriesIndex永久设置为0(简单版已实现,但根据情况也要有微调)
- 对于多y轴情况,需要动态设定定时器循环所依赖的数据项
- 提示框内容针对要求,对数据进行循环拼接
功能实现
实现的原理就是图例点击时对图表的数据进行重置,重新生成图表。
图例点击
为了适应情况,需要对图表数据的生成封装成一个方法。
图例点击后隐藏了对应的y轴,所以我们在自定义事件里需要动态的填充y轴(yAxis)的数据,同时因为缺失对应的y轴,所以需要把被隐藏y轴对应的数据data置为空。
myChart.on("legendselectchanged", function (params) {
// 得到当前的图例显示隐藏状态分别有哪些
SelectedData = params.selected;
Init(SelectedData, DataInfo);
if (option && typeof option === "object") {
myChart.setOption(option, true);
}
})
params的内容是图例相关的对象,内容有当前图例名称和所有图例的选中状态以及事件类型
let SelectedData = {}, //图例选择的数据
LengData =[], // legend属性data
YaData=[], // yAxis
SeriesData=[], // series
DataInfo=[], // series属性的data
option={}; // option
function Init(sel, dataInfo) {
SelectedData = sel || {};
YaData = [], SeriesData = [];
for (let n = 0, l = LengData.length; n < l; n++) {
// 如果该图例状态为true时,则填入yAxis中
if (sel[LengData[n]]) {
YaData.push({
// xxx
})
} else {
// 将未填入的y轴对应的series-data置为空数组
Datas[n].data = [];
}
// 多y轴多数据时的对应关系,视情况而定,
Datas[n].yAxisIndex = YaData.length - 1 < 0 ? 0 : YaData.length - 1;
SeriesData.push(Datas[n]);
}
// 都隐藏时候的,保证图表正常显示
if (YaData.length == 0) {
YaData = [{ type: 'value' }];
}
// xxx
}
以上Init方法的实现限于篇幅原因,仅有重点内容,完整内容会在整理后重新把地址编辑上去。
自动轮播进阶
由于点击不同的图例,所对应的数据seriesIndex不一定为0,需要动态设置。那么从哪里获取这个依据呢?还记得图例点击事件中我们获取到的选中状态数组吗?从里面获取第一个为true的位置就可以满足我们的要求。
SelectedData = params.selected;
let serIndex = 0; // 动态获取的数据所在位置
Object.values(SelectedData).forEach((item,index)=>{
if(item){
serIndex = index;
}
})
对应的定时器中的修改
// 数据高亮
myChart.dispatchAction({
type: 'highlight',
seriesIndex: seriesIndex,
dataIndex: dataIndex,
});
myChart.dispatchAction({
type: "showTip",
seriesIndex: seriesIndex,
dataIndex: dataIndex,
});
提示框的动态渲染
formatter(params) {
let result = '';
if(params.length > 0){
// x轴数据名称,如xxx年
result +=`<div style="font-size:18px;">${params[0].axisValue}:</div>`
// 数据数值
params.forEach(item=>{
result += `<div style="line-height:20px">${item.value}</div>`
})
}
return result;
},