In our digital feature, A Vanishing Aquifer, we take you through a massive underground water basin in the central US, known as the High Plains Aquifer, and show how it's changed. We do this using a series of responsive and dynamic maps and graphics. I'll walk you through the construction of the project.
The interactive was largely derived from a magazine graphic spread by Lauren James, who was also instrumental in the construction of the digital version.
This graphic has been reworked for a digital experience in order to introduce concepts and geography gradually, and be readily consumable on small screens. From print, the core map's component parts have been split into a series of layers, as opposed to a single static image, in order to activate labels and features sequentially. We composited the following layers:
These layers were derived from data acquired from the USGS. This data, the result of an analysis comparing current aquifer levels (2011-2013) to a historic baseline (1950-2013), was brought into ArcGIS, mapped to a color ramp, and exported according to various color breaks.
Atop those we layer an SVG (vector) representing rivers, states, and country boundaries. We source the data from a mix of internal databases, Natural Earth features, and the National Hydrography Dataset. It's prepared in ArcGIS, then styled in Illustrator, and exported as an SVG:
However, for this project, we didn't have data changing over time, so it saved development time to serve up pre-rendered SVGs, using Illustrator for fine-grained cartographic control. It was also a more clear division of labor between myself and Lauren—she prepared static cartography, I worked on its web implementation. In future projects, I could see using both on-the-fly and pre-rendered SVG, as long as everything can be registered to a true geographic space. In this project, no lat/long pairs are referenced in the browser.
States and rivers are one of a few SVG layers that we used. We're loading in another layer of location symbols, leader lines, and curved text (image left). These pieces are activated along with accompanying HTML map labels (image right).
These labels (right) aren't an SVG layer. By rendering HTML, we make these labels more accessible to search engines, more responsive-friendly, and readily editable after export. It saves a lot of time to work out label placement and typography directly in Illustrator (initially GIS software) and then use the NYTimes' ai2html script to generate their placement within the browser. Ai2html is a great tool, and it can export HTML/CSS along with a properly registered underlying base graphic, but it has some limitations. It doesn't export imagery as SVG or transparent PNG well, and while it renders rotated text, it doesn't respect text on a path. Given that, we basically only used ai2html to export uncurved label placement, and exported all other features out manually. That's why our curved text (text on a path) is included within the other SVG layer.
This comprises the map of the aquifer, but we also have an introductory USA locator map, and we've seamlessly integrated this map by zooming out to it:
In this locator map, the red box depicts the exact placement of the aquifer in the zoomed in scale:
That means that if we scale the aquifer raster to the height of the screen, and then zoom that red box to the height of the screen, the two layers will align perfectly.
We achieve this zoom by tweening (transitioning between number values) the viewBox attribute of the locator SVG
<svg viewBox="0 0 288 184"> to a viewBox that represents the red box. This is a surprisingly simple technique:
First we get the viewBox of the locator:
var targetViewbox = $("#gfx-svg-locator svg").getAttribute('viewBox') // results in: "0 0 288 184"
We then use the getBBox() function on the red box SVG element within the locator SVG, and turn it into the string format that the viewbox wants
viewBox="x y width height".
var bbox = $("#L-align_Mobile rect").getBBox(); var sourceViewbox = [bbox.x, bbox.y, bbox.width, bbox.height].join(" ") // results in "99.33000183105469 49.90999984741211 56.1300048828125 97.44999694824219"
We then smoothly transition each of the viewBox values respectively to each other across a scroll distance (detailed below), and the map scales. There's been some great articles written on scaling SVGs if you want to dig deeper:
Meanwhile, while this zooming animation is going on, we're tweening a host of other properties—stroke weights, shape fills, and text visibility, and finally raster visibility to get a seamless transition.
But how are we manipulating layers and properties according to the scroll, in a way that works well across devices?
This scroll-driven interactive has a few goals for a more satisfying UX:
- Minimal autopilot: transition elements only according to scroll movement. Put another way, don't trigger actions that animate on their own by reaching certain thresholds of scroll distance.
- No scrolljacking: use the browser's natural scroll/touch functionality, tied to the
- Maintain good performance across devices.
- Be a responsible parallaxer: don't do things just for animation's sake.
Throughout the scroll distance of the pinned element, scroll-watcher keeps track of percentage distance. While the creators of scroll-watcher use this to control data activation in D3-based interactives, we essentially use this scroll percentage as a vertical timeline to control a sequence of events.
To control event sequencing we're using the very underrated Greensock Animation Platform to tween events. Tweening (in-between-ing) means smoothly interpolating a property from one value to another over a period of time. Interpolation and transitions are something that D3 does well, but I've felt that GSAP does so in a more intuitive way with cleaner code. It's been a while since I didn't use D3 at all in a project, so this was refreshing.
Given that there are a lot of elements changing state over the course of the page we needed a less confusing way to manage this. The page was broken down into active areas--think of a series of invisible yardsticks stacked one after another. If we can track distance travelled across a specific yardstick, we can make tweens occur over these distances. I made these yardsticks a reality when viewing the project in debug mode:
Physically knowing this distance was really helpful in knowing when to trigger what, and I could directly pump those percentage numbers into the application logic. This technique combined with GSAP to handing tweening is actually very similar to what ScrollMagic does.
You can visit the interactive here: http://www.nationalgeographic.com/magazine/2016/08/vanishing-aquifer-interactive-map/