How to update the fill color on existing svg elements with d3.js? -
so i'm trying make map .svg file produced illustrator because it's map of netherlands not straightforward regions.
all regions have own #id.
now i'm trying color each region according value in dataset. can force color on regions css ive done on 1 region thats not solution.
if example try select(#id) , change .attr("fill","red"); doesnt work.
how update region colors id using d3.js according d[1] value in dataset ?
files: https://gist.github.com/gordonhatusupy/9466794
live link: http://www.gordonjakob.me/regio_map/
the problem illustrator file specifies fill colours on individual <path>
elements, , id values parent <g>
elements. child elements inherit styles parents, if child doesn't have values of own.
there couple things change it:
change illustrator file paths have no fill. inherit fill colour set on parent.
select paths directly, using
d3.selectall("g#id path")
ord3.select("g#id").selectall("path")
; either version select<path>
elements descendents of<g>
elment id "id". can set fill attribute directly over-write value illustrator.
as discussed in comments main question, if want take step further , join data elements future reference (e.g., in event handler), easiest way loop through dataset, select each element, use .datum(newdata)
method attach data each element:
dataset.foreach(function(d){ //d of form [id,value] d3.select("g#"+d[0]) //select group matching id .datum(d) //attach data future reference .selectall("path, polygon") //grab shapes .datum(d) //attach data directly *each* shape future reference .attr("fill", colour(d[1]) ); //colour based on data });
if want able select top-level <g>
elements in future, suggest giving them class, can select them with, example, d3.select("g.region")
. example:
dataset.foreach(function(d){ //d of form [id,value] d3.select("g#"+d[0]) //select group matching id .datum(d) //attach data future reference .classed("region", true) //add class, without erasing existing classes .selectall("path, polygon") //grab shapes .datum(d) //attach data directly *each* shape future reference .attr("fill", colour(d[1]) ); //colour based on data }); d3.selectall("g.region") .on("click", function(d,i) { infobox.html("<strong>" + d[0] + ": </strong>" + d[1] ); //print associated data page });
example implementation: http://jsfiddle.net/ybaj5/7/
although using dataset.foreach
doesn't seem using full capability of d3, simpler trying attach whole dataset @ once -- since there such variability in structure of regions, of have nested <g>
elements:
//option two: select elements @ once , create datajoin d3.selectall("g[id]") //select g elements have id values .datum(function(){ var id=d3.select(this).attr("id"); return [id, null]; }) //create initial [id, value] dataset based on id attribute, //with null value .data(dataset, function(d){return d[0];}) //use first entry in [id,value] key //to match dataset placeholder data created each .selectall("path, polygon") //grab shapes .datum(function(){ return d3.select(this.parentnode).datum() || d3.select(this.parentnode.parentnode).datum(); }) //use parent's data if exists, else grandparent's data .attr("fill", function(d){return d?colour(d[1]):"lightgray";}); //set colour based on data, if there valid data element //else use gray.
this fiddle shows above code in action, again recommend using foreach
approach.
Comments
Post a Comment