All that hard work you put in on Step 2? It's about to start paying dividends. Because Step 3 is just a variation on the pattern you just learned -- only instead of creating rectangles, we are going to create text to put the state names on the map.
Let's start by playing with the code.
var state_map = [ { "state": "ME", "row": 0, "col": 10 }, { "state": "VT", "row": 1, "col": 9 }, { "state": "NH", "row": 1, "col": 10 }, ... ]; // Put the name of each state on its rectangle svg_area.selectAll("text") .data(state_map) .enter() .append("text") .attr("x", function(d,i) { return d.col * width + 108;}) .attr("y", function(d,i) {return d.row * height + 26;}) .text(function (d) { return d.state; }) .style("font", "16px sans-serif") .style("fill", "White") .style("pointer-events", "none");
For the first part of the code, we use the same pattern that we used with rectangles: Select-Data-Enter-Append.
This time, instead of selecting and appending "rect", short rectangles, we select and append "text".
svg_area.selectAll("text") .data(state_map) .enter() .append("text")
For text, we've got a couple of additional commands:
.text(function (d) { return d.state; }) .style("font", "16px sans-serif") .style("fill", "White") .style("pointer-events", "none");
For the text label, we use the same function trick that we used for grabbing rows and columns, only this time we use the name of the state, which in stateMap is called "state".
X and Y are a bit more complicated.
We want to make sure that the state's name is centered in its rectangle. Ideally we would just tell D3 to center the name. Unfortunately, the technique for doing this, which is called "grouping", Looks pretty weird when you first see it -- and we think you've already had plenty of weird stuff to deal with.
We'll teach the grouping technique in a coming recipe. For now, we will use a quick and dirty trick:
For now, we will use a quick and dirty trick: if you add __ pixels to the text's height and width, it'll be close enough to being centered to be fine for now.
That's not completely intuitive. So let's play a little to get a better feel for how it works.
.attr("x", function(d,i) { return d.col * width + 108;}) .attr("y", function(d,i) {return d.row * height + 26;})
As you can see, Step 3 was a lot easier then Step 2. All you needed to do was take the code pattern we saw in Step 2 and tweak it to account for the difference between a rectangle and a text label.