Abstract State Map: Basic Recipe

d3 sandwich

Recipe: Abstract State Map

Step #3: Add the State Names to the Map

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");
Font
X Offset
Y Offset
Fill

Select-Data-Enter-Append

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")

Creating the Text Labels

For text, we've got a couple of additional commands:

  • text: the text we are going to put on the map
  • font: the text's font
  • pointer-events: make it so that if someone clicks on the text, it won't respond like text, which can be selected, it'll respond as if it's just part of the rectangle

        .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".

Centering the State's Name In Its Rectangle

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;})
X Offset
Y Offset

Recap

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.

Up Next: Recipe Step #4: Changing the color of selected states