Skip to content

Latest commit

 

History

History
112 lines (101 loc) · 5.49 KB

choropleth.md

File metadata and controls

112 lines (101 loc) · 5.49 KB

Choropleth

  • Choropleth
    • This is county-level choropleth
    • Note about tooltips: This choropleth has a built-in SVG tooltip
      • implemented with SVG <title> element
      • Observable Plot implements tooltips the same way
        • each mark has an optional "title" channel -- if you provide a value, it'll show up as an SVG <title>
        • the other channels: "fill", "fillOpacity", "stroke", "strokeOpacity", "strokeWidth"
      • Note: SVG <title> is not the same as the HTML document <title>
  • My Zoom to Bounding Box
    • Adds pan and zoom capabilities to the county-level choropleth
    • I created this because zooming a county-level SVG can have performance issues
  • State Choropleth
    • we're going to customize this below
    • topojson has 2-character ID and state name
  • TODO: discuss color scale

EXERCISE #1: Circle

Add a circle that follows the mouse to State Choropleth

  • Hints:
  • SOLUTION
    • State Choropleth (w/tooltip)
    • First: add a circle that will follow the mouse
      • const circle = svg.append("circle").attr("r", 10)
      • That line should appear after the code that draws the states and state boundaries
        • Otherwise it will appear underneath those elements
      • When you add the line, you should see 1/4 of the circle in the upper left corner, where x = y = 0
        • That's because we have yet to set the values for cx and cy
    • Second, declare function mousemoved(event) {}, which will determine the circle position based on the mouse event
      function mousemoved(event) {
        const pointer = d3.pointer(event, svg.node());
        circle.attr("cx", pointer[0])
          .attr('cy', pointer[1])
        // mutable z = pointer  // use this to inspect the mouse location (add a `mutable z` cell to the notebook)
      }
      
      • You can place this anywhere inside the cell.
        • Arbitrary placement in the cell is due to Hoisting in JavaScript.
    • Third, add an event listener to the SVG
      • Add svg.on("mousemove", mousemoved) somewhere in the cell.
      • You can do it by changing
      const svg = d3.create("svg")
        .attr("viewBox", [0, 0, 975, 610]);
      
      to
      const svg = d3.create("svg")
        .attr("viewBox", [0, 0, 975, 610])
        .on('mousemove', mousemoved);
      
      • Note: the technique for getting the circle to follow the mouse on the map in Introduction to Views is significantly more subtle
    • When you add an event listener for mousemove
      • If you add it to the states, then you can use it below for data-dependent styling or a tooltip
        • To put it on states, move the line: .on("mousemove", mousemoved) after: .join("path")
    • TODO Show what happens when you change the location of .on("mousemove", mousemoved)
      • If you put it on the main SVG, then the circle goes anywhere
      • If you put it on the "g" with the legend, it only moves if you mouse over the legend
      • If you put it on the states, then it won't move outside the states

EXERCISE #2: Styling

Update the styling to highlight the state that's being moused over

  • Again, get hints from here: Plot Tooltip
  • d3.select() -- tells you about this
    • You'll use this to select a state
    • You can also use this to get the data value that's bound to the state
  • If you change the implementation to
  const states = svg.append("g")
    .selectAll("path")
    .data(topojson.feature(us, us.objects.states).features)
    .join("path")
      .attr("fill", d => color(data.get(d.properties.name)))
      .attr("d", path)
      .on("mousemove", mousemoved)
      .on("mouseout", mousedout)
    .append("title")
      .text(d => `${d.properties.name}
${format(data.get(d.properties.name))}`);
  • Then update function mousemoved() to include the following...
    d3.select(this).attr('fill', 'crimson')
  • And add function mousedout() as follows (using this to get the bound datum)
  function mousedout(event) {
    const d = d3.select(this).data()[0];
    d3.select(this).attr('fill', color(data.get(d.properties.name)));
  }
  • If the circle is still there, then you'll have to add .attr("pointer-events", "none")
    • Otherwise the circle will be underneath the mouse, and the states' <path> elements will never detect mouse events

EXERCISE #3: Tooltip

Add a tooltip that shows the data value as it follows the mouse