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上查。代碼這個東西不少時候不是光用語言能描述清楚的。

相關文章
相關標籤/搜索