欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(1)Echarts图表绑定特殊事件

程序员文章站 2022-05-24 20:38:46
...

前言:Echarts插件是基于canvas画布而构建的一个图表库,每一个图表由一个或者多个canvas画布构成,大多数时候都由一个canvas构成,图表内部不同组件和图形可以分属于不同的层级,类似于html的z-index属性的功能。不同的层级组件在刷新的时候,有性能的差异。而事件的捕捉和监听,与html存在本质的不同,dom事件的那一套处理规则,在Echarts插件内部并没有具体的元素去支撑,这与基于svg技术的d3和highcharts图表存在本质不同,也可以说是canvas图表库的天然缺陷。

Echarts事件处理原理:Echarts事件的监听和响应,是由底层的zrender库来模拟和封装的。封装后,接口的调用和使用,跟dom元素的事件接口的使用方法类似。具体的实现原理:监听事件的发生坐标(如鼠标点击或者悬浮时候的坐标),判断在哪个绘制元素的范围中,如果在某个元素包含的范围中,该元素就可以监听该事件,执行与该事件相关的事件处理逻辑。具体的解释可参考:HTML5 Canvas绘制的图形的事件处理。Echarts内部每一个类都有一个getBoundingRect方法,该方法会返回与这个类相关的矩形信息。该矩形对应这个元素在图表上的包含范围。如图1所示,当点击y轴的时候,Echarts内部会判断,鼠标的点击位置是否在y轴组件的矩形框包含的范围内。
(1)Echarts图表绑定特殊事件

Echarts初始化事件的总函数:该函数是echartsProto原型下_initEvents的函数,这个函数处理和逻辑,决定我们在内部编写的自定义事件,能不能正常执行和响应。这个坑是我当初花了很多时间才发现的。如下代码段是它的源码。从源码中,不知大家有木有发现params参数的秘密:params若为空,则无法触发事件。而只有el && el.dataIndex和
el && el.eventData这两种情况下,params才不为空,事件才能正常监听。故要监听某图表元素绑定的事件,一定要满足上面两个条件,或者传递某个参数,然后根据参数在_initEvents函数内部做处理,如代码2所示,通过在el元素添加eventData属性,然后在_initEvents函数中添加代码2所示的代码,即可实现。

代码1:
echartsProto._initEvents = function () {
       each(MOUSE_EVENT_NAMES, function (eveName) {
            this._zr.on(eveName, function (e) {
                var ecModel = this.getModel();
                var el = e.target;
                var params;

                // no e.target when 'globalout'.
                if (eveName === 'globalout') {
                    params = {};
                }
                else if (el && el.dataIndex != null) {
                    var dataModel = el.dataModel || ecModel.getSeriesByIndex(el.seriesIndex);
                    params = dataModel && dataModel.getDataParams(el.dataIndex, el.dataType) || {};
                }
                // If element has custom eventData of components
                else if (el && el.eventData) {
                    params = zrUtil.extend({}, el.eventData);
                }                                               
                if (params) {
                    params.event = e;
                    params.type = eveName;
                    this.trigger(eveName, params);
                }

            }, this);
        }, this);

        each(eventActionMap, function (actionType, eventType) {
            this._messageCenter.on(eventType, function (event) {
                this.trigger(eventType, event);
            }, this);
        }, this);
    };

    代码2if (eveName === 'contextmenu') {                       
            if (el && el.eventData && el.eventData.selectMode) {
                e.event.preventDefault();
                e.event.stopPropagation();
                params = zrUtil.extend(params, el.eventData);
            } else {
                params = null;
            }
        }               

option配置项的配置
此外,我们在源码中绑定的自定义事件,要生效还需要修改两个配置项属性,一个是silent属性:当它为true的时候,会禁止所有的事件响应,为false的时候,响应事件。triggerEvent属性: 为true的 时候,响应事件。这两个配置项,silent属性每一个图表元素都具有;triggerEvent则是组件和图形元素才有。