Skip to content

Instantly share code, notes, and snippets.

@brunob
Last active September 25, 2019 12:13
Show Gist options
  • Save brunob/c7ad54d2487d92b066cb03c1923eed4e to your computer and use it in GitHub Desktop.
Save brunob/c7ad54d2487d92b066cb03c1923eed4e to your computer and use it in GitHub Desktop.
Boat animated track - 2019_09_07
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Le Zigomar !</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
crossorigin=""></script>
<script src="https://calvinmetcalf.github.io/leaflet-ajax/dist/leaflet.ajax.js"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
.info { padding: 6px 8px; font: 14px/16px Arial, Helvetica, sans-serif; background: rgba(255,255,255,0.8); box-shadow: 0 0 15px rgba(0,0,0,0.2); border-radius: 4px; }
.info p { margin-top: 0; }
.info #speed { background: #d7301f; height: 4px; width: 0; transition: all 0.5s ease; }
.glyphicon { display: inline-block; width: 16px; height: 16px; background-size: 16px; }
.glyphicon-globe { background-image: url(earth.svg); }
.glyphicon-target { background-image: url(target.svg); }
.glyphicon-play { background-image: url(play.svg); }
.glyphicon-pause { background-image: url(pause.svg); }
.glyphicon-replay { background-image: url(replay.svg); }
.glyphicon-time { background-image: url(time.svg); }
</style>
</head>
<body>
<div id="map"></div>
<script>
var bounds;
var map = L.map('map', {
center: [48.31356955685135, -4.523620605468751],
zoom: 10,
playing: false,
tracking: false
});
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
subdomains: 'abcd',
maxZoom: 19
}).addTo(map);
L.Util.ajax('2019_09_07.json').then(function(data){
var bounds = L.geoJSON(data).getBounds();
map.fitBounds(bounds);
var trackControl = L.control({position: 'topright'});
trackControl.onAdd = function(map) {
var container = L.DomUtil.create('div', 'leaflet-bar');
var animButton = L.DomUtil.create('a', 'glyphicon glyphicon-play', container);
animButton.setAttribute('role', 'button');
animButton.title = 'Start, pause or replay the animation';
animButton.setAttribute('aria-label', animButton.title);
animButton.setAttribute('id', 'animButton');
// usefull ?
L.DomEvent.on(animButton, 'click', L.DomEvent.stopPropagation);
L.DomEvent.on(animButton, 'click', L.DomEvent.preventDefault);
//
L.DomEvent.on(animButton, 'click', function() {
// Play
if (L.DomUtil.hasClass(animButton, 'glyphicon-play') === true) {
L.DomUtil.setClass(animButton, 'glyphicon glyphicon-pause');
map.playing = true;
window.requestAnimationFrame(addSegment);
}
// Pause
else if (L.DomUtil.hasClass(animButton, 'glyphicon-pause') === true) {
L.DomUtil.setClass(animButton, 'glyphicon glyphicon-play');
map.playing = false;
}
// Replay
else {
L.DomUtil.setClass(animButton, 'glyphicon glyphicon-pause');
map.playing = true;
i = 2;
window.requestAnimationFrame(addSegment);
}
}, this);
var trackButton = L.DomUtil.create('a', 'glyphicon glyphicon-target', container);
trackButton.setAttribute('role', 'button');
trackButton.title = 'Click to track the boats. Click again to zoom out to full view';
trackButton.setAttribute('aria-label', animButton.title);
// usefull ?
L.DomEvent.on(trackButton, 'click', L.DomEvent.stopPropagation);
L.DomEvent.on(trackButton, 'click', L.DomEvent.preventDefault);
//
L.DomEvent.on(trackButton, 'click', function() {
if (L.DomUtil.hasClass(trackButton, 'glyphicon-target') === true) {
L.DomUtil.setClass(trackButton, 'glyphicon glyphicon-globe');
map.setView(position._latlng, 15);
map.tracking = true;
} else {
L.DomUtil.setClass(trackButton, 'glyphicon glyphicon-target');
map.fitBounds(bounds);
map.tracking = false;
};
}, this);
return container;
}
trackControl.addTo(map);
var maxSpeed = Math.max.apply(Math, data.features.map(function(o) { return o.properties.speed; }));
var info = L.control({position: 'bottomright'});
info.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info');
// https://stackoverflow.com/a/4020842 / find max value in array with js
var time = new Date(data.features[0].properties.time.replace(/\//g, '-').slice(0, -3)).toTimeString().split(' ')[0];
div.innerHTML = '<p id="chrono"><span class="glyphicon glyphicon-time" aria-hidden="true"></span> Time <span id="time">' + time +'</span></p><p>Speed (max ' + Math.round(maxSpeed * 1.94384 * 100) / 100 + ' knots)</p><p id="speed"></p>';
return div;
};
info.addTo(map);
var stylePoint = {
radius: 30,
fillColor: "#d7301f",
fillOpacity: 1,
color: "#d7301f"
};
var point_1 = new L.LatLng(data.features[0].geometry.coordinates[1], data.features[0].geometry.coordinates[0]);
var point_2 = new L.LatLng(data.features[1].geometry.coordinates[1], data.features[1].geometry.coordinates[0]);
var pointList = [point_1, point_2];
var trailLine = L.polyline(pointList, {color: '#d7301f', weight: 1.5}).addTo(map);
var trackLine = L.polyline(pointList, {color: '#d7301f', weight: 1, opacity: 0.2}).addTo(map);
var position = L.circle([data.features[0].geometry.coordinates[1], data.features[0].geometry.coordinates[0]], stylePoint).addTo(map);
var i = 2;
function draw(layer, polyline, position, splice) {
position._latlng.lat = layer.features[i].geometry.coordinates[1];
position._latlng.lng = layer.features[i].geometry.coordinates[0];
position.redraw();
var point_n = new L.LatLng(layer.features[i].geometry.coordinates[1], layer.features[i].geometry.coordinates[0]);
if (polyline._latlngs.length < 11) {
polyline.addLatLng(point_n);
}
else {
if (splice) {
polyline.getLatLngs().splice(0, 1);
}
polyline.addLatLng(point_n);
}
if (map.tracking === true) {
map.setView(position._latlng, 15);
}
}
function addSegment() {
var time = L.DomUtil.get('time');
var speed = L.DomUtil.get('speed');
if (i++ < data.features.length - 1) {
draw(data, trailLine, position, true);
draw(data, trackLine, position, false);
if (i%6==0) {
time.innerHTML = new Date(data.features[i].properties.time.replace(/\//g, '-').slice(0, -3)).toTimeString().split(' ')[0];
speed.setAttribute('style', 'width: ' + data.features[i].properties.speed * 100 / maxSpeed + '%');
}
} else {
map.playing = false;
L.DomUtil.setClass(L.DomUtil.get('animButton'), 'glyphicon glyphicon-replay');
trailLine.getLatLngs().splice(0, 11);
L.DomUtil.get('speed').setAttribute('style', 'width: 0');
}
if(map.playing){
window.requestAnimationFrame(addSegment);
}
}
});
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>target</title>
<path d="M32 14h-3.154c-0.864-5.57-5.276-9.982-10.846-10.846v-3.154h-4v3.154c-5.57 0.864-9.982 5.276-10.846 10.846h-3.154v4h3.154c0.864 5.57 5.276 9.982 10.846 10.846v3.154h4v-3.154c5.57-0.864 9.982-5.276 10.846-10.846h3.154v-4zM24.776 14h-3.118c-0.603-1.705-1.953-3.056-3.658-3.658v-3.118c3.36 0.765 6.010 3.416 6.776 6.776zM16 18c-1.105 0-2-0.895-2-2s0.895-2 2-2c1.105 0 2 0.895 2 2s-0.895 2-2 2zM14 7.224v3.118c-1.705 0.603-3.056 1.953-3.658 3.658h-3.118c0.765-3.36 3.416-6.010 6.776-6.776zM7.224 18h3.118c0.603 1.705 1.953 3.056 3.658 3.658v3.118c-3.36-0.765-6.010-3.416-6.776-6.776zM18 24.776v-3.118c1.705-0.603 3.056-1.953 3.658-3.658h3.118c-0.765 3.36-3.416 6.010-6.776 6.776z"></path>
</svg>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment