最近在做公司的数据大盘,要用到图表显示,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)合并,这样会乱了之前的状态。你需要额外一个变量

metaKey来记录你是不是之前用过command键。处理完了,记得把metaKey=false;
 
    好吧,我觉得我说的有点乱,我准备有空了话了流程图。下面先上代码了,实在是太忙了,马上接着搬砖!!!能看懂代码就直接看代码吧:
 
 
  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. this.metaKey = false;
  89. return true;
  90. }
  91. };
  92.  
  93. if (!this.myChart) {
  94. this.myChart = echarts.init(document.getElementById(id));
  95. this
  96. .myChart
  97. .on('legendselectchanged', (obj) => {
  98. this.selected = obj.selected;
  99. // 使用 legendToggleSelect Action 会重新触发 legendselectchanged Event,导致本函数重复运行 使得 无
  100. // selected 对象
  101. if (this.selected !== undefined) {
  102. if (!window.event.metaKey && isFirstUnSelect(this.selected)) {
  103. triggerAction('legendToggleSelect', this.selected);
  104. } else {
  105. if (!this.preSelect) {
  106. this.preSelect = {};
  107. }
  108. this.metaKey = true;
  109. savePreSelected(this.selected);
  110. }
  111. }
  112. });
  113. }

如何自定义echarts 线性图的选择事件的更多相关文章

  1. echarts雷达图点击事件

    最近看见别人问的问题,点击雷达图的拐点,获取点击数据的问题,直接上代码. echarts配置问题:https://www.douban.com/note/509404582/ <!doctype ...

  2. echarts雷达图点击事件 包含(2.x,3.85,4.02)测试

    最近看见别人问的问题,点击雷达图的拐点,获取点击数据的问题,直接上代码. echarts 2x 的点击事件 echarts配置问题:https://www.douban.com/note/509404 ...

  3. nw.js自定义最小化图标的click事件

    选择frameless时,最小化和关闭按钮的点击事件需要自己来做,办法是: /* * 下面两个模块一定要引入到js文件中 */ var gui = require('nw.gui'); var win ...

  4. Echarts折线图点击事件

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  5. echarts异步数据加载(在下拉框选择事件中异步更新数据)

    接触echarts 大半年了,从不会到熟练也做过不少的图表,隔了一段时间没使用这玩意,好多东西真心容易忘了.在接触echarts这期间也没有总结什么东西,今天我就来总结一下如何在echart中异步加载 ...

  6. echarts柱图自定义为硬币堆叠的形式

    看这标题,可能会有一些人不太明白,那么直接上图,就是柱图展示形式如下图(兼容IE8) 要想实现这样展示效果.我们想用echarts直接实现不行的,即使是纹理填充也不可行的,但是我们可以借助echart ...

  7. 用echartsjs 实现散点图与table表格双向交互,以及实现echarts取自于table数据,和自定义echarts提示内容

    本人研究echarts已经有一段时间了,今天就分享几个关于echarts的小技巧.虽然看起来简单,但做起来却很繁琐,不过实用性倒是很好. 在一个大的页面中,左边为table表格,右边为echarts的 ...

  8. 如何自定义echarts主题

    上一篇,选择echarts原有的主题样式,那么如何自定义自己的主题 与选择原有主题类似 1.echarts官网地址http://echarts.baidu.com/echarts2/doc  在工具中 ...

  9. Dotfuscator自定义规则中的元素选择

    Dotfuscator是专业的.NET程序代码保护软件.是支持规则自定义的,你可以对重命名.程序控制流.字符串加密等等功能自定义规则.在进行规则自定义过程中,可以通过元素的不同选择,满足自己的程序需要 ...

随机推荐

  1. awk向脚本传递參数(二)

    命令行參数的一个重要限制是它们在BEGIN过程中是不可用的. 也就是说,直到首行输入完毕以后它们才可用.为什么?这是一个easy混乱的部分.从命令行传递的參数就好像文件名称一样被处理.赋值操作知道这个 ...

  2. 面试题思考:什么是 Java 的反射机制

    一.反射机制概述 Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法.这种在运行时动态的获取信息以及动态调用对象的方法 ...

  3. springboot2.1.1 中集成websocket 单元测试异常

    单元测试在没有集成websocket之前是好好的,当集成websocket之后就出现了下面的异常(只贴出来关键信息): 2019-01-11 10:05:42 [ERROR] [org.springf ...

  4. 《从零开始学Swift》学习笔记(Day60)——Core Foundation框架

    原创文章,欢迎转载.转载请注明:关东升的博客 Core Foundation框架是苹果公司提供一套概念来源于Foundation框架,编程接口面向C语言风格的API.虽然在Swift中调用这种C语言风 ...

  5. HDU 5157 Harry and magic string(回文树)

    Harry and magic string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  6. sql---字段类型转换,sql获取当前时间

    一.字段类型转换 convert(要转换成的数据类型,字段名称)例如 convert(varchar(100),col_name)Convert(int,Order_no) 二.sql获取当前时间 s ...

  7. Linux网络配置:设置IP地址、网关DNS、主机名

    查看网络信息 1.ifconfig eth0 2.ifconfig -a 3.ip add 设置主机名需改配置文件: /etc/hosts /etc/sysconfig/network vim /et ...

  8. django 表单系统 之 forms.Form

    继承forms.Form实现django表单系统 参考: https://www.cnblogs.com/zongfa/p/7709639.html https://www.cnblogs.com/c ...

  9. web 开发常见问题--Session 与 Cookie 却别

    总结: 1.首先,session与cookie都是保存数据的,存在的原因很大程度上是为了解决HTTP协议的无状态特性 2.都是保存数据,却别在于cookie保存在客户端,由浏览器管理,session保 ...

  10. linux c编程:Posix信号量

    POSIX信号量接口,意在解决XSI信号量接口的几个不足之处: POSIX信号量接口相比于XSI信号量接口,允许更高性能的实现. POSIX信号量接口简单易用:没有信号量集,其中一些接口模仿了我们熟悉 ...