Skip to content

Instantly share code, notes, and snippets.

@c16a
Last active June 19, 2018 16:16
Show Gist options
  • Save c16a/6e3916eb8156c3ccfa231c627fd5ab8e to your computer and use it in GitHub Desktop.
Save c16a/6e3916eb8156c3ccfa231c627fd5ab8e to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Animate a point</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=yes' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.45.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.45.0/mapbox-gl.css' rel='stylesheet' />
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.21.2.js"></script>
<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/turf/v2.0.0/turf.min.js' charset='utf-8'></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
var points = [];
class Point {
constructor(id, lat, lon) {
this.id = id;
this.lat = lat;
this.lon = lon;
}
}
mapboxgl.accessToken = 'pk.eyJ1IjoibXVudWt1dGxhIiwiYSI6ImNqaWFoZDE1YzAxdnEzcG54dDd1M3dhbWEifQ.JdHu_4E9Ky3n-73LSUfwdQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [0, 0],
zoom: 2
});
pubnub = new PubNub({
publishKey: '',
subscribeKey: 'sub-c-18580a92-f8cc-11e5-9086-02ee2ddab7fe'
})
pubnub.addListener({
message: pubnubListener,
presence: function (presenceEvent) {
// handle presence
}
});
map.on('load', () => {
pubnub.subscribe({
channels: ['exp-channel']
});
})
function getCenter(points) {
var minLat = Math.min(...points.map(p => p.lat));
var maxLat = Math.max(...points.map(p => p.lat));
var minLong = Math.min(...points.map(p => p.lon));
var maxLong = Math.max(...points.map(p => p.lon));
var centerLong = (maxLong - minLong) / 2;
var centerLat = (maxLat - minLat) / 2;
return [centerLat, centerLong];
}
// San Francisco
var origin = [-122.414, 37.776];
function pubnubListener(m) {
var point = JSON.parse(m.message);
var coords = [parseFloat(point["Latitude"]), parseFloat(point["Longitude"])];
var deviceId = point["DeviceID"];
console.log(coords);
console.log(deviceId);
var pointObj = new Point(deviceId, coords[0], coords[1]);
var center = getCenter(points);
if (points.length > 1) {
map.setCenter(center);
}
var point = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"name": deviceId,
"icon": "monument"
},
"geometry": {
"type": "Point",
"coordinates": coords
}
}]
};
var oldPoint = points.find(p => p.id == deviceId)
var objIndex = points.findIndex(p => p.id == deviceId)
if (oldPoint) {
console.log("old point")
// If it's an old point
var route = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[oldPoint.lat, oldPoint.lon],
[coords[0], coords[1]]
]
}
}]
};
// Calculate the distance in kilometers between route start/end point.
var lineDistance = turf.lineDistance(route.features[0], 'kilometers');
var arc = [];
var steps = 200;
// Draw an arc between the `origin` & `destination` of the two points
for (var i = 0; i < lineDistance; i += lineDistance / steps) {
var segment = turf.along(route.features[0], i, 'kilometers');
arc.push(segment.geometry.coordinates);
}
// Update the route with calculated arc coordinates
route.features[0].geometry.coordinates = arc;
// Used to increment the value of the point measurement against the route.
var counter = 0;
function animate() {
// Update point geometry to a new position based on counter denoting
// the index to access the arc.
point.features[0].geometry.coordinates = route.features[0].geometry.coordinates[counter];
// Update the source with this new data.
map.getSource('points-' + deviceId).setData(point);
// Request the next frame of animation so long the end has not been reached.
if (counter < steps) {
requestAnimationFrame(animate);
}
counter = counter + 1;
}
// Reset the counter
counter = 0;
// Restart the animation.
animate(counter);
points[objIndex].lat = coords[0];
points[objIndex].lon = coords[1];
} else {
console.log("New point")
map.addLayer({
"id": "points-" + deviceId,
"type": "symbol",
"source": {
"type": "geojson",
"data": point
},
"layout": {
"icon-image": "{icon}-15",
"text-field": "{title}",
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
"text-offset": [0, 0.6],
"text-anchor": "top"
}
});
points.push(pointObj);
map.on('click', 'points-' + deviceId, function (e) {
new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(e.features[0].properties.name)
.addTo(map);
});
// Change the cursor to a pointer when the mouse is over the states layer.
map.on('mouseenter', 'points-' + deviceId, function () {
map.getCanvas().style.cursor = 'pointer';
});
// Change it back to a pointer when it leaves.
map.on('mouseleave', 'points-' + deviceId, function () {
map.getCanvas().style.cursor = '';
});
var center = getCenter(points);
map.setCenter(center);
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment