js first commit
This commit is contained in:
266
src/map.js
Normal file
266
src/map.js
Normal file
@ -0,0 +1,266 @@
|
||||
mapboxgl.accessToken = config.mapboxKey;
|
||||
const owmKey = config.owmKey
|
||||
|
||||
var map = new mapboxgl.Map({
|
||||
container: 'map',
|
||||
style: {
|
||||
"glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
|
||||
"light": {
|
||||
"anchor": "viewport",
|
||||
"color": "white",
|
||||
"intensity": 0.1
|
||||
},
|
||||
'version': 8,
|
||||
'sources': {
|
||||
'default-background': {
|
||||
'type': 'raster',
|
||||
'tiles': [
|
||||
//'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/VIIRS_CityLights_2012/default//GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpg'
|
||||
//'https://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer/tile/{z}/{y}/{x}'
|
||||
//'https://stamen-tiles-b.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg'
|
||||
'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'
|
||||
],
|
||||
'tileSize': 256
|
||||
}
|
||||
},
|
||||
'layers': [{
|
||||
id: 'background',
|
||||
type: 'background',
|
||||
paint: {
|
||||
'background-color': '#ffffff'
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 'default-background',
|
||||
'type': 'raster',
|
||||
'source': 'default-background',
|
||||
'minzoom': 0,
|
||||
'maxzoom': 18
|
||||
}
|
||||
]
|
||||
},
|
||||
center: [0, 20],
|
||||
zoom: 2,
|
||||
attributionControl: false
|
||||
|
||||
});
|
||||
//prevent world duplication
|
||||
map.setRenderWorldCopies(status === 'false')
|
||||
|
||||
map.on('load', function () {
|
||||
//displaying clouds from OpenWeatherMap free API not enough
|
||||
|
||||
// map.addSource('clouds', {
|
||||
// 'type': 'raster',
|
||||
// 'tiles': [
|
||||
// 'https://tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid='+owmKey+''
|
||||
// ],
|
||||
// 'tileSize': 256
|
||||
// });
|
||||
|
||||
// map.addLayer({
|
||||
// 'id': 'clouds',
|
||||
// 'type': 'raster',
|
||||
// 'source': 'clouds',
|
||||
// 'minzoom': 0,
|
||||
// 'maxzoom': 10,
|
||||
// 'paint':{
|
||||
// 'raster-opacity':0.5
|
||||
// }
|
||||
// });
|
||||
|
||||
//loading icons and colors, too lazy to make a loop, to change.
|
||||
map.loadImage('src/img/plane-FFE419.png',
|
||||
function (error, image) {
|
||||
if (error) throw error;
|
||||
map.addImage('plane-FFE419', image);
|
||||
})
|
||||
map.loadImage('src/img/plane-66FF00.png',
|
||||
function (error, image) {
|
||||
if (error) throw error;
|
||||
map.addImage('plane-66FF00', image);
|
||||
})
|
||||
map.loadImage('src/img/plane-FF5555.png',
|
||||
function (error, image) {
|
||||
if (error) throw error;
|
||||
map.addImage('plane-FF5555', image);
|
||||
})
|
||||
var colors = ["FFE419","66FF00","FF5555"]
|
||||
|
||||
//get now in GMT+0
|
||||
var nowGMTSeconds = moment.tz(new Date(), "Europe/London").unix()
|
||||
|
||||
//get the planes from firestore
|
||||
db.collection("planes").where("deliverySecondsServer", ">", nowGMTSeconds).get().then((querySnapshot) => { //change query to get only the ones who are still flying
|
||||
querySnapshot.forEach((doc) => {
|
||||
var id = doc.id
|
||||
var data = doc.data()
|
||||
//creating arcs
|
||||
var line = turf.lineString([data.startCoordo,data.destCoordo])
|
||||
var lineDistance = turf.length(line);
|
||||
var arc = [];
|
||||
var steps = 500;
|
||||
for (var i = 0; i < lineDistance; i += lineDistance / steps) {
|
||||
var segment = turf.along(line, i);
|
||||
arc.push(segment.geometry.coordinates);
|
||||
}
|
||||
line.geometry.coordinates = arc;
|
||||
|
||||
//random color
|
||||
var randomColor = colors[Math.floor(Math.random() * colors.length)];
|
||||
|
||||
map.addSource('route-'+id+'', {
|
||||
'type': 'geojson',
|
||||
'data': line
|
||||
});
|
||||
map.addLayer({
|
||||
'id': 'route-'+id+'',
|
||||
'source': 'route-'+id+'',
|
||||
'type': 'line',
|
||||
'paint': {
|
||||
'line-width': 2,
|
||||
'line-color': '#'+randomColor
|
||||
}
|
||||
});
|
||||
map.setLayoutProperty('route-'+id+'', 'visibility', 'none');
|
||||
|
||||
|
||||
//creating and animating planes
|
||||
|
||||
// calculating area already travelled
|
||||
var dateStart = moment(data.sentDate[0])
|
||||
var dateEnd = moment(data.deliveryDate[0])
|
||||
var dateNow = moment(new Date())
|
||||
var totalSeconds = dateEnd.diff(dateStart,'seconds');
|
||||
var travelledSeconds = dateNow.diff(dateStart,'seconds')
|
||||
var travelRatio = travelledSeconds/totalSeconds
|
||||
var lineDistance = turf.length(line);
|
||||
var currentPosition = turf.along(line, lineDistance*travelRatio,{units: 'kilometers'})
|
||||
var plane = turf.point(currentPosition.geometry.coordinates,data)
|
||||
|
||||
//calculating bearing based on two points, one just before and one just after
|
||||
var positionBefore = turf.along(line, (lineDistance*travelRatio)-0.00001,{units: 'kilometers'})
|
||||
var positionAfter = turf.along(line, (lineDistance*travelRatio)+0.00001,{units: 'kilometers'})
|
||||
plane.properties.bearing = turf.bearing(
|
||||
positionBefore,
|
||||
positionAfter
|
||||
);
|
||||
|
||||
map.addSource('plane-'+id+'', {
|
||||
'type': 'geojson',
|
||||
'data': plane
|
||||
});
|
||||
map.addLayer({
|
||||
'id': 'plane-'+id+'',
|
||||
'source': 'plane-'+id+'',
|
||||
'type': 'symbol',
|
||||
'layout': {
|
||||
'icon-image': 'plane-'+randomColor+'',
|
||||
'icon-rotate': ['get', 'bearing'],
|
||||
'icon-size':0.05,
|
||||
'icon-rotation-alignment': 'map',
|
||||
'icon-allow-overlap': true,
|
||||
'icon-ignore-placement': true
|
||||
}
|
||||
});
|
||||
|
||||
//animating
|
||||
function animate(){
|
||||
var dateStart = moment(data.sentDate[0])
|
||||
var dateEnd = moment(data.deliveryDate[0])
|
||||
var dateNow = moment(new Date())
|
||||
var totalSeconds = dateEnd.diff(dateStart,'seconds');
|
||||
var travelledSeconds = dateNow.diff(dateStart,'seconds')
|
||||
var travelRatio = travelledSeconds/totalSeconds
|
||||
var lineDistance = turf.length(line);
|
||||
var currentPosition = turf.along(line, lineDistance*travelRatio,{units: 'kilometers'})
|
||||
var plane = turf.point(currentPosition.geometry.coordinates,data)
|
||||
|
||||
//calculating bearing based on two points, one just before and one just after
|
||||
var positionBefore = turf.along(line, (lineDistance*travelRatio)-0.00001,{units: 'kilometers'})
|
||||
var positionAfter = turf.along(line, (lineDistance*travelRatio)+0.00001,{units: 'kilometers'})
|
||||
plane.properties.bearing = turf.bearing(
|
||||
positionBefore,
|
||||
positionAfter
|
||||
);
|
||||
map.getSource('plane-'+id+'').setData(plane);
|
||||
var nowGMTSeconds = moment.tz(new Date(), "Europe/London").unix()
|
||||
//removing the plane from map if arrived
|
||||
if (data.deliverySecondsServer < nowGMTSeconds){
|
||||
map.setLayoutProperty('plane-'+id+'', 'visibility', 'none');
|
||||
}
|
||||
requestAnimationFrame(animate)
|
||||
}
|
||||
// uncomment to animate below, still some clipping issues
|
||||
//animate()
|
||||
|
||||
//on click on a plane: get popup + display route
|
||||
map.on('click', 'plane-'+id+'', function (e) {
|
||||
var coordinates = e.features[0].geometry.coordinates.slice();
|
||||
var prop = e.features[0].properties;
|
||||
var sentDate = JSON.parse(prop.sentDate)[0]
|
||||
var deliveryDate = JSON.parse(prop.deliveryDate)[0]
|
||||
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
|
||||
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
|
||||
}
|
||||
//displying route
|
||||
map.setLayoutProperty('route-'+id+'', 'visibility', 'visible');
|
||||
|
||||
var popup = new mapboxgl.Popup()
|
||||
.setLngLat(coordinates)
|
||||
.setHTML("<b>Origine:</b> "+prop.startName+"<br><em>"+sentDate+"</em><br><b>Destination:</b> "+prop.destName+"<br><em>"+deliveryDate+"</em>")
|
||||
.addTo(map);
|
||||
//removing route
|
||||
popup.on('close', function(){
|
||||
map.setLayoutProperty('route-'+id+'', 'visibility', 'none');
|
||||
});
|
||||
|
||||
});
|
||||
// Change the cursor to a pointer when the mouse is over the places layer.
|
||||
map.on('mouseenter', 'plane-'+id+'', function () {
|
||||
map.getCanvas().style.cursor = 'pointer';
|
||||
});
|
||||
|
||||
// Change it back to a pointer when it leaves.
|
||||
map.on('mouseleave', 'plane-'+id+'', function () {
|
||||
map.getCanvas().style.cursor = '';
|
||||
});
|
||||
|
||||
//adapt icon size to zoom level
|
||||
map.on('zoom', function() {
|
||||
map.setLayoutProperty('plane-'+id+'', 'icon-size', (map.getZoom())*0.025);
|
||||
});
|
||||
|
||||
|
||||
//URL Parameter : zooming to ID and opening popup when url in format avion-poe.me?plane=id
|
||||
var queryString = window.location.search;
|
||||
queryString = queryString.substring(7)
|
||||
if(id == queryString){
|
||||
map.setLayoutProperty('route-'+id+'', 'visibility', 'visible');
|
||||
var bboxTravel = turf.bbox(line);
|
||||
var bounds = [[bboxTravel[0],bboxTravel[1]],[bboxTravel[2],bboxTravel[3]]]
|
||||
map.fitBounds(bounds, {
|
||||
padding: 65,
|
||||
speed: 0.5, // make the flying slow
|
||||
curve: 0.8, // change the speed at which it zooms out
|
||||
// This can be any easing function: it takes a number between
|
||||
// 0 and 1 and returns another number between 0 and 1.
|
||||
easing: function(
|
||||
t) {
|
||||
return t;
|
||||
},
|
||||
});
|
||||
var sentDate = plane.properties.sentDate[0]
|
||||
var deliveryDate = plane.properties.deliveryDate[0]
|
||||
var popup = new mapboxgl.Popup()
|
||||
.setLngLat(currentPosition.geometry.coordinates)
|
||||
.setHTML("<b>Origine:</b> "+plane.properties.startName+"<br><em>"+sentDate+"</em><br><b>Destination:</b> "+plane.properties.destName+"<br><em>"+deliveryDate+"</em>")
|
||||
.addTo(map);
|
||||
//removing route
|
||||
popup.on('close', function(){
|
||||
map.setLayoutProperty('route-'+id+'', 'visibility', 'none');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
Reference in New Issue
Block a user