Skip to content

Instantly share code, notes, and snippets.

@elenatorro
Last active July 22, 2019 06:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elenatorro/ab00b847d42376a793df770395691d32 to your computer and use it in GitHub Desktop.
Save elenatorro/ab00b847d42376a793df770395691d32 to your computer and use it in GitHub Desktop.
Multiple animation controls
<!DOCTYPE html>
<html>
<head>
<title>Animation | CARTO VL</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<script src="https://libs.cartocdn.com/carto-vl/v1.4/carto-vl.min.js"></script>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.js"></script>
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100,200,400,500" rel="stylesheet">
<style type="text/css">
body {
margin: 0;
}
aside.toolbox {
right: 96px;
position: absolute;
top: 24px;
right: 24px;
min-width: 250px;
max-width: 250px;
max-width: 350px;
z-index: 2;
overflow-wrap: break-word;
}
.box {
width: 320px;
background: #f2f2f2;
z-index: 2;
border-radius: 4px;
padding: 16px;
margin: 0 0 24px;
box-shadow: 0 0px 16px rgba(0, 0, 0, 0.24);
}
section {
display: flex;
flex-direction: row;
justify-content: space-between;
}
section.controls {
margin-top: 15px;
flex-direction: column;
align-items: left;
}
hr {
margin: 15px auto;
}
input[type=range] {
-webkit-appearance: none;
border: 1px solid white;
background: transparent;
border: none;
cursor: pointer;
flex: 1;
padding: auto 10px;
margin: auto 5px;
width: 100%;
}
input[type=range]::-webkit-slider-runnable-track {
height: 3px;
background: #1785FB;
border: none;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
height: 10px;
width: 10px;
border-radius: 50%;
background: #1785FB;
margin-top: -4px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-moz-range-track {
height: 3px;
background: #1785FB;
border: none;
border-radius: 3px;
}
input[type=range]::-moz-range-thumb {
border: none;
height: 10px;
width: 10px;
border-radius: 50%;
background: #1785FB;
}
input[type=range].white-thumb::-moz-range-thumb {
border-radius: 50%;
border: 2px solid #1785FB;
background: white;
height: 12px;
width: 12px;
}
input[type=range].white-thumb::-webkit-slider-thumb {
border-radius: 50%;
border: 3px solid #1785FB;
background: white;
height: 15px;
width: 15px;
margin-top: -6px;
}
input[type=range].white-thumb::-ms-thumb {
border-radius: 50%;
border: 2px solid #1785FB;
background: white;
height: 12px;
width: 12px;
}
input[type=range]:-moz-focusring {
outline: 1px solid white;
outline-offset: -1px;
}
input[type=range]::-ms-track {
height: 3px;
background: transparent;
border-color: transparent;
border-width: 6px 0;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #1785FB;
}
input[type="range"]::-moz-range-progress {
background: #1785FB;
}
input[type=range]::-ms-fill-upper {
background: #ccc;
}
input[type="range"]::-moz-range-track {
background: #ccc;
}
input[type=range]::-ms-thumb {
border: none;
height: 10px;
width: 10px;
border-radius: 50%;
background: #1785FB;
}
input[type="button"] {
width: 36px;
height: 36px;
border-radius: 4px;
border: 0;
box-shadow: none;
color: #fff;
cursor: pointer;
display: inline-flex;
font: 500 12px/20px 'Roboto';
margin: 0;
margin-right: 10px;
}
#map {
flex: 1;
position: absolute;
height: 100%;
width: 100%;
z-index: 0;
}
#js-duration-span {
background: white;
border: 1px solid #ddd;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
}
#js-play-button {
background-color: #1785FB;
background-position: center;
}
#js-pause-button {
background-color: #1785FB;
background-position: center;
}
</style>
</head>
<body>
<div id="map"></div>
<!-- Animation control elements -->
<aside class="toolbox">
<div class="box">
<header>
<h1>Seattle Collisions</h1>
</header>
<section>
<p class="description open-sans">Add animation controls for "play", "pause" and "set" commands</p>
</section>
<section class="controls">
<div>
<button id="js-play-button">Play</button>
<button id="js-pause-button">Pause</button>
</div>
<div>
<p>Animation 1 progress</p>
<input type="range" id="js-time-range-1" min="0" max="1" step="0.01">
</div>
<div>
<p>Animation 2 progress</p>
<input type="range" id="js-time-range-2" min="0" max="1" step="0.01">
</div>
</section>
<br />
<section>
<span id="js-current-time" class="open-sans"></span>
</section>
<hr>
<section>
<span style="margin-right: 5px" class="open-sans">Duration (seconds)</span>
<input class="white-thumb" type="range" id="js-duration-range" min="1" max="60" step="1">
<span style="margin-left: 5px" class="open-sans" id="js-duration-span">10</span>
</section>
</div>
</aside>
<div id="loader">
<div class="CDB-LoaderIcon CDB-LoaderIcon--big">
<svg class="CDB-LoaderIcon-spinner" viewBox="0 0 50 50">
<circle class="CDB-LoaderIcon-path" cx="25" cy="25" r="20" fill="none"></circle>
</svg>
</div>
</div>
<script>
const map = new mapboxgl.Map({
container: 'map',
style: carto.basemaps.darkmatter,
center: [-122.33, 47.61],
zoom: 10,
scrollZoom: false
});
const nav = new mapboxgl.NavigationControl();
map.addControl(nav, 'top-left');
map.addControl(new mapboxgl.FullscreenControl(), 'top-left');
carto.setDefaultAuth({
username: 'cartovl',
apiKey: 'default_public'
});
const source1 = new carto.source.Dataset('seattle_collisions');
const source2 = new carto.source.Dataset('seattle_collisions');
// Define animation viz with variables
const viz1 = new carto.Viz(`
@duration: 30
@animation: animation($incdate, @duration, fade(1, 1))
filter: @animation
color: turquoise
strokeWidth: 0
`);
const viz2 = new carto.Viz(`
@duration: 30
@animation: animation($incdate, @duration, fade(1, 1))
filter: @animation
color: purple
strokeWidth: 0
`);
const layer1 = new carto.Layer('layer1', source1, viz1);
const layer2 = new carto.Layer('layer2', source2, viz2);
layer2.addTo(map);
layer1.addTo(map);
// Get HTML elements
const $playbutton = document.getElementById('js-play-button');
const $pausebutton = document.getElementById('js-pause-button');
const $durationRange = document.getElementById('js-duration-range');
const $timeRange1 = document.getElementById('js-time-range-1');
const $timeRange2 = document.getElementById('js-time-range-2');
const $spanDuration = document.getElementById('js-duration-span');
const $currentTime = document.getElementById('js-current-time');
// Save initial time range value
let last1 = $timeRange1.value;
let last2 = $timeRange2.value;
// Listen to interaction events
$durationRange.addEventListener('change', () => {
const duration = parseInt($durationRange.value, 10);
// Update animation duration
viz1.variables.duration = $spanDuration.innerHTML = duration;
viz2.variables.duration = $spanDuration.innerHTML = duration;
});
$playbutton.addEventListener('click', () => {
// Play the animation
viz1.variables.animation.play()
viz2.variables.animation.play();
});
$pausebutton.addEventListener('click', () => {
// Pause the animation
viz1.variables.animation.pause();
viz2.variables.animation.pause();
});
$timeRange1.addEventListener('change', () => {
// Update animation progress
viz1.variables.animation.setProgressPct($timeRange1.value);
last1 = $timeRange1.value;
});
$timeRange2.addEventListener('change', () => {
// Update animation progress
viz2.variables.animation.setProgressPct($timeRange2.value);
last2 = $timeRange2.value;
});
// Listen to layer events
layer1.on('updated', () => {
if ($timeRange1.value == last1) {
$timeRange1.value = viz1.variables.animation.getProgressPct();
last1 = $timeRange1.value;
}
if ($timeRange2.value == last2) {
$timeRange2.value = viz2.variables.animation.getProgressPct();
last2 = $timeRange2.value;
}
});
carto.on('loaded', [layer1, layer2], hideLoader);
function hideLoader() {
document.getElementById('loader').style.opacity = '0';
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment