183 lines
3.8 KiB
JavaScript
183 lines
3.8 KiB
JavaScript
import './style.css';
|
|
import {Map, View} from 'ol';
|
|
import Feature from 'ol/Feature';
|
|
import GeoJSON from 'ol/format/GeoJSON';
|
|
import Overlay from 'ol/Overlay';
|
|
import Point from 'ol/geom/Point';
|
|
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
|
|
import {Circle as CircleStyle, Fill, Icon, Stroke, Style} from 'ol/style';
|
|
import {OSM, Vector as VectorSource} from 'ol/source';
|
|
import {useGeographic} from 'ol/proj';
|
|
import geojsonRoute from './geo/route.json'
|
|
import geojsonPOI from './geo/poi.json'
|
|
|
|
useGeographic();
|
|
|
|
const styles = {
|
|
lineOrange: new Style({
|
|
stroke: new Stroke({
|
|
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({
|
|
color: 'white',
|
|
width: 2,
|
|
}),
|
|
})
|
|
})
|
|
}
|
|
|
|
//
|
|
// Route
|
|
//
|
|
|
|
const lastStageFinished = 4;
|
|
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 vectorSourceVan = new VectorSource();
|
|
|
|
const vanFeature= new Feature({
|
|
geometry: new Point([ 12.498556, 45.780383 ]),
|
|
name: 'Support Van'
|
|
});
|
|
|
|
vectorSourceVan.addFeature(vanFeature);
|
|
|
|
const vanLayer = new VectorLayer({
|
|
source: vectorSourceVan,
|
|
style: styles.iconVan
|
|
});
|
|
|
|
//
|
|
// Map initialization
|
|
//
|
|
|
|
const view = new View({
|
|
center: [10.6, 46.9],
|
|
zoom: 6.6
|
|
})
|
|
|
|
const map = new Map({
|
|
target: 'map',
|
|
layers: [
|
|
new TileLayer({
|
|
source: new OSM()
|
|
}),
|
|
stagesCompletedLayer,
|
|
stagesAheadLayer,
|
|
poiLayer,
|
|
vanLayer
|
|
],
|
|
view: view
|
|
});
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
// 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: feature.get('name'),
|
|
});
|
|
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);
|