StoryMapJS for Technical Users

Most users will probably use the StoryMapJS authoring tool to create their StoryMaps. But if you want maximum control over StoryMapJS, read on.

Managing StoryMapJS data

StoryMapJS uses JSON data as its native data format. You can load the data from a file on the web, or you can create a javascript object by any other means you like. If you are loading the data from a URL, it must either be on the same server as the page where you are displaying the StoryMap or from a server with correctly configured CORS headers. (The details of cross-domain origin restrictions are out of scope for this document.)

Complete details on the JSON syntax for StoryMapJS is below.

Setting up your page

You'll need to include code something like the following.

<!-- The StoryMap container can go anywhere on the page. Be sure to
    specify a width and height.  The width can be absolute (in pixels) or
    relative (in percentage), but the height must be an absolute value.
    Of course, you can specify width and height with CSS instead -->
<div id="mapdiv" style="width: 100%; height: 600px;"></div>

<!-- Your script tags should be placed before the closing body tag. -->
<link rel="stylesheet" href="https://cdn.knightlab.com/libs/storymapjs/latest/css/storymap.css">
<script type="text/javascript" src="https://cdn.knightlab.com/libs/storymapjs/latest/js/storymap-min.js"></script>

<script>
// storymap_data can be an URL or a Javascript object
var storymap_data = '//media.knightlab.com/StoryMapJS/demo/demo.json';

// certain settings must be passed within a separate options object
var storymap_options = {};

var storymap = new VCO.StoryMap('mapdiv', storymap_data, storymap_options);
window.onresize = function(event) {
    storymap.updateDisplay(); // this isn't automatic
}
</script>

When creating a StoryMap object, certain settings, if you wish to override the defaults, may be passed within the separate options parameter. However, as of StoryMap 0.4.6, you can also specify these directly in the storymap_data JSON, as "top-level" keys.

  • map_type
  • map_subdomains
  • map_as_image
  • map_background_color
  • language
  • zoomify
  • calculate_zoom
  • call_to_action
  • call_to_action_text

Also, any specified fonts must be loaded by the embedding page. View the StoryMap embed tool source code for details.

JSON syntax

StoryMapJS is still in beta, so the JSON format is subject to change. Most changes should be additions, providing backward compatibility.

Map-based storymaps tell stories with geographic locations. The JSON for these StoryMaps have the following structure:

{
    width: integer,                // required for embed tool; width of StoryMap
    height: integer,               // required for embed tool; width of StoryMap
    font_css: string,              // optional; font set
    calculate_zoom: true,              // optional; defaults to true.
    storymap: {
        language: string,          // required; two-letter ISO language code
        map_type: string,          // required
        map_as_image: false,       // required
        map_subdomains: string,    // optional
        slides: [object]           // required; array of slide objects (see below)
    }
}

map_type may be either a custom URL tile template as described in the Leaflet documentation or one of the following coded values:

  • stamen:toner-lite - the default
  • stamen:toner - high-contrast black and white
  • stamen:toner-lines - just the lines (mostly roads) from the Toner style
  • stamen:toner-labels - just the labels (place names and roads) from the Toner style
  • stamen:terrain - map with roads as well as some natural features
  • stamen:watercolor - an artistic representation
  • osm:standard - maps used by OpenStreetMap
  • mapbox:map-id - replace map-id with a Mapbox Map ID (requires a MapBox account)

map_subdomains is only relevant if you specify a custom URL tile template. If needed, it should be specified as a single string, where each character is a valid subdomain substitution (e.g. "abc").

calculate_zoom is optional. StoryMapJS will compute the optimal zoom level for each of your slides so as to keep both the previous and the next map point visible. If you'd rather control the zoom level for each slide, set the calculate_zoom option to false and then be sure to set the zoom property for each slide.

Gigapixel StoryMaps tell stories using large, high-resolution images. The JSON for these StoryMaps have the following structure:

{
    width: integer,                    // required for embed tool; width of StoryMap
    height: integer,                   // required for embed tool; height of StoryMap
    font_css: string,                  // optional; font set for UI controls/messages
    calculate_zoom: true,              // optional; defaults to true *unless* map_as_image is true.
    storymap: {
        language: string,              // required; two-letter ISO language code
        map_type: "zoomify",           // required
        map_as_image: boolean,         // required; omit connecting lines between slide locations
        map_background_color:  string, // optional; hexadecimal color value for map background
        zoomify: {
            path: string,              // required; URL path to zoomable image folder
            width: integer,            // required; maximum width of image
            height: integer,           // required; maximum height of image
            tolerance: decimal         // required; display tolerance
        }
        slides: [object]               // required; array of slide objects (see below)
    }
}

map_as_image gives StoryMap a hint about whether your gigapixel image is a map (such as a historic map) or a non-geographic image. When map_as_image is set to true, StoryMap understands that you are using a non-geographic image. It suppresses the line that connects markers, and it implicitly sets the calculate_zoom option to false, which means that you must make sure to set the zoom property for each of your slides.

For either type of StoryMap:

The language setting specifies the language for user-interface controls and messages. Supported codes can be viewed here.

The font_css value should be specified as an URL to your font CSS file or as "stock:code" (e.g. "stock:amatic-andika"). For an example of how to define a custom font CSS file, see the GitHub repository. The valid values for code above are the parts of the file names in the repository between font. and .css. Examples of the available fonts can be seen in this image.

Each object with the slides array has the following specification:

{
    type: "overview",      // optional; if present must be set to "overview"
    location: {            // required for all slides except "overview" slide
        lat: decimal,      // latitude of point on map
        lon: decimal       // longitude of point on map
    },
    text: {                // optional if media present
        headline: string,
        text: string       // may contain HTML markup
    },
    media: {               // optional if text present
        url: string,       // url for featured media
        caption: string,   // optional; brief explanation of media content
        credit: string     // optional; creator of media content
    }
}

It is recommended that your first slide be an "overview" slide. The map on an overview slide will show the locations of all subsequent slides.

The media URL can come from a number of different services, including YouTube, Flickr, Vimeo, and Twitter. You can get an overview of supported media types by looking at the StoryMapJS source code.