7

Mike 有一篇关于在 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)并提供当前索引作为事件中的参数,但我还没有想出如何在给定索引的情况下调用组件的特定实例。

4

2 回答 2

0

我认为最简单的方法是为每个组件提供相同的类。然后当你打电话时chart.toggleState(1)你可以做d3.selectAll('.component').each(function(d, i) { if (i == index) doWhatever; });

于 2014-06-17T13:05:52.587 回答
0

特定选择的数据在 selection[0] 中。您可以选择第 i 个元素并因此设置属性:

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

如果你知道 i,你可以这样写 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"))
}

如果你不知道 i,你可以这样写 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/

对于不同上下文中的相同答案,请参阅: d3js:如何选择组的第 n 个元素?

于 2016-06-12T22:31:59.217 回答