2012-07-09 37 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?

相关问题