如何在数组中保存d3选择以供以后使用D3.js?

时间:2015-10-16 13:41:45

标签: javascript d3.js svg

我正在尝试在数组中保存选定的圆圈,以便稍后我可以操纵这些圆圈而无需搜索页面上的所有圆圈。我希望能够从不同的功能访问圆圈,而不是创建它们。

// From outer function
var selections = [];

// From inner function A
circles.on("click", function(da){
  d3.selectAll("circle").filter(function(db){
    var result = da.someProperty == db.someProperty;
    var circle = d3.select(this);
    if(result) selections.push(circle);
    return result;
  })
  .attr("fill", "red");
});

// From inner function B
selections.forEach(function(circle){
  circle.attr("fill", "black");        // Doesn't work
});

有没有办法使用我的选择数组的内容修改圆属性?

3 个答案:

答案 0 :(得分:5)

从D3的角度来看,适用于您的方法的一些改进将使您的代码更具可读性和 D3ish 。尝试通过D3' concept of selections来了解它。即使不知道您的整个代码,您问题中发布的代码段也可能会被重构为:

// From outer function
// This will hold the selection in the outer scope.
var selections;

// From inner function A
circles.on("click", function(da){
  // Fill in the reference to the selection which is returned by filter().
  selections = d3.selectAll("circle").filter(function(db){
    return da.someProperty == db.someProperty;
  })
  .attr("fill", "red");
});

// From inner function B
// No need for an explicit loop here; D3 will take care of that.
selections.attr("fill", "black");

filter()函数将返回您所选择的选项,而无需摆弄任何辅助数组。您只需在selections中将对该选择的引用存储在外部范围内。

稍后,当你以某种方式想要对此选择进行操作时,不需要对数组进行显式循环,因为D3会处理这个问题。您可以调用其处理属性,样式,事件处理程序等的方法。有关d3.select()上提供的所有方法,请参阅API docs

答案 1 :(得分:2)

在你的selections.forEach(...)中,看一下" circle"实际上是。从我测试过(我必须创建变量"圆圈"提前,这只是d3.selectAll(' circle'),但你应该特别包括您在提示中使用的内容),"圈"在你的函数中,B循环是指一个1单元格的数组,它包含另一个单元格数组,该数组包含一个圆形引用(对于原生HTML / SVG圆,而不是d3包装器)。

将B循环功能的内容更改为

d3.select(circle[0][0]).attr('fill','black');

也许这是一种更优雅,面向d3的方式,但这绝对有效,而且它仍然很简单。

编辑:经过进一步测试后,我实际上并不确定为什么你所做的事情不起作用。一旦我将var circles = d3.selectAll('circle');添加到开头,假设您在运行之前实际点击了一个圆,则功能B循环正常工作。如果你没有,你就会重复一个空数组。

答案 2 :(得分:0)

这是一个有效的jsfiddle

var jsonCircles = [{
    "x_axis": 30,
        "y_axis": 30,
        "radius": 20,
        "color": "green"
}, {
    "x_axis": 70,
        "y_axis": 70,
        "radius": 20,
        "color": "purple"
}, {
    "x_axis": 110,
        "y_axis": 100,
        "radius": 20,
        "color": "red"
}, {
    "x_axis": 150,
        "y_axis": 230,
        "radius": 70,
        "color": "yellow"
}, {
    "x_axis": 300,
        "y_axis": 100,
        "radius": 90,
        "color": "grey"
}];

var svgContainer = d3.select("body").append("svg")
    .attr("width", 400)
    .attr("height", 400);

var circles = svgContainer.selectAll("circle")
    .data(jsonCircles)
    .enter()
    .append("circle");

var circleAttributes = circles.attr("cx", function (d) {
    return d.x_axis;
})
    .attr("cy", function (d) {
    return d.y_axis;
})
    .attr("r", function (d) {
    return d.radius;
})
    .style("fill", function (d) {
    return d.color;
});

var selection = [];

d3.selectAll('circle')[0].forEach(function (circle) {
    if (circle.r.baseVal.value > 20) {
        selection.push(circle);
    }
});

alert('We have ' + selection.length + 'circle(s) selected');
selection.forEach(function (circle) {
    circle.style.fill = "blue";
});