CategoryJavaScript

Roaring to life: How we built our Elwha watershed package

When Lynda Mapes, our environment reporter, came to us with the story of how the Elwha watershed had been recovering after the world’s largest dam removal, we knew we wanted to present it in a way that would make a splash. The final result (GitHub repo) drew heavily on talents from all over the newsroom, ranging from the graphics team’s hand-drawn art to Lynda’s beautiful prose. On the digital side, there were three interesting JavaScript components that deserve more explanation: the watercolor animations, scroll-triggered effects, and FLIP transitions.

You otter be in pictures

Black and white river otter sketch

Black and white base layer

Full color otter sketch

Color “paint” layer

We knew going into this project that we would want to feature the beautiful hand-drawn images of various critters in the Elwha watershed. The final technique is an adaptation of the “lead dust” effect that we used in our Loaded with Lead investigative report. Instead of a single texture that’s used to “reveal” hidden text, we split the sketches into two layers: one base image that only contained the black channel for shading, and another full-color image that gets painted on top. By using intentionally-imperfect circles as our “brushes,” and expanding these circles from randomized positions, the resulting “watercolor” effect helps add a simple splash of life to the static images, without feeling gratuitous or jarring.

Ultimately, what makes this effect possible (and performant) on a range of devices is the canvas createPattern() method, which takes an image and generates a fill pattern object. Most of the time, this is used with smaller images to add texture to a filled path, so that you don’t need to draw and clip the pattern by hand. But in this case, the pattern is the same size as the canvas itself, meaning that we can use this to copy pieces of one image into the canvas in irregular patches–perfect for our watercolor wash. (source code)

Scroll me maybe

Another key part of the presentation is that many animations trigger as they become visible, rewarding readers for scrolling down the page. This is a pretty typical part of news interactive UI these days, but it’s worth looking at how to do it without causing jank.

Our secret weapon for many scroll-triggered effects at the Seattle Times is getBoundingClientRect(), one of the many useful DOM methods that (surprisingly) originated in Internet Explorer. When called on any element, it returns an object with the coordinates for that element relative to the viewport. In other words, it tells you where the object is displayed right now, without having to walk up the DOM for offset values or check the current scroll position. This leads to easy visibility tests like this one:

var bounds = element.getBoundingClientRect();
if (bounds.top < window.innerHeight && bounds.bottom > 0) {
  //element is onscreen in some form
}

getBoundingClientRect() is fast and easy to use for a variety of purposes, and it’s well-supported everywhere. While browsers continue to work to make scrolling smoother, it’s still important to do as little work on scroll listeners as possible, especially when the page may contain many of them (as the Elwha package does). We created a unified scroll notification queue for this project to try to keep the load down. Which brings us to our last animation feature…

FLIP and forget it

I’m a big fan of Paul Lewis’ FLIP animation technique, which leverages the browser to perform smooth animations with as little JavaScript as possible. It’s worth reading the article for more details, but the acronym spells out the basic steps: get the first position, move to the last position, invert the difference through the use of transforms, and then play by removing the offsets.

Elwha feature section

One of our animated feature sections. The animals on the right swap into the main section with a smooth expand effect when clicked.

The nice thing about FLIP is that it’s not only buttery-smooth, but it also adapts well to various lower-level page changes. In this case, when a user clicks on one of the sidebar items to swap between featured animals, we actually move the entire block between two different container elements for styling purposes. But because FLIP works entirely via on-screen coordinates and transforms, none of that  matters. We only have to know the first and last positions to create the transform, and those are easy to get via our old pal getBoundingClientRect().

Although the code for FLIP isn’t hard to write, it comes up often enough (see also: EB-5 visas, teacher pay, and modern dating) that we’ve added a small module to our news app template to make it even easier. The function takes two arguments: an element that you want to animate, and a callback that’s executed between measurements. Just make whatever changes you want during the callback, and the module will figure out the difference and apply transforms to blend between the two. Feel free to take and adapt for your own purposes!

Introducing our news app template

Hi, I’m Thomas Wilburn, newsroom web developer here at The Seattle Times. I work with editors and reporters to tell stories on the web, ranging from data visualizations to custom news applications. One of my most important tools for putting out great projects under deadline pressure is our news app template.

Digital storytelling is not new at The Seattle Times — you only have to look to Sea Change or our election guides to see that — but it hasn’t had a consistent process for development. Some of our news apps were built in Django, some in WordPress, and others in notepad.exe, depending on the staff assigned and their mood at the time. When I joined the newsroom earlier this year, one of my goals was to create a standard platform for digital projects, generating static files for ease of maintenance and low-stress hosting.

The result is a scaffolding system built on top of Grunt and NodeJS for producing news applications with the absolute minimum of friction (editorial or technical). In addition to populating a project with boilerplate HTML, the project initialization process also sets up the following helpful features:

  • A local development server, with live reload integration
  • Lo-dash templates, with some useful built-in helper functions
  • LESS and JavaScript compilation via AMD modules
  • A “watch” server to run build tasks automatically whenever files change
  • Bower pre-configured to install client-side libraries in a standard location
  • The ability to pull data from CSV, JSON, or Google Docs
  • One-command publication to Amazon S3

In many ways, this list is similar to scaffolding solutions from other organizations, including the NPR app template and the Chicago Tribune’s Tarbell. However, being built on NodeJS, the Seattle Times template is a bit easier to set up, and runs on more diverse software (namely, Windows). As a result, it’s been easy to get our web producers working on the same stack that we use for our big projects.

Our experiences using this app scaffolding have been positive so far. Using this scaffolding, we can be up and running on a new project in minutes, and the common structure means that it’s easy to reuse components from one app to another. Fast deployment makes our development faster, and being able to pull from Google Docs makes it easier to bring in editors and reporters. If they can use a spreadsheet, they can edit our interactives. We’ve used it to power many of our online features this year, including “Where the Bidding Wars Are?” and our Oso Landslide timeline. It even runs our Seahawks fan map!

As big proponents of open-source software, our team believes this kind of slick development experience is just too cool to keep to ourselves. So we’ve made our scaffolding available on GitHub under a GPL license. There are a few Seattle Times-specific bits you’ll need to adapt if you use it for yourself, such as our ad and tracking code. But other than that, I think it could be useful for anyone building static sites — inside or outside of a newspaper. If you build something with it, we’d love to hear about it!