2012-07-09 34 views
7

Mike有一篇關於在D3中編寫reusable components的優秀文章。本文介紹瞭如何使組件可配置以及如何將組件應用於選擇的模式。如何使用操縱組件的每個實例的API在D3中創建可重用組件?

該模式允許通過將單個組件對象連接到數據來重複使用多個選擇對象;例如

var chart = myChart(); 

d3.select("div.chart") 
    .data(data) 
    .call(chart); 

我的組件實現如下所示:

function myChart() { 

    function my(selection) { 
     selection.each(function(d, i) { 

      // generate chart here 
      // `d` is the data, `i` is the index, `this` is the element 

      var state = false; 

      var circle = d3.select(this).append("circle") 
       .attr("r", "10") 
       .style("fill", "#000") 
       .on("click", toggleState); 

      function toggleState() { 
       // this function updates the current instance trapped by this closure 
       (state = !state) 
        ? circle.style("fill", "#fff") 
        : circle.style("fill", "#000"); 
      } 
     }); 
    } 

    my.toggleState(i) { 
     // How do I access the `i`th instance of the component here? 
    } 

    return my; 
} 

我想實現的就是讓呼叫者操縱給定了索引該組件的一個實例。例如,如果上面的選擇器div.chart返回一個包含兩個元素的選擇,我想調用chart.toggleState(1)並讓它更新選擇中的第二個div。

就這樣,我不會混淆任何人爲什麼我要這樣做,調用者需要將兩種類型的組件同步到一起。想象一下,我有一個由圓圈表示的組件和由矩形表示的另一個組件。這兩個組件必須是獨立的,而不是彼此綁定。我需要能夠創建4個圓形和4個矩形,當我點擊矩形時,我希望能夠根據索引順序更新相應的圓。我已經想出瞭如何從組件中引發事件(d3.dispatch),並提供當前索引作爲事件中的參數,但我還沒有弄清楚如何根據其索引調用組件的特定實例。

+1

這聽起來好像做的方式是隻選擇需要更新的元素,然後調用組件。其他任何東西都會違反通過此組件模式實現的封裝。 – 2014-05-07 18:36:28

+0

我最近完成了基於Mikes文章的關於開源可重用組件的工作。 https://timebandit.github.io/graphSub – timebandit 2015-08-12 12:06:11

回答

0

我認爲最簡單的方法是給每個組件同一個類。然後,當您撥打chart.toggleState(1)時,您可以執行d3.selectAll('.component').each(function(d, i) { if (i == index) doWhatever; });

0

特定選擇的數據在選擇[0]中。您可以選擇的第i個元素正是如此設置屬性:

var i = 3 
d3.select(mySelection[0][i]).attr("fill","#fff") 

如果你知道我,你可以這樣寫toggleState:

function toggleState(i) { 
    var toggle_me = d3.select(circles[0][i]) 
    var state = !(toggle_me.attr("fill") == "#fff") 
    toggle_me.attr("fill", (state ? "#fff": "#000")) 
} 

如果你不知道我,你可以寫toggleState從而:

function toggleState() { 
    var toggle_me = d3.select(this) 
    var i = circles[0].findIndex(function(d) { 
     return d == toggle_me[0][0] 
    }) 
    if (i !== -1) { 
     var state = !(toggle_me.attr("fill") == "#fff") 
     toggle_me.attr("fill", (state ? "#fff": "#000")) 
     // Do additional functions with i here 
     //var triange = d3.select(triangles[0][i]) 
     //... 
    } 
} 

工作實施例:https://jsfiddle.net/fd7fyeoq/

爲SA我在不同的上下文中回答請參閱: d3js : How to select nth element of a group?

相關問題