4 Commits

Author SHA1 Message Date
Râu Cao
e00b5576e6 1.2.0 2022-09-06 21:09:39 +02:00
Râu Cao
e06b9d5109 MVP 2022-09-06 21:09:06 +02:00
Râu Cao
b527049acb 1.1.0 2022-09-04 20:55:44 +02:00
Râu Cao
18ea53313f WIP tracked POIs 2022-09-04 20:53:37 +02:00
6 changed files with 112 additions and 25 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/index.html vendored
View File

@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Road2Bitcoin Live Map</title> <title>Road2Bitcoin Live Map</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css">
<script type="module" crossorigin src="/assets/index.1d1993b1.js"></script> <script type="module" crossorigin src="/assets/index.098b1da4.js"></script>
<link rel="stylesheet" href="/assets/index.eed9f443.css"> <link rel="stylesheet" href="/assets/index.eed9f443.css">
</head> </head>
<body> <body>

107
main.js
View File

@@ -7,7 +7,7 @@ import Point from 'ol/geom/Point';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer'; import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {Circle as CircleStyle, Fill, Icon, Stroke, Style} from 'ol/style'; import {Circle as CircleStyle, Fill, Icon, Stroke, Style} from 'ol/style';
import {OSM, Vector as VectorSource} from 'ol/source'; import {OSM, Vector as VectorSource} from 'ol/source';
import {useGeographic} from 'ol/proj'; import {useGeographic, fromLonLat} from 'ol/proj';
import geojsonRoute from './geo/route.json' import geojsonRoute from './geo/route.json'
import geojsonPOI from './geo/poi.json' import geojsonPOI from './geo/poi.json'
@@ -60,7 +60,7 @@ const styles = {
// Route // Route
// //
const lastStageFinished = 4; const lastStageFinished = 1;
const stagesCompleted = geojsonRoute.features.slice(0, lastStageFinished); const stagesCompleted = geojsonRoute.features.slice(0, lastStageFinished);
const stagesAhead = geojsonRoute.features.slice(lastStageFinished); const stagesAhead = geojsonRoute.features.slice(lastStageFinished);
const vectorSourceStagesCompleted = new VectorSource(); const vectorSourceStagesCompleted = new VectorSource();
@@ -96,17 +96,18 @@ const poiLayer = new VectorLayer({
style: styles.circleBlack, style: styles.circleBlack,
}); });
const vectorSourceVan = new VectorSource(); const vectorSourceTrackedPoints = new VectorSource();
const vanFeature= new Feature({ const vanFeature= new Feature({
geometry: new Point([ 12.498556, 45.780383 ]), geometry: new Point([8.918618, 44.407408]),
name: 'Support Van' name: 'Support Van',
trackable: true
}); });
vectorSourceVan.addFeature(vanFeature); vectorSourceTrackedPoints.addFeature(vanFeature);
const vanLayer = new VectorLayer({ const trackedPointsLayer = new VectorLayer({
source: vectorSourceVan, source: vectorSourceTrackedPoints,
style: styles.iconVan style: styles.iconVan
}); });
@@ -119,6 +120,8 @@ const view = new View({
zoom: 6.6 zoom: 6.6
}) })
window.view = view;
const map = new Map({ const map = new Map({
target: 'map', target: 'map',
layers: [ layers: [
@@ -128,11 +131,23 @@ const map = new Map({
stagesCompletedLayer, stagesCompletedLayer,
stagesAheadLayer, stagesAheadLayer,
poiLayer, poiLayer,
vanLayer trackedPointsLayer
], ],
view: view 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);
// //
// Popups // Popups
// //
@@ -153,6 +168,23 @@ function disposePopover() {
} }
} }
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 // display popup on click
map.on('click', function (evt) { map.on('click', function (evt) {
const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) { const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
@@ -166,7 +198,7 @@ map.on('click', function (evt) {
popover = new bootstrap.Popover(popupEl, { popover = new bootstrap.Popover(popupEl, {
placement: 'top', placement: 'top',
html: true, html: true,
content: feature.get('name'), content: createPopoverHtml(feature)
}); });
popover.show(); popover.show();
}); });
@@ -180,3 +212,58 @@ map.on('pointermove', function (evt) {
// Close the popup when the map is moved // Close the popup when the map is moved
map.on('movestart', disposePopover); 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);

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ol-vite", "name": "ol-vite",
"version": "1.0.1", "version": "1.2.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ol-vite", "name": "ol-vite",
"version": "1.0.1", "version": "1.2.0",
"dependencies": { "dependencies": {
"ol": "latest" "ol": "latest"
}, },

View File

@@ -1,6 +1,6 @@
{ {
"name": "map", "name": "map",
"version": "1.0.1", "version": "1.2.0",
"scripts": { "scripts": {
"start": "vite", "start": "vite",
"build": "vite build", "build": "vite build",