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

如何使用d3.js更新现有svg元素的填充颜色?,svg,d3.js,Svg,D3.js,所以我试图从Illustrator生成的.svg文件中制作一张地图,因为这是一张荷兰地图,没有那么简单的区域 所有区域都有自己的ID 现在,我尝试根据数据集中的值为每个区域着色。我可以用CSS在一个区域强制着色,但这显然不是一个好的解决方案 例如,如果我尝试选择ID,然后更改.attrfill,红色;它不起作用 如何根据数据集中的d[1]值使用d3.js按id更新区域颜色 档案: 实时链接:问题在于Illustrator文件已经指定了各个元素的填充颜色,并且您的id值用于父元素。子元素从父元素继

所以我试图从Illustrator生成的.svg文件中制作一张地图,因为这是一张荷兰地图,没有那么简单的区域

所有区域都有自己的ID

现在,我尝试根据数据集中的值为每个区域着色。我可以用CSS在一个区域强制着色,但这显然不是一个好的解决方案

例如,如果我尝试选择ID,然后更改.attrfill,红色;它不起作用

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

档案:


实时链接:

问题在于Illustrator文件已经指定了各个元素的填充颜色,并且您的id值用于父元素。子元素从父元素继承样式,但前提是子元素没有自己的值

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

更改Illustrator文件,使路径没有填充。然后,它们将继承父对象上的填充颜色集

使用d3.selectAllgid path或d3.selectgid.selectAllpath直接选择路径;任何一个版本都将选择id为的elment的所有子元素。然后您可以直接设置fill属性以覆盖Illustrator中的值

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

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
});
如果您希望将来能够选择所有顶级元素,我建议也给它们一个类,这样您就可以使用d3.selectg.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
  });

显示了上面的代码,但我还是建议使用forEach方法。

另一方面,我在使用它并生成它。但也许这对于你想要的东西来说太简单了。我执行了d3.xml调用,只关注颜色。@FernOfTheAndes:比这更复杂,该方法不能确保数据是基于id值连接的,颜色也不是基于数据的。在这种情况下,我实际上建议使用for循环,或者更具体地说,在数据集上使用forEach来生成更简单、更可读的代码:这是真的@AmeliaBR,我只是根据名称而不是实际值来确定颜色。你的表演很好@AmeliaBR,我仔细查看了您的小提琴,并从研究处理数据的两个选项中受益匪浅。我想知道你是否有时间把它作为你下面答案的一部分浮出水面,从而增加其他人阅读它的机会。我把投票作为一种象征性的激励:-感谢你们两位。现在有道理了,我想我必须学习更多的Javascript:还有,我导入.svg的方式是否可能导致一些问题?还有一个问题,这到底是什么意思?看看@FernOfTheAndes的实现,我注意到您的一些形状是元素,而不仅仅是元素。您需要更改select语句以选择形状:d3.selectAllgid path,gid polygon或d3.selectgid.selectAllpath,polygon
//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.