最近在做公司的数据大盘,要用到图表显示,echarts研二的时候有用过,我就决定用它了。
这里用到一个可以同时显示多条曲线的line-charts,基本样子如下:
看到这个画红色圈圈的地方了吗??? 正常来讲,有色调的就是激活状态,没色调的就是未激活状态,ok,我觉得很不错,完全满足需求。可是需求方以前用过别人写的数据大盘,用的图表框架不一样,他们的操作有点“另类”:
(1)一开始初始化,全部都是选中的(和我们的echarts)一毛一样!假如说有3个按钮,btn1,btn2和btn3.初始化的时候,全是激活状态。
(2)随便点击哪个,假如说点了btn1, 其他的都变成非选中,即btn2,btn3都变灰(尼玛。。。。),
(3)再点击btn1,又全选!!! 点击别的,比如说,点击btn2,则btn1和btn3都变灰。
ok!!,那怎么多选呢???,请按 command+点击,实现多选,松开command,单纯的点击又像步骤(2)一样。
这个需求拿到,我就尴尬了,不过我不能留下没技术的眼泪,决定想一想,实现这样的功能需要哪些知识!!!
(1)组合键操作
(2)监听选择改变事件(echarts已经自带了!!问题是回调函数的参数不是event,而是包装了一层的数据!!)
(3)event去哪里拿?为什么要event?因为我要监听组合键啊!!!我要metaKey啊,别急!!!window上是挂着的。
好了,有了以上知识,我们就可以设计如何将echarts的选择事件改成我们要的了。
这事情其实也不是很简单!!!但是理清楚流程就ok了!!!
(1)先从最简单的开始,一开始初始化的时候,是全选的,然后点击任意一个,除了这个被点击的btn,其他的都变灰。记住,这时候我们还没有按command。 怎么写????
ok,本来btn1,btn2,btn3都是选中状态,你点击btn1,btn1肯定变成灰色了,即btn1未激活,btn2,btn3都是激活的,但是你的目标是反过来!!!echats有个“legendToggleSelect”事件,那你把所有的现在的状态,都反转一遍就是你要的了!!!!
(2)当你再次点击的时候,记住你已经不是第一次点击了!!如果还是点击btn1,又变成全选,怎么写???
仔细想想,本来就一个btn1是激活的,你再点一下,就全是未激活的了,但是你的目标是全激活???好!!!就判断是不是全部未激活的!是的话继续反转!!!然后就变成了(1)的状态了!!
(3)如果(2)中 当你再次点击的不是btn1,而是点击btn2,又变成btn2激活,btn1和btn3未激活,怎么写???
思考一会,你会发现,这种情况相比前一个状态,永远只会改变一个地方!!什么意思??本来你btn1激活,btn2,btn3未激活,下载你点击btn2,那是不是,btn1和btn2都激活了,就btn3未激活!!
也就是改变了btn2而已!!!发现这个规律,我们就把前一次状态和当前状态比较,相同的全部变灰!!!不相同的取反。所以你需要一个变量preSelect来存储上一个状态。
-------------------------------------------以上都是没有加command---------------------
-------------------------------------------以下开始加command---------------------
(1)如果你加了command,可以实现多选,那其实就是利用echarts本身的方法,那你其实什么都不用做,使用默认行为就行!!!
(2)假如你利用command多选了btn1和btn2,现在你松开command,要点击btn3,你希望,btn3激活,btn1和btn2都是未激活,怎么办???
其实这里也是用了上面(3)中的preSelect状态,去比较,因为这样的情况和上一个状态比,只会改变一个状态,但你不能把代码和上面的(1)、(2)、(3)合并,这样会乱了之前的状态。你需要额外一个变量
1 const savePreSelected = (selected) => { 2 if (!this.isFirst) { 3 this.isFirst = true; 4 } 5 for (name in selected) { 6 if (!selected.hasOwnProperty(name)) { 7 continue; 8 } 9 10 this.preSelect[name] = selected[name]; 11 } 12 }; 13 14 const isFirstUnSelect = (selected) => { 15 if (!this.isFirst) { 16 this.isFirst = true; 17 18 this.preSelect = cloneObj(selected); 19 20 for (name in selected) { 21 if (!selected.hasOwnProperty(name)) { 22 continue; 23 } 24 25 this.preSelect[name] = !selected[name]; 26 } 27 return true; 28 } else if (!this.metaKey) { 29 let totalTrue = 0; 30 const newObj = {}; 31 for (name in selected) { 32 if (!selected.hasOwnProperty(name)) { 33 continue; 34 } 35 36 if (selected[name] === true) { 37 totalTrue++; 38 } 39 } 40 41 if (totalTrue === 2) { 42 for (name in selected) { 43 if (!selected.hasOwnProperty(name)) { 44 continue; 45 } 46 if (this.preSelect[name] === true) { 47 newObj[name] = true; 48 this.preSelect[name] = false; 49 } else if (this.preSelect[name] !== selected[name]) { 50 this.preSelect[name] = selected[name]; 51 } 52 } 53 this.selected = newObj; 54 } else if (totalTrue === 0) { 55 for (name in selected) { 56 if (!selected.hasOwnProperty(name)) { 57 continue; 58 } 59 60 selected[name] = false; 61 this.preSelect[name] = !selected[name]; 62 } 63 64 this.isFirst = false; 65 } 66 return true; 67 } else if (this.metaKey) { 68 const newObj = {}; 69 for (name in selected) { 70 if (!selected.hasOwnProperty(name)) { 71 continue; 72 } 73 74 if (this.preSelect[name] === selected[name]) { 75 if (this.preSelect[name] === true) { 76 newObj[name] = true; 77 } 78 this.preSelect[name] = false; 79 } else if (this.preSelect[name] !== selected[name] && selected[name] === false) { 80 newObj[name] = true; 81 this.preSelect[name] = true; 82 } else if (this.preSelect[name] !== selected[name] && selected[name] === true) { 83 this.preSelect[name] = true; 84 } 85 } 86 this.selected = newObj; 87 88 89 this.metaKey = false; 90 return true; 91 } 92 }; 93 94 95 if (!this.myChart) { 96 this.myChart = echarts.init(document.getElementById(id)); 97 this 98 .myChart 99 .on('legendselectchanged', (obj) => { 100 this.selected = obj.selected; 101 // 使用 legendToggleSelect Action 会重新触发 legendselectchanged Event,导致本函数重复运行 使得 无 102 // selected 对象 103 if (this.selected !== undefined) { 104 if (!window.event.metaKey && isFirstUnSelect(this.selected)) { 105 triggerAction('legendToggleSelect', this.selected); 106 } else { 107 if (!this.preSelect) { 108 this.preSelect = {}; 109 } 110 this.metaKey = true; 111 savePreSelected(this.selected); 112 } 113 } 114 }); 115 }