Built with blockbuilder.org
xxxxxxxxxx
<html>
<head>
<meta charset='utf-8' />
<title>Scrollytelling Template</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css' rel='stylesheet' />
<script src="https://unpkg.com/intersection-observer@0.5.1/intersection-observer.js"></script>
<script src="https://unpkg.com/scrollama"></script>
<style>
body {
margin:0;
padding:0;
font-family: sans-serif;
}
a, a:hover, a:visited {
color: #41abf1;
}
#map {
top:0;
height: 100vh;
width:100vw;
position: fixed;
z-index: -5;
}
#header {
margin: 3vh auto;
width: 90vw;
padding: 2vh;
text-align: center;
}
#footer {
width: 100%;
min-height: 5vh;
padding-top: 2vh;
padding-bottom: 2vh;
text-align: center;
line-height: 25px;
font-size: 13px;
}
#features {
padding-top: 10vh;
padding-bottom: 10vh;
z-index: 100;
}
.centered {
width: 50vw;
margin: 0 auto;
}
.lefty {
width: 33vw;
margin-left: 5vw;
}
.righty {
width: 33vw;
margin-left: 62vw;
}
.light {
color: #ffffff;
background-color: #696969;
}
.dark {
color: #fafafa;
background-color: #444;
}
.step {
padding-bottom: 50vh;
/* margin-bottom: 10vh; */
opacity: 0.25;
}
.step.active {
opacity: 0.9;
}
.step div {
padding: 25px 50px;
line-height: 25px;
font-size: 13px;
}
.step img {
width: 100%;
}
@media (max-width: 750px) {
#features {
width: 90vw;
margin: 0 auto;
}
}
</style>
</head>
<body>
<div id="map"></div>
<div id="story"></div>
<script src="./config.js"></script>
<script>
var layerTypes = {
'fill': ['fill-opacity'],
'line': ['line-opacity'],
'circle': ['circle-opacity', 'circle-stroke-opacity'],
'symbol': ['icon-opacity', 'text-opacity'],
'raster': ['raster-opacity'],
'fill-extrusion': ['fill-extrusion-opacity']
}
var alignments = {
'left': 'lefty',
'center': 'centered',
'right': 'righty'
}
function getLayerPaintType(layer) {
var layerType = map.getLayer(layer).type;
return layerTypes[layerType];
}
function setLayerOpacity(layer) {
var paintProps = getLayerPaintType(layer.layer);
paintProps.forEach(function(prop) {
map.setPaintProperty(layer.layer, prop, layer.opacity);
});
}
var story = document.getElementById('story');
var features = document.createElement('div');
features.classList.add(alignments[config.alignment]);
features.setAttribute('id', 'features');
var header = document.createElement('div');
if (config.title) {
var titleText = document.createElement('h1');
titleText.innerText = config.title;
header.appendChild(titleText);
}
if (config.subtitle) {
var subtitleText = document.createElement('h2');
subtitleText.innerText = config.subtitle;
header.appendChild(subtitleText);
}
if (config.byline) {
var bylineText = document.createElement('p');
bylineText.innerHTML = 'created by <a href="https://github.com/Hirosaji">' + config.byline + '</a>';
header.appendChild(bylineText);
}
if (header.innerText.length > 0) {
header.classList.add(config.theme);
header.setAttribute('id', 'header');
story.appendChild(header);
}
config.chapters.forEach((record, idx) => {
var container = document.createElement('div');
var chapter = document.createElement('div');
if (record.title) {
var title = document.createElement('h3');
title.innerText = record.title;
chapter.appendChild(title);
}
if (record.image) {
var image = new Image();
image.src = record.image;
chapter.appendChild(image);
}
if (record.description) {
var story = document.createElement('p');
story.innerHTML = record.description;
chapter.appendChild(story);
}
container.setAttribute('id', record.id);
container.classList.add('step');
if (idx === 0) {
container.classList.add('active');
}
chapter.classList.add(config.theme);
container.appendChild(chapter);
features.appendChild(container);
});
story.appendChild(features);
var footer = document.createElement('div');
if (config.footer) {
var footerText = document.createElement('p');
footerText.innerHTML = config.footer;
footer.appendChild(footerText);
}
if (footer.innerText.length > 0) {
footer.classList.add(config.theme);
footer.setAttribute('id', 'footer');
story.appendChild(footer);
}
mapboxgl.accessToken = config.accessToken;
const transformRequest = (url) => {
const hasQuery = url.indexOf("?") !== -1;
const suffix = hasQuery ? "&pluginName=journalismScrollytelling" : "?pluginName=journalismScrollytelling";
return {
url: url + suffix
}
}
var map = new mapboxgl.Map({
container: 'map',
style: config.style,
center: config.chapters[0].location.center,
zoom: config.chapters[0].location.zoom,
bearing: config.chapters[0].location.bearing,
pitch: config.chapters[0].location.pitch,
scrollZoom: false,
transformRequest: transformRequest
});
var marker = new mapboxgl.Marker();
if (config.showMarkers) {
marker.setLngLat(config.chapters[0].location.center).addTo(map);
}
// instantiate the scrollama
var scroller = scrollama();
map.on("load", function() {
// setup the instance, pass callback functions
scroller
.setup({
step: '.step',
offset: 0.5,
progress: true
})
.onStepEnter(response => {
var chapter = config.chapters.find(chap => chap.id === response.element.id);
response.element.classList.add('active');
map.flyTo(chapter.location);
if (config.showMarkers) {
marker.setLngLat(chapter.location.center);
}
if (chapter.onChapterEnter.length > 0) {
chapter.onChapterEnter.forEach(setLayerOpacity);
}
})
.onStepExit(response => {
var chapter = config.chapters.find(chap => chap.id === response.element.id);
response.element.classList.remove('active');
if (chapter.onChapterExit.length > 0) {
chapter.onChapterExit.forEach(setLayerOpacity);
}
});
});
// setup resize event
window.addEventListener('resize', scroller.resize);
</script>
</body>
</html>
https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js
https://unpkg.com/intersection-observer@0.5.1/intersection-observer.js
https://unpkg.com/scrollama