Built with blockbuilder.org
Created
May 21, 2019 08:17
-
-
Save mastersigat/2c0514819a1e57040ae7cf7e35c66f05 to your computer and use it in GitHub Desktop.
#MapboxGL / Carte itinéraire
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset='utf-8' /> | |
<title>Animate a point along a route</title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.54.0/mapbox-gl.css' rel='stylesheet' /> | |
<style> | |
body { margin:0; padding:0; } | |
#map { position:absolute; top:0; bottom:0; width:100%; } | |
</style> | |
</head> | |
<body> | |
<style> | |
.overlay { | |
position: absolute; | |
top: 10px; | |
left: 10px; | |
} | |
.overlay button { | |
font:600 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif; | |
background-color: #3386c0; | |
color: #fff; | |
display: inline-block; | |
margin: 0; | |
padding: 10px 20px; | |
border: none; | |
cursor: pointer; | |
border-radius: 3px; | |
} | |
.overlay button:hover { | |
background-color:#4ea0da; | |
} | |
</style> | |
<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/turf/v2.0.0/turf.min.js' charset='utf-8'></script> | |
<div id='map'></div> | |
<div class='overlay'> | |
<button id='replay'>Relancer le trajet</button> | |
</div> | |
<script> | |
// Appel de la carte | |
mapboxgl.accessToken = 'pk.eyJ1IjoibmluYW5vdW4iLCJhIjoiY2pjdHBoZGlzMnV4dDJxcGc5azJkbWRiYSJ9.o4dZRrdHcgVEKCveOXG1YQ'; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
style: 'mapbox://styles/mapbox/streets-v11', | |
center: [-1.7031,48.1183], | |
zoom: 16.3, | |
pitch: 45, | |
bearing:30 | |
}); | |
// Itinéraire (Geojson) | |
var route = { | |
"type": "FeatureCollection", | |
"features": [{ | |
"type": "Feature", | |
"geometry": { | |
"type": "LineString", | |
"coordinates": [ | |
[ | |
-1.703691, | |
48.121242 | |
], | |
[ | |
-1.703718, | |
48.120525 | |
], | |
[ | |
-1.703235, | |
48.120515 | |
], | |
[ | |
-1.70324, | |
48.119881 | |
], | |
[ | |
-1.703342, | |
48.119881 | |
], | |
[ | |
-1.703358, | |
48.119404 | |
], | |
[ | |
-1.70301, | |
48.119236 | |
], | |
[ | |
-1.702275, | |
48.119215 | |
], | |
[ | |
-1.702248, | |
48.118867 | |
], | |
[ | |
-1.702253, | |
48.118506 | |
], | |
[ | |
-1.702312, | |
48.117578 | |
], | |
[ | |
-1.702334, | |
48.11742 | |
], | |
[ | |
-1.703407, | |
48.117456 | |
], | |
[ | |
-1.703407, | |
48.117009 | |
] | |
] | |
} | |
}] | |
}; | |
// A single point that animates along the route. | |
// Coordinates are initially set to origin. | |
var point = { | |
"type": "FeatureCollection", | |
"features": [{ | |
"type": "Feature", | |
"properties": {}, | |
"geometry": { | |
"type": "Point", | |
"coordinates": origin | |
} | |
}] | |
}; | |
// Calculate the distance in kilometers between route start/end point. | |
var lineDistance = turf.lineDistance(route.features[0], 'kilometers'); | |
var arc = []; | |
// Number of steps to use in the arc and animation, more steps means | |
// a smoother arc and animation, but too many steps will result in a | |
// low frame rate | |
var steps = 500; | |
// 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; | |
map.on('load', function () { | |
// Add a source and layer displaying a point which will be animated in a circle. | |
map.addSource('route', { | |
"type": "geojson", | |
"data": route | |
}); | |
map.addSource('point', { | |
"type": "geojson", | |
"data": point | |
}); | |
map.addLayer({ | |
"id": "route", | |
"source": "route", | |
"type": "line", | |
"paint": { | |
"line-width": 4, | |
"line-color": "#007cbf" | |
} | |
}); | |
map.addLayer({ | |
"id": "point", | |
"source": "point", | |
"type": "circle", | |
"paint": { | |
"circle-radius": 9, | |
"circle-color": "#007cbf", | |
"circle-stroke-color": "#FFFFFF", | |
"circle-stroke-width": 2.5 } | |
}); | |
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]; | |
// Calculate the bearing to ensure the icon is rotated to match the route arc | |
// The bearing is calculate between the current point and the next point, except | |
// at the end of the arc use the previous point and the current point | |
point.features[0].properties.bearing = turf.bearing( | |
turf.point(route.features[0].geometry.coordinates[counter >= steps ? counter - 1 : counter]), | |
turf.point(route.features[0].geometry.coordinates[counter >= steps ? counter : counter + 1]) | |
); | |
// Update the source with this new data. | |
map.getSource('point').setData(point); | |
// Request the next frame of animation so long the end has not been reached. | |
if (counter < steps) { | |
requestAnimationFrame(animate); | |
} | |
counter = counter + 1; | |
} | |
document.getElementById('replay').addEventListener('click', function() { | |
// Set the coordinates of the original point back to origin | |
point.features[0].geometry.coordinates = origin; | |
// Update the source layer | |
map.getSource('point').setData(point); | |
// Reset the counter | |
counter = 0; | |
// Restart the animation. | |
animate(counter); | |
}); | |
// Start the animation. | |
animate(counter); | |
var layers = map.getStyle().layers; | |
var labelLayerId; | |
for (var i = 0; i < layers.length; i++) { | |
if (layers[i].type === 'symbol' && layers[i].layout['text-field']) { | |
labelLayerId = layers[i].id; | |
break; | |
} | |
} | |
map.addLayer({ | |
'id': '3d-buildings', | |
'source': 'composite', | |
'source-layer': 'building', | |
'filter': ['==', 'extrude', 'true'], | |
'type': 'fill-extrusion', | |
'minzoom': 15, | |
'paint': { | |
'fill-extrusion-color': '#aaa', | |
// use an 'interpolate' expression to add a smooth transition effect to the | |
// buildings as the user zooms in | |
'fill-extrusion-height': [ | |
"interpolate", ["linear"], ["zoom"], | |
15, 0, | |
15.05, ["get", "height"] | |
], | |
'fill-extrusion-base': [ | |
"interpolate", ["linear"], ["zoom"], | |
15, 0, | |
15.05, ["get", "min_height"] | |
], | |
'fill-extrusion-opacity': .6 | |
} | |
}, labelLayerId); | |
map.loadImage("https://i.imgur.com/MK4NUzI.png", function(error, image) { | |
if (error) throw error; | |
map.addImage("custom-marker", image); | |
/* Style layer: A style layer ties together the source and image and specifies how they are displayed on the map. */ | |
map.addLayer({ | |
id: "markers", | |
type: "symbol", | |
/* Source: A data source specifies the geographic coordinate where the image marker gets placed. */ | |
source: { | |
type: "geojson", | |
data: { | |
type: 'FeatureCollection', | |
features: [ | |
{ | |
type: 'Feature', | |
properties: {}, | |
geometry: { | |
type: "Point", | |
coordinates: [-1.703407, 48.117009] | |
}, | |
properties: { | |
"title": "MSHB", | |
"description": "Salle 108 / 1er étage" | |
} | |
} | |
] | |
} | |
}, | |
layout: { | |
"icon-image": "custom-marker", | |
} | |
}); | |
}); | |
}); | |
var popup = new mapboxgl.Popup({ | |
closeButton: false, | |
closeOnClick: false }); | |
map.on('mousemove', function(e) { | |
var features = map.queryRenderedFeatures(e.point, { layers: ['markers'] }); | |
// Change the cursor style as a UI indicator. | |
map.getCanvas().style.cursor = (features.length) ? 'pointer' : ''; | |
if (!features.length) { | |
popup.remove(); | |
return; } | |
var feature = features[0]; | |
popup.setLngLat(feature.geometry.coordinates) | |
.setHTML('<h2>' + feature.properties.title + '</h2>' | |
+ feature.properties.description ) .addTo(map); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment