Fall Foliage: JavaScript/OJS Edition – Security Boulevard

I (mostly) follow the annual updates to my R/{sf} American Foliage article which you can find on GH. This year we have Quarto, and it comes with so many batteries included, you’d think it was Christmas. One of these farms fully supports the Observable runtime environment. These are used in {ojs} Quarto blocks and rendered builds can run anywhere.

The Observable rig is great for both DIY and publishing (we use it at work for quick screw work or experimental), and with some of the recent articles here showing how to turn Observable notebooks In Quarto documents, you’re literally two clicks or a command line away from using any public Observable notebook directly in Quarto.

I created a version of the vis foliage in Observable, then did the qmd conversion using the Chrome extension, modified the source a bit, and published the same in Quarto.

The interactive datavis uses some fundamental Observable/D3 libraries:

In the JS code, we define data-centric values:

foliage_levels = [0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6]
foliage_colors = ["#83A87C", "#FCF6B4", "#FDCC5C", "#F68C3F", "#EF3C23", "#BD1F29", "#98371F"]
foliage_labels = ["No Change", "Minimal", "Patchy", "Partial", "Near Peak", "Peak", "Past Peak"]
week_label = ["Sept 5th", "Sept 12th", "Sept 19th", "Sept 26th", "Oct 3rd", "Oct 10th", "Oct 17th", "Oct 24th", "Oct 31st", "Nov 7th", "Nov 14th", "Nov 21st"]

We then borrow the topojson file projected by Albers from the United States at Choropleth example notebook and rebuild the contour mesh and county geometry collections, because we need to get rid of Alaska and Hawaii (they are not present in the source data). To do this, we filter two FIPS codes:

counties = {
  var cty = topojson.feature(us, us.objects.counties);
  cty.features = cty.features.filter(
    (d) => (d.id.substr(0, 2) != "02") & (d.id.substr(0, 2) != "15")
  return cty;

I also ended up modifying the source CSV a bit to account for the missing counties.

After that it was a simple call to our imported Choropleth function:

chart = Choropleth(rendered2022, {
  id: (d) => d.id.toString().padStart(5, "0"), // this is needed since the CSV id column is numeric
  value: (d) => d[week_label.indexOf(week) + 1], // this gets the foliage value based on which index the selected week is at
  scale: d3.scaleLinear, // this says to map foliage_levels to foliage_colors directly
  domain: foliage_levels,
  range: foliage_colors,
  title: (f, d) =>
    `${f.properties.name}, ${statemap.get(f.id.slice(0, 2)).properties.name}`, // this makes the county hover text the county + state names
  features: counties, // this is the counties we modified
  borders: statemesh, // this is the statemesh
  width: 975,
  height: 610

and place the legend and the cleanup cursor.

The only real difference between notebook and qmd is the inclusion of source functions rather than using those from Observable import (I found that there is a slight delay in loading for imports when the network conditions aren’t super perfect and the inclusion of the source – WITH the copyright – compensates for that).

I configured the Quarto project so that the renders go to the docs/ directory, making it easy to post as a GH page.


File issues on GH if anything needs clarification or correction and go experiment! You can’t break anything on the Observable or locally that version control can’t fix (yes, Observable has version control!).

A few things to change/add:

  • one click takes you to a map service (selectable?), so people can get directions
  • turn hover text into proper tooltip
  • speed up or slow down the animation when ‘Play’ is typed
  • use different colors
  • import older datasets (see the foliage GH repo) and create multiple maps or let the user select or compare them over the years

*** This is a syndicated Security Bloggers Network blog from rud.is written by hrbrmstr. Read the original post at: https://rud.is/b/2022/09/09/fall-foliage-javascript-ojs-edition/

Comments are closed.