= [
cities name: "Brisbane", lat: -27.467778, lon: 153.028056 },
{ name: "New Delhi", lat: 28.613889, lon: 77.208889 },
{ name: "Singapore", lat: 1.283333, lon: 103.833333 },
{ name: "Istanbul", lat: 41.013611, lon: 28.955 },
{ name: "Paris", lat: 48.856667, lon: 2.352222 },
{ name: "Nairobi", lat: -1.286389, lon: 36.817222 },
{ name: "São Paulo", lat: -23.55, lon: -46.633333 },
{ name: "Montreal", lat: 45.508889, lon: -73.554167 },
{ name: "Houston", lat: 29.762778, lon: -95.383056 },
{ name: "Vancouver", lat: 49.260833, lon: -123.113889 },
{ name: "Honolulu", lat: 21.306944, lom: -157.858333 }
{ ]
OJS Variables
Closeread makes scrolling progress available to users as Observable JavasScript variables, so you can create closeread sections with interactive graphics that change as you scroll.
Let’s use this functionality to make a visualization of a globe. Before we start, let’s define some cities that we’ll plot on that glove. Here I’ve done it in OJS, but you could easily make an R or Python data frame available using ojs_define()
(or load a CSV from elsewhere):
Now let’s load data that describes the shape of the continents.
= FileAttachment("naturalearth-land-110m.geojson").json() world
The cities above wrap the entire globe, so to view them all we’ll need to be give the user the ability to spin the globe. We’ll map the progress of the user’s scroll, stored in a variable called crProgressBlock
, to a variable called angle
. The scale.Linear
function handles the linear mapping of crProgressBlock
going from 0 to 1 to angle
going from -180 to 0.
= d3.scaleLinear()
angleScale1 .domain([0, 1])
.range([-180, 0])
.clamp(true)
= angleScale1(crProgressBlock) angle1
To see the OJS code that actually creates the globe, look into the source of this document. Here is the result:
As you back and forth over this closeread section, note the values of the all six ojs variables that closeread makes available in ojs code cells:
crActiveSticky
: name of the active stickycrTriggerIndex
: index of the active triggercrTriggerProgress
: progress of the active trigger block from 0 to 1crDirection
: either"down"
or"up"
, depending on the direction a user is scrollingcrProgressBlock
: progress of the active spanning progress block from 0 to 1
To demonstrate the use of other ojs variables, we’ll recreate the spinning behavior by a more creative mapping of crTriggerIndex
and crTriggerProgress
to form angle2
. [This second globe demonstrates some interesting behavior: angle2
was actually changing as a result of the two triggers used in making the first globe. ]
Eu in culpa officia cupidatat nostrud laborum do consequat officia Lorem tempor consectetur pariatur sunt. Veniam culpa dolore laborum nostrud ipsum pariatur ipsum dolore consectetur commodo ex. Non culpa deserunt voluptate. Amet excepteur incididunt deserunt pariatur velit labore do sunt occaecat eiusmod. Tempor proident sint exercitation culpa incididunt sunt proident sunt reprehenderit. Sint ipsum qui id nisi quis officia in. Anim velit minim fugiat qui dolor enim occaecat amet excepteur do aliqua ex adipisicing laboris labore.
Culpa aute sint aliquip in aute enim cillum in exercitation cupidatat ex cupidatat mollit dolore ut. Et culpa minim laborum in ipsum laborum velit laboris fugiat ad culpa cillum. Sit nulla eu minim in nulla. Nulla esse sint occaecat eiusmod in irure in dolor veniam pariatur laboris consectetur sunt laboris excepteur. Dolor dolore ad incididunt consequat. Ad elit ullamco veniam cillum reprehenderit pariatur pariatur nisi ea. Pariatur quis ut deserunt eiusmod ipsum magna ullamco.
Amet velit ea ex. Pariatur anim laboris fugiat labore velit ullamco aute aliquip incididunt. Ut labore voluptate exercitation esse aliquip dolor ex magna occaecat ullamco nisi sit non quis nulla. Elit qui do sunt consectetur officia sint veniam incididunt laboris aute eu nisi qui. Et voluptate consequat sunt commodo dolor dolor veniam minim incididunt culpa anim nulla duis est. Excepteur occaecat tempor veniam magna sit sunt enim sint exercitation dolore fugiat nulla consequat proident. Reprehenderit consequat reprehenderit amet dolore cillum elit dolore officia enim dolor.