d3可视化实战04:事件绑定机制

首先说明,d3支持全部的JS事件——甚至其余代码的自定义事件。这里有一个列表,The MDN Event Reference, 包含了几乎全部浏览器建立的事件类型。你们有须要能够去查看。node

D3的事件绑定的语法,与jquery等其余类库用起来区别不大,都是object.on( event, listener )的形式。可是在具体实践中,咱们常常会遇到给同一个对象绑定多个事件监听器的问题。这里就原生js、jquery和d3分别进行讨论。jquery

一.原生JS的事件绑定

在探讨这个问题以前,咱们首先须要看一下原生js事件绑定机制的实现方法。原生js典型方法就是使用onclick属性来进行事件绑定。但当同一个对象使用.onclick的写法触发多个方法的时候,后一个方法会把前一个方法覆盖掉,也就是说,在对象的onclick事件发生时,只会执行最后绑定的方法。因此下面这个例子,能够想到最后的结果只能弹出一个alert对话框。git

在原生JS中,对词问题的解决方法是使用事件监听器对象来处理事件响应。下面这段代码展现了事件监听器的用法,这下能够弹出两个对话框了。程序员

固然,能绑定就能解除绑定,方法以下:angularjs

————————————————————————————————–github

二.d3的事件绑定机制

一样的,在使用d3进行事件绑定的时候,也会遇到相似的问题。若是直接进行绑定,那么后果是同样的,后面的方法会覆盖掉前面的方法。例如在下面的例子中,只有第二个函数Listenerbt会执行。浏览器

咱们想启用监听器。可是d3 API里面并无这个东东。难道要我用原生JS写?虽然不是不能够,但事实上是,d3js对此有更好的解决方式,那就是使用命名空间,对事件响应进行区分!框架

see: https://github.com/mbostock/d3/wiki/Selections#wiki-onsvg

If an event listener was already registered for the same type on the selected element, the existing listener is removed before the new listener is added. To register multiple listeners for the same event type, the type may be followed by an optional namespace, such as “click.foo” and “click.bar”. To remove a listener, pass null as the listener.函数

下面这个例子,就是使用了命名空间来处理多个事件绑定到同一对象这一问题。运行结果是,两个函数listenersp,listenerbt都会被执行。

能绑定固然也能解除绑定,方法以下:

事实上,在d3两个自建的交互方法drag和zoom中,都使用了复数的事件绑定机制。例如在d3的ZOOM方法中,实际绑定了7个事件:mousedown, mousemove, dbclick, touchstart, wheel, mousewheel, MOzMousePixelScroll. 为了不这些事件与用户本身的事件产生覆盖冲突,他们都使用了zoom这一命名空间。这个例子值得咱们学习。

see: https://github.com/mbostock/d3/wiki/Zoom-Behavior

有时候zoom的功能太丰富了也很头痛,会跟你的需求产生冲突。这个时候就须要解除绑定一些事件。解绑只须要置空就行:

特别提一点:jquery中也是使用命名空间对不一样绑定事件进行区分的。可是它是隐式地使用命名空间,用户不须要特别声明。例以下面的例程,两个console都会出现。

这虽然很方便,但许多从jquery入门的程序员若不了解这一点,会致使在其余类库中会出现错误。

————————————————————————————————–

三.d3的自定义事件

大多数时候,咱们只要利用这些已有事件就能够了。可是正如别的类库会自定义事件用以处理一些定制问题同样,d3也能够建立自定义事件。这里就要用到d3.dispatch对象。

see: https://github.com/mbostock/d3/wiki/Internals#rebind

使用起来也很简单,首先声明一个命名空间,例如:

而后就能够分别定义具体的处理函数和调用方式:

别的事件也能够触发自定义事件:

固然,这个dispatch的具体用法,状况要比以前讨论的内容复杂得多。具体咱们仍是要看例程才能理解其做用。

一个例子是:http://bl.ocks.org/mbostock/5872848,这是一个自定义事件的典型用法,经过自定义事件和命名空间将又一个交互形成的多个响应事件统一块儿来,从而获得一致的处理逻辑。

第二个例子是:https://github.com/kristw/angularjs-requirejs-d3-seed。它使用自定义事件来定义d3 vis模块与外层angularjs框架之间的交互,取得了很好的效果。

PS:最后这里必需要吐槽一下d3的API文档,虽然介绍很详细,可是缺乏代码示例,这点就不如jquery API和angularjs API。原本很简单的东西让人看不懂,还得我去stackoverflow上查。代码这个东西不少时候不是光用语言能描述清楚的。

相关文章
相关标签/搜索