如何使用d3.js更新现有svg元素的填充颜色?

use*_*511 10 svg d3.js

所以我试图用我用Illustrator制作的.svg文件制作一张地图,因为它是荷兰的地图,而不是那么简单的地区.

所有地区都有自己的#ID.

现在我正在尝试根据数据集中的值为每个区域着色.我可以通过CSS在区域上强制颜色,但这显然不是很好的解决方案.

如果我例如尝试选择(#id)然后更改.attr("填充","红色"); 它不起作用.

如何根据数据集中的d [1]值使用d3.js按id更新区域颜色?

文件:https://gist.github.com/gordonhatusupy/9466794

实时链接:http://www.gordonjakob.me/regio_map/

Ame*_*aBR 11

问题是您的Illustrator文件已经指定了各个<path>元素的填充颜​​色,而您的id值是父<g>元素的.子元素继承父项的样式,但前提是子项没有自己的值.

你可以做几件事来改变它:

  1. 更改Illustrator文件,以使路径无填充.然后他们将继承父级的填充颜色集.

  2. 使用d3.selectAll("g#id path")或直接选择路径d3.select("g#id").selectAll("path"); 任何一个版本都将选择ID为"id"的<path>元素后代的所有元素<g>.然后,您可以直接设置fill属性以覆盖Illustrator中的值.


正如对主要问题的评论中所讨论的那样,如果您想更进一步并将数据实际连接到元素以供将来参考(例如,在事件处理程序中),最简单的方法是遍历数据集,选择每个元素,然后使用该.datum(newData)方法将数据附加到每个元素:

dataset.forEach(function(d){ //d is of form [id,value]
    d3.select("g#"+d[0]) //select the group matching the id
      .datum(d) //attach this data for future reference
      .selectAll("path, polygon") //grab the shapes
      .datum(d) //attach the data directly to *each* shape for future reference
      .attr("fill", colour(d[1]) ); //colour based on the data
});
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/ybAj5/6/

如果您希望<g>将来能够选择所有顶级元素,我建议也给它们一个类,所以您可以选择它们,例如d3.select("g.region").例如:

dataset.forEach(function(d){ //d is of form [id,value]
    d3.select("g#"+d[0]) //select the group matching the id
      .datum(d) //attach this data for future reference
      .classed("region", true) //add a class, without erasing any existing classes
      .selectAll("path, polygon") //grab the shapes
      .datum(d) //attach the data directly to *each* shape for future reference
      .attr("fill", colour(d[1]) ); //colour based on the data
});

d3.selectAll("g.region")
  .on("click", function(d,i) {
         infoBox.html("<strong>" + d[0] + ": </strong>" + d[1] ); 
          //print the associated data to the page
  });
Run Code Online (Sandbox Code Playgroud)

示例实现:http://jsfiddle.net/ybAj5/7/

虽然使用dataset.forEach似乎没有使用d3的全部功能,但它实际上比尝试立即附加整个数据集简单得多 - 特别是因为区域结构存在这种可变性,其中一些具有嵌套<g>元素:

//Option two: select all elements at once and create a datajoin
d3.selectAll("g[id]") //select only g elements that have id values
    .datum(function(){
        var id=d3.select(this).attr("id"); 
        return [id, null]; })
        //create an initial [id, value] dataset based on the id attribute, 
        //with null value for now
    .data(dataset, function(d){return d[0];}) 
       //use the first entry in [id,value] as the key
       //to match the dataset with the placeholder data we just created for each
    .selectAll("path, polygon") //grab the shapes
    .datum(function(){
        return d3.select(this.parentNode).datum() ||
        d3.select(this.parentNode.parentNode).datum();
    }) //use the parent's data if it exists, else the grandparent's data
    .attr("fill", function(d){return d?colour(d[1]):"lightgray";});
         //set the colour based on the data, if there is a valid data element
         //else use gray.
Run Code Online (Sandbox Code Playgroud)

这个小提琴显示了上面的代码,但我再次建议使用这种forEach方法.