所以我正在尝试使用Illustrator生成的.svg文件制作地图,因为它是荷兰的地图,而不是那么简单的地区。
所有地区都有自己的#ID。
现在我正在尝试根据数据集中的值为每个区域着色。我可以通过CSS在区域上强制颜色,但这显然不是很好的解决方案。
例如,如果我尝试选择(#id)然后更改.attr(“填充”,“红色”);它不起作用。
如何根据数据集中的d [1]值使用d3.js按ID更新区域颜色?
答案 0 :(得分:11)
问题是,您的Illustrator文件已经在各个<path>
元素上指定了填充颜色,而您的ID值是针对父<g>
元素的。子元素从父元素继承样式,但仅当子元素不具有的值时才会继承。
您可以采取一些措施来改变它:
更改Illustrator文件,使路径无填充。然后他们将继承父母的填充颜色。
使用d3.selectAll("g#id path")
或d3.select("g#id").selectAll("path")
直接选择路径;任何一个版本都会选择所有<path>
个元素,这些元素是ID为{id“的<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
});
如果您希望以后能够选择所有顶级<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
});
示例实施: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.
This fiddle显示了上述代码,但我再次建议使用forEach
方法。