Please use the new interactive atom template for all future interactives: https://github.com/guardian/interactive-atom-template-2019
npm install
npm start
Go to http://localhost:8000
Fill out config.json
:
{
"title": "Title of your interactive",
"docData": "Any associated external data",
"path": "year/month/unique-title"
}
Then run
npm run deploy
You can check the deploy log by running
npm run log
NOTE: Updates can take up to 30 seconds to show in the logs
Run the command below, copy the URL into Composer and click embed.
npm run url
We use SASS for better CSS, Babel for next generation JavaScript and Rollup for bundling.
Interactive atoms have three components:
- CSS -
src/css/main.scss
- HTML -
src/render.js
should generate some HTML (by default returns the contents ofsrc/templates/main.html
) - JS -
src/js/main.js
, by default this simply loadssrc/js/app.js
Resources must be loaded with absolute paths, otherwise they won't work when deployed.
Use the template string <%= path %>
in any CSS, HTML or JS, it will be replaced
with the correct absolute path.
<img src="<%= path %>/assets/image.png" />
.test {
background-image: url('<%= path %>/assets/image.png');
}
var url = '<%= path %>/assets/image.png';
Interactive atoms are baked into the initial page response so you need to be careful about how much weight you are adding. While CSS and HTML are unlikely to ever be that large, you should worry about the size of your JS.
The difference between src/js/main.js
and src/js/app.js
is that the former is baked into
the page and the latter is not. Never load large libraries (such as d3) in src/js/main.js
.
In most cases, the majority of the work should happen in src/js/app.js
and src/js/main.js
should be reserved for simple initialisation.
We have a ready-built component for loading JSON files. It uses the Fetch api and includes the necessary polyfills to work on most browsers. It is only designed to be used client-side.
For example:
import loadJson from '../components/load-json/'
loadJson("https://interactive.guim.co.uk/...)
.then((data) => {
console.log(data);
})
The ScrollyTeller module is written as a class. You can check the scrollyteller-example branch for a full example.
Import it as normal into your project
import ScrollyTeller from "./scrollyteller"
Instantiate a new instance of it and pass in a config object
const scrolly = new ScrollyTeller({
parent: document.querySelector("#scrolly-1"),
triggerTop: 1/3, // percentage from the top of the screen that the trigger should fire
triggerTopMobile: 0.75,
transparentUntilActive: true
});
Add your trigger points:
scrolly.addTrigger({num: 1, do: () => {
console.log("Console log 1");
}});
And finally start off the scroll listener:
scrolly.watchScroll();
You'll also need to comment in the _scrolly.scss code in main.scss, as well as structuring your HTML in the following way:
<div id="scrolly-1">
<div class="scroll-wrapper">
<div class="scroll-inner">
<svg id="data-viz">
</svg>
</div>
<div class="scroll-text">
<div class="scroll-text__inner">
<div class="scroll-text__div">
<p>1</p>
</div>
</div>
<div class="scroll-text__inner">
<div class="scroll-text__div">
<p>2</p>
</div>
</div>
<div class="scroll-text__inner">
<div class="scroll-text__div">
<p>3</p>
</div>
</div>
</div>
</div>
</div>
Support information can be found in SUPPORT.md.