Load current tour status from server
This commit is contained in:
parent
3324a57206
commit
0c1aeebdf7
468
main.js
468
main.js
@ -13,257 +13,263 @@ import geojsonPOI from './geo/poi.json'
|
|||||||
|
|
||||||
useGeographic();
|
useGeographic();
|
||||||
|
|
||||||
const styles = {
|
async function main() {
|
||||||
lineOrange: new Style({
|
const styles = {
|
||||||
stroke: new Stroke({
|
lineOrange: new Style({
|
||||||
color: '#FF9900',
|
|
||||||
// lineDash: [8],
|
|
||||||
width: 5,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
lineGrey: new Style({
|
|
||||||
stroke: new Stroke({
|
|
||||||
color: '#555555',
|
|
||||||
// lineDash: [8],
|
|
||||||
width: 5,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
iconStop: new Style({
|
|
||||||
image: new Icon({
|
|
||||||
anchor: [0.5, 46],
|
|
||||||
anchorXUnits: 'fraction',
|
|
||||||
anchorYUnits: 'pixels',
|
|
||||||
src: '/img/icon.png',
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
iconVan: new Style({
|
|
||||||
image: new Icon({
|
|
||||||
anchor: [0.5, 16],
|
|
||||||
anchorXUnits: 'fraction',
|
|
||||||
anchorYUnits: 'pixels',
|
|
||||||
src: '/img/van-100px.png',
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
circleBlack: new Style({
|
|
||||||
image: new CircleStyle({
|
|
||||||
radius: 7,
|
|
||||||
fill: new Fill({color: '#FF9900'}),
|
|
||||||
stroke: new Stroke({
|
stroke: new Stroke({
|
||||||
color: 'white',
|
color: '#FF9900',
|
||||||
width: 2,
|
// lineDash: [8],
|
||||||
|
width: 5,
|
||||||
}),
|
}),
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Route
|
|
||||||
//
|
|
||||||
|
|
||||||
const lastStageFinished = 2;
|
|
||||||
const stagesCompleted = geojsonRoute.features.slice(0, lastStageFinished);
|
|
||||||
const stagesAhead = geojsonRoute.features.slice(lastStageFinished);
|
|
||||||
const vectorSourceStagesCompleted = new VectorSource();
|
|
||||||
const vectorSourceStagesAhead = new VectorSource();
|
|
||||||
|
|
||||||
for (const stage of stagesCompleted) {
|
|
||||||
vectorSourceStagesCompleted.addFeature(new GeoJSON().readFeature(stage));
|
|
||||||
}
|
|
||||||
for (const stage of stagesAhead) {
|
|
||||||
vectorSourceStagesAhead.addFeature(new GeoJSON().readFeature(stage));
|
|
||||||
}
|
|
||||||
|
|
||||||
const stagesCompletedLayer = new VectorLayer({
|
|
||||||
source: vectorSourceStagesCompleted,
|
|
||||||
style: styles.lineOrange
|
|
||||||
});
|
|
||||||
|
|
||||||
const stagesAheadLayer = new VectorLayer({
|
|
||||||
source: vectorSourceStagesAhead,
|
|
||||||
style: styles.lineGrey
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// Points of Interest
|
|
||||||
//
|
|
||||||
|
|
||||||
const vectorSourcePOI = new VectorSource({
|
|
||||||
features: new GeoJSON().readFeatures(geojsonPOI),
|
|
||||||
});
|
|
||||||
|
|
||||||
const poiLayer = new VectorLayer({
|
|
||||||
source: vectorSourcePOI,
|
|
||||||
style: styles.circleBlack,
|
|
||||||
});
|
|
||||||
|
|
||||||
const vectorSourceTrackedPoints = new VectorSource();
|
|
||||||
|
|
||||||
const vanFeature= new Feature({
|
|
||||||
geometry: new Point([8.918618, 44.407408]),
|
|
||||||
name: 'Support Van',
|
|
||||||
trackable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
vectorSourceTrackedPoints.addFeature(vanFeature);
|
|
||||||
|
|
||||||
const trackedPointsLayer = new VectorLayer({
|
|
||||||
source: vectorSourceTrackedPoints,
|
|
||||||
style: styles.iconVan
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// Map initialization
|
|
||||||
//
|
|
||||||
|
|
||||||
const view = new View({
|
|
||||||
center: [10.6, 46.9],
|
|
||||||
zoom: 6.6
|
|
||||||
})
|
|
||||||
|
|
||||||
window.view = view;
|
|
||||||
|
|
||||||
const map = new Map({
|
|
||||||
target: 'map',
|
|
||||||
layers: [
|
|
||||||
new TileLayer({
|
|
||||||
source: new OSM()
|
|
||||||
}),
|
}),
|
||||||
stagesCompletedLayer,
|
lineGrey: new Style({
|
||||||
stagesAheadLayer,
|
stroke: new Stroke({
|
||||||
poiLayer,
|
color: '#555555',
|
||||||
trackedPointsLayer
|
// lineDash: [8],
|
||||||
],
|
width: 5,
|
||||||
view: view
|
}),
|
||||||
});
|
}),
|
||||||
|
iconStop: new Style({
|
||||||
//
|
image: new Icon({
|
||||||
// Center map on current/next stage
|
anchor: [0.5, 46],
|
||||||
//
|
anchorXUnits: 'fraction',
|
||||||
|
anchorYUnits: 'pixels',
|
||||||
setTimeout(() => {
|
src: '/img/icon.png',
|
||||||
const nextStageFeature = new GeoJSON().readFeature(stagesAhead[0]);
|
}),
|
||||||
view.fit(nextStageFeature.getGeometry(), {
|
}),
|
||||||
maxZoom: 10,
|
iconVan: new Style({
|
||||||
duration: 1000
|
image: new Icon({
|
||||||
});
|
anchor: [0.5, 16],
|
||||||
}, 3000);
|
anchorXUnits: 'fraction',
|
||||||
|
anchorYUnits: 'pixels',
|
||||||
//
|
src: '/img/van-100px.png',
|
||||||
// Popups
|
}),
|
||||||
//
|
}),
|
||||||
const popupEl = document.getElementById('popup');
|
circleBlack: new Style({
|
||||||
|
image: new CircleStyle({
|
||||||
const popup = new Overlay({
|
radius: 7,
|
||||||
element: popupEl,
|
fill: new Fill({color: '#FF9900'}),
|
||||||
positioning: 'bottom-center',
|
stroke: new Stroke({
|
||||||
stopEvent: false,
|
color: 'white',
|
||||||
});
|
width: 2,
|
||||||
map.addOverlay(popup);
|
}),
|
||||||
|
})
|
||||||
let popover;
|
})
|
||||||
function disposePopover() {
|
|
||||||
if (popover) {
|
|
||||||
popover.dispose();
|
|
||||||
popover = undefined;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function createPopoverHtml(feature) {
|
//
|
||||||
const container = document.createElement('div');
|
// Route
|
||||||
const title = document.createElement('div');
|
//
|
||||||
title.textContent = feature.get('name');
|
|
||||||
container.append(title);
|
|
||||||
return container.innerHTML;
|
|
||||||
// if (feature.get('trackable')) {
|
|
||||||
// const linkParent = document.createElement('div');
|
|
||||||
// const followLink = document.createElement('a');
|
|
||||||
// followLink.textContent = 'Follow';
|
|
||||||
// followLink.href = '#';
|
|
||||||
// followLink.addEventListener('click', startFollowing(feature, followLink));
|
|
||||||
// linkParent.append(followLink);
|
|
||||||
// container.append(linkParent);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// display popup on click
|
const tourStatus = await fetch('https://r2b22.kip.pe/status.json').then(res => res.json());
|
||||||
map.on('click', function (evt) {
|
|
||||||
const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
|
const lastStageFinished = tourStatus.lastStageFinished;
|
||||||
return feature;
|
const stagesCompleted = geojsonRoute.features.slice(0, lastStageFinished);
|
||||||
});
|
const stagesAhead = geojsonRoute.features.slice(lastStageFinished);
|
||||||
disposePopover();
|
const vectorSourceStagesCompleted = new VectorSource();
|
||||||
if (!feature) {
|
const vectorSourceStagesAhead = new VectorSource();
|
||||||
return;
|
|
||||||
|
for (const stage of stagesCompleted) {
|
||||||
|
vectorSourceStagesCompleted.addFeature(new GeoJSON().readFeature(stage));
|
||||||
}
|
}
|
||||||
popup.setPosition(evt.coordinate);
|
for (const stage of stagesAhead) {
|
||||||
popover = new bootstrap.Popover(popupEl, {
|
vectorSourceStagesAhead.addFeature(new GeoJSON().readFeature(stage));
|
||||||
placement: 'top',
|
}
|
||||||
html: true,
|
|
||||||
content: createPopoverHtml(feature)
|
const stagesCompletedLayer = new VectorLayer({
|
||||||
|
source: vectorSourceStagesCompleted,
|
||||||
|
style: styles.lineOrange
|
||||||
});
|
});
|
||||||
popover.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
// change mouse cursor when over marker
|
const stagesAheadLayer = new VectorLayer({
|
||||||
map.on('pointermove', function (evt) {
|
source: vectorSourceStagesAhead,
|
||||||
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel)
|
style: styles.lineGrey
|
||||||
? 'pointer'
|
});
|
||||||
: '';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Close the popup when the map is moved
|
//
|
||||||
map.on('movestart', disposePopover);
|
// Points of Interest
|
||||||
|
//
|
||||||
|
|
||||||
|
const vectorSourcePOI = new VectorSource({
|
||||||
|
features: new GeoJSON().readFeatures(geojsonPOI),
|
||||||
|
});
|
||||||
|
|
||||||
//
|
const poiLayer = new VectorLayer({
|
||||||
// Tracking
|
source: vectorSourcePOI,
|
||||||
//
|
style: styles.circleBlack,
|
||||||
|
});
|
||||||
|
|
||||||
const updateInterval = 5000;
|
const vectorSourceTrackedPoints = new VectorSource();
|
||||||
let followedFeature = vanFeature;
|
|
||||||
let followedZoomed = false;
|
|
||||||
// let followedFeature = null;
|
|
||||||
|
|
||||||
function startFollowing(feature, followLink) {
|
const vanFeature= new Feature({
|
||||||
followedFeature = feature;
|
geometry: new Point([8.918618, 44.407408]),
|
||||||
followLink.textContent = 'Stop following';
|
name: 'Support Van',
|
||||||
// followLink.removeEventListener('click', startFollowing);
|
trackable: true
|
||||||
followLink.addEventListener('click', stopFollowing(feature, followLink));
|
});
|
||||||
}
|
|
||||||
|
|
||||||
function stopFollowing(feature, followLink) {
|
vectorSourceTrackedPoints.addFeature(vanFeature);
|
||||||
followedFeature = null;
|
|
||||||
followedZoomed = false;
|
|
||||||
followLink.textContent = 'Stop following';
|
|
||||||
// followLink.removeEventListener('click', stopFollowing);
|
|
||||||
followLink.addEventListener('click', startFollowing(feature, followLink));
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateData(startInterval=false) {
|
const trackedPointsLayer = new VectorLayer({
|
||||||
fetch('https://r2b22.kip.pe/last.json')
|
source: vectorSourceTrackedPoints,
|
||||||
.then(response => response.json())
|
style: styles.iconVan
|
||||||
.then(data => {
|
});
|
||||||
console.log(data);
|
|
||||||
const coords = [data.lon, data.lat];
|
|
||||||
vanFeature.getGeometry().setCoordinates(coords);
|
|
||||||
|
|
||||||
// let zoomLevel;
|
//
|
||||||
// if (!followedZoomed) {
|
// Map initialization
|
||||||
// zoomLevel = 13;
|
//
|
||||||
// followedZoomed = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (followedFeature) {
|
const view = new View({
|
||||||
// view.animate({
|
center: [10.6, 46.9],
|
||||||
// center: followedFeature.getGeometry().getCoordinates(),
|
zoom: 6.6
|
||||||
// duration: 500,
|
})
|
||||||
// zoom: zoomLevel
|
|
||||||
// });
|
window.view = view;
|
||||||
// }
|
|
||||||
|
const map = new Map({
|
||||||
|
target: 'map',
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
source: new OSM()
|
||||||
|
}),
|
||||||
|
stagesCompletedLayer,
|
||||||
|
stagesAheadLayer,
|
||||||
|
poiLayer,
|
||||||
|
trackedPointsLayer
|
||||||
|
],
|
||||||
|
view: view
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Center map on current/next stage
|
||||||
|
//
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const nextStageFeature = new GeoJSON().readFeature(stagesAhead[0]);
|
||||||
|
view.fit(nextStageFeature.getGeometry(), {
|
||||||
|
maxZoom: 10,
|
||||||
|
duration: 1000
|
||||||
});
|
});
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
if (startInterval) {
|
//
|
||||||
setInterval(updateData, updateInterval);
|
// Popups
|
||||||
|
//
|
||||||
|
const popupEl = document.getElementById('popup');
|
||||||
|
|
||||||
|
const popup = new Overlay({
|
||||||
|
element: popupEl,
|
||||||
|
positioning: 'bottom-center',
|
||||||
|
stopEvent: false,
|
||||||
|
});
|
||||||
|
map.addOverlay(popup);
|
||||||
|
|
||||||
|
let popover;
|
||||||
|
function disposePopover() {
|
||||||
|
if (popover) {
|
||||||
|
popover.dispose();
|
||||||
|
popover = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createPopoverHtml(feature) {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
const title = document.createElement('div');
|
||||||
|
title.textContent = feature.get('name');
|
||||||
|
container.append(title);
|
||||||
|
return container.innerHTML;
|
||||||
|
// if (feature.get('trackable')) {
|
||||||
|
// const linkParent = document.createElement('div');
|
||||||
|
// const followLink = document.createElement('a');
|
||||||
|
// followLink.textContent = 'Follow';
|
||||||
|
// followLink.href = '#';
|
||||||
|
// followLink.addEventListener('click', startFollowing(feature, followLink));
|
||||||
|
// linkParent.append(followLink);
|
||||||
|
// container.append(linkParent);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// display popup on click
|
||||||
|
map.on('click', function (evt) {
|
||||||
|
const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
|
||||||
|
return feature;
|
||||||
|
});
|
||||||
|
disposePopover();
|
||||||
|
if (!feature) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
popup.setPosition(evt.coordinate);
|
||||||
|
popover = new bootstrap.Popover(popupEl, {
|
||||||
|
placement: 'top',
|
||||||
|
html: true,
|
||||||
|
content: createPopoverHtml(feature)
|
||||||
|
});
|
||||||
|
popover.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
// change mouse cursor when over marker
|
||||||
|
map.on('pointermove', function (evt) {
|
||||||
|
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel)
|
||||||
|
? 'pointer'
|
||||||
|
: '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the popup when the map is moved
|
||||||
|
map.on('movestart', disposePopover);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Tracking
|
||||||
|
//
|
||||||
|
|
||||||
|
const updateInterval = 5000;
|
||||||
|
// let followedFeature = vanFeature;
|
||||||
|
// let followedZoomed = false;
|
||||||
|
// let followedFeature = null;
|
||||||
|
|
||||||
|
function startFollowing(feature, followLink) {
|
||||||
|
followedFeature = feature;
|
||||||
|
followLink.textContent = 'Stop following';
|
||||||
|
// followLink.removeEventListener('click', startFollowing);
|
||||||
|
followLink.addEventListener('click', stopFollowing(feature, followLink));
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopFollowing(feature, followLink) {
|
||||||
|
followedFeature = null;
|
||||||
|
followedZoomed = false;
|
||||||
|
followLink.textContent = 'Stop following';
|
||||||
|
// followLink.removeEventListener('click', stopFollowing);
|
||||||
|
followLink.addEventListener('click', startFollowing(feature, followLink));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateData(startInterval=false) {
|
||||||
|
fetch('https://r2b22.kip.pe/last.json')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
console.log(data);
|
||||||
|
const coords = [data.lon, data.lat];
|
||||||
|
vanFeature.getGeometry().setCoordinates(coords);
|
||||||
|
|
||||||
|
// let zoomLevel;
|
||||||
|
// if (!followedZoomed) {
|
||||||
|
// zoomLevel = 13;
|
||||||
|
// followedZoomed = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (followedFeature) {
|
||||||
|
// view.animate({
|
||||||
|
// center: followedFeature.getGeometry().getCoordinates(),
|
||||||
|
// duration: 500,
|
||||||
|
// zoom: zoomLevel
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (startInterval) {
|
||||||
|
setInterval(updateData, updateInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateData(true);
|
main();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user