D3如何从一个组中选择具有共享属性的多个形状?

时间:2013-09-30 08:58:55

标签: d3.js

D3如何在具有共享属性的组中选择多个形状?

我在D3中构建一个图表,其中每个数据点由多个形状表示。我有一个简单的数据集,我创建了一个组,其中包含三个独立的形状集。

我希望在鼠标悬停和鼠标移动时,行上的形状会改变颜色。有两个功能 - “over”和“out” - 我在mouseover上调用它。他们成功地更改了对象的样式属性,但是依次为每组形状更改。

下面的代码和this fiddle说明了问题。

这种方法不会在形状上扩展,感觉我错过了关于D3选择的关键点。我可以一步选择具有共享索引(或其他属性)的所有对象吗?

我尝试了各种方法:

  • 选择( “形状”)。过滤(...)
  • 选择( “形状”)[0] [I]

但没有成功地让这些工作。

var dataset = ["A", "B", "C"];

// Create SVG object
var svg = d3.select("body")
    .append("svg")
    .attr({width: 600, height: 400});

var shapes = svg.append("g");

// Circles
var circles = shapes.selectAll("circle")
    .data(dataset)
    .enter()
    .append("circle")
    .attr("id",function(d, i) {return i;})
    .attr("cx",125)
    .attr("cy",function(d, i) {return (i+1)*100-25;})
    .attr("r",25)
    .on("mouseover", over)
    .on("mouseout", out)
    .append("title").text(function(d, i) {return d + " " + i;});

// Ellipses
var ellipses = shapes.selectAll("ellipse")
    .data(dataset)
    .enter()
    .append("ellipse")
    .attr("cx", 350)
    .attr("cy",function(d, i) {return (i+1)*100-25;})
    .attr("rx",50)
    .attr("ry",25)
    .on("mouseover", over)
    .on("mouseout", out)
    .append("title").text(function(d, i) {return d + " " + i;});

// Squares
var squares = shapes.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("x", 200)
    .attr("y",function(d, i) {return (i+1)*100-50;})
    .attr("height",50)
    .attr("width",50)
    .on("mouseover", over)
    .on("mouseout", out)
    .append("title").text(function(d, i) {return d + " " + i;});

// Over function to be called on mouseover
function over(d, i) {
    shapes.selectAll("circle").filter(function(e, j) {return j == i;})
        .style("fill", "green");
    shapes.selectAll("rect").filter(function(e, j) {return j == i;})
        .style("fill", "green");
    shapes.selectAll("ellipse").filter(function(e, j) {return j == i;})
        .style("fill", "green");
}

// Out function to be called on mouseout
function out(d, i) {
    shapes.selectAll("rect").filter(function(e, j) {return j == i;})
        .style("fill", null);
    shapes.selectAll("circle").filter(function(e, j) {return j == i;})
        .style("fill", null);
    shapes.selectAll("ellipse").filter(function(e, j) {return j == i;})
        .style("fill", null);
}

1 个答案:

答案 0 :(得分:1)

如果将它们与g元素组合在一起,则更容易处理元素组。在您的情况下,每行将有一个g,并将元素和处理程序附加到该行。然后,在鼠标事件上,您只需选择要操作的组的所有后代元素。

我已将你的jsfiddle修改为here。关键是创建群组

var gs = shapes.selectAll("g").data(dataset)
  .enter()
  .append("g")
  .attr("id",function(d, i) {return i;})
  .attr("transform",function(d, i) {return "translate(0," + i*100 + ")";})
  .on("mouseover", over)
  .on("mouseout", out);

以及大大简化的事件处理程序

function over(d, i) {
  d3.select(this).selectAll("*").style("fill", "green");
}