首先说明,d3支持所有的JS事件——甚至其他代码的自定义事件。这里有一个列表,The MDN Event Reference, 包含了几乎所有浏览器创建的事件类型。大家有需要可以去查看。

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

一.原生JS的事件绑定

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

 
1
2
3
4
5
6
7
8
9
10
11
12
<span style="font-size:18px;">window.onload = function(){  
    var btn = document.getElementById("yuanEvent");  
    btn.onclick = function(){  
        alert("第一个事件");  
    }  
    btn.onclick = function(){  
        alert("第二个事件");  
    }  
    btn.onclick = function(){  
        alert("第三个事件");  
    }  
}</span>

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

 
1
2
3
4
5
6
7
8
9
10
11
12
var eventOne = function(){  
    alert("第一个监听事件");  
}  
function eventTwo(){  
    alert("第二个监听事件");  
}  
window.onload = function(){  
    var btn = document.getElementById("yuanEvent");  
    //addEventListener:绑定函数  
    btn.addEventListener("click",eventOne);  
    btn.addEventListener("click",eventTwo);  
}

当然,能绑定就能解除绑定,方法如下:

 
1
2
btn.addEventListener("click",eventTwo);  
btn.removeEventListener("click",eventOne);

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

二.d3的事件绑定机制

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

 
1
2
3
d3.select("#timebasis")
    .on("change", listenersp)
    .on("change", listenerbt);

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

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

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都会被执行。

 
1
2
3
d3.select("#timebasis")
    .on("change.sp", listenersp)
    .on("change.bt", listenerbt);

能绑定当然也能解除绑定,方法如下:

 
1
2
3
d3.select("#timebasis")
    .on("change.sp", null)
    .on("change.bt", null);

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

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

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

 
1
2
3
4
5
6
7
                svg.on("mousedown.zoom", null);
                    svg.on("mousemove.zoom", null);
                svg.on("dblclick.zoom", null);
                svg.on("touchstart.zoom", null);
                svg.on("wheel.zoom", null);
                svg.on("mousewheel.zoom", null);
                svg.on("MozMousePixelScroll.zoom", null);

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

 
1
2
$(".logo").mouseenter(function(){console.log("paomian")});
$(".logo").mouseenter(function(){console.log("niuroumian")});

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

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

三.d3的自定义事件

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

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

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

 
1
var dispatch = d3.dispatch('nodeClick', 'evaluationDialog', 'infoboxDblclick');

然后就可以分别定义具体的处理函数和调用方式:

 
1
dispatch.on("nodeClick", listener);

别的事件也可以触发自定义事件:

 
1
.on('click.dispatch', dispatch.nodeClick);

当然,这个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上查。代码这个东西很多时候不是光用语言能描述清楚的。

d3可视化实战04:事件绑定机制的更多相关文章

  1. d3可视化实战03:神奇的superformula

    需求驱动实现 前文讲过了D3的数据驱动机制,中间所举的例子都很简单.例如那个demo里面,绑定的数据是一个简单的数组,实现的图元也仅仅是一堆用SVG画的circle.但是现实世界中我们往往会遇到复杂的 ...

  2. 关于jQuery新的事件绑定机制on()的使用技巧

    关于jQuery新的事件绑定机制on()的使用技巧 http://www.jb51.net/article/36064.htm 本篇文章介绍了,关于jQuery新的事件绑定机制on()的使用技巧.需要 ...

  3. jQuery新的事件绑定机制on()

    浏览jQuery的deprecated列表,发现live()和die()在里面了,赶紧看了一下,发现从jQuery1.7开始,jQuery引入了全新的事件绑定机制,on()和off()两个函数统一处理 ...

  4. JQuery的方便之处——宽高设置、坐标值和滚动条+事件绑定机制

    1.元素的宽高 可以通过css来进行设置,例如:$("元素").css({"宽度":"值","高度":"值&q ...

  5. jQuery新的事件绑定机制on()示例应用

    投稿:whsnow 字体:[增加 减小] 类型:转载   从jQuery1.7开始,jQuery引入了全新的事件绑定机制,on()和off()两个函数统一处理事件绑定,下面通过示例为大家介绍下     ...

  6. d3可视化实战00:d3的使用心得和学习资料汇总

    最近以来,我使用d3进行我的可视化工具的开发已经3个月了,同时也兼用其他一些图表类库,自我感觉稍微有点心得.之前我也写过相关文章,我涉及的数据可视化的实现技术和工具,但是那篇文章对于项目开发而言太浅了 ...

  7. d3可视化实战02:理解d3数据驱动的真正含义

    前文中已经提到,SVG从诞生之初起就可以非常方便地使用javascript脚本语言来进行其DOM对象的控制.当然,控制的方法有很多,有直接控制SVG对象的方法,例如使用原生js:有帮你封装一下图形接口 ...

  8. d3可视化实战01:理解SVG元素特性

    一. SVG简介 ————————————————————————————————————————————————————————————————— SVG是一种和图像分辨率无关的矢量图形格式,它使用 ...

  9. 关于jQuery事件绑定

    转自:http://www.cnblogs.com/gaojun/p/3497582.html html: <a href="#" onclick="addBtn( ...

随机推荐

  1. Nodejs in Visual Studio Code 04.Swig模版

    1.开始 设置Node_Global:npm config set prefix "C:\Program Files\nodejs" Express组件:npm install e ...

  2. 转自http://blog.sina.com.cn/daylive——C++ STL map

    Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作! 1.map最基本的构造函数: map<string ...

  3. 使用GDB生成coredump文件【转载】

    本文转载自: http://blog.csdn.net/sky_qing/article/details/8548989 如果在测试过程中遇到某个进程的CPU利用率过高或者卡死而需要去调试该进程时,可 ...

  4. [置顶] 【Git入门之九】解决冲突

    原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/12309531 1.多人协作冲突 如果多人同时修改了同一个文件,那会出现什么样 ...

  5. [置顶] COcos2d-X 中文API

    本文来自http://blog.csdn.net/runaying ,引用必须注明出处! COcos2d-X 中文API 温馨提醒:使用二维码扫描软件,就可以在手机上访问我的博客啦!另外大家可以访问另 ...

  6. object- c 字符串操作

    Objective-C 中核心处理字符串的类是 NSString 与 NSMutableString ,这两个类最大的区别就是NSString 创建赋值以后该字符串的内容与长度不能在动态的更改,除非重 ...

  7. C++中struct和class的区别 [转]

    一. C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能. struct能包含成员函数吗?   能! struct能继承吗?  ...

  8. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

  9. rsync+inotify实现服务器之间文件实时同步--转

    之前做了“ssh信任与scp自动传输脚本”的技术文档,此方案是作为公司里备份的方法,但在实际的运行中,由于主服务器在给备份服务器传输的时候,我们的主服务器需要备份的文件是实时.不停的产生的,造成不知道 ...

  10. [转] Python 模块学习:os模块

    一.os模块概述 Python os模块包含普遍的操作系统功能.如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的.(一语中的) 二.常用方法 1.os.name 输出字符串指示正在使用的平台 ...