9 Commits

Author SHA1 Message Date
Râu Cao 0d66bc1266 1.4.0 2022-09-11 12:31:26 +02:00
Râu Cao ba3982d9a6 Add plausible analytics script 2022-09-11 12:30:52 +02:00
Râu Cao f2cc9a9783 1.3.0 2022-09-09 20:29:41 +02:00
Râu Cao 0c1aeebdf7 Load current tour status from server 2022-09-09 20:29:18 +02:00
Râu Cao 3324a57206 Update route 2022-09-09 20:29:00 +02:00
Râu Cao cf8e6882f8 1.2.1 2022-09-08 09:49:18 +02:00
Râu Cao 6c4959deda Hackety hack, no time 2022-09-08 09:48:51 +02:00
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
9 changed files with 46582 additions and 52826 deletions
+11
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-11
View File
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -6,7 +6,8 @@
<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.b64a86a4.js"></script> <script defer data-domain="r2b22.kip.pe" src="https://plausible.io/js/plausible.js"></script>
<script type="module" crossorigin src="/assets/index.148d1b99.js"></script>
<link rel="stylesheet" href="/assets/index.eed9f443.css"> <link rel="stylesheet" href="/assets/index.eed9f443.css">
</head> </head>
<body> <body>
+46326 -52595
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -6,6 +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 defer data-domain="r2b22.kip.pe" src="https://plausible.io/js/plausible.js"></script>
</head> </head>
<body> <body>
<div id="map"><div id="popup"></div></div> <div id="map"><div id="popup"></div></div>
+112 -89
View File
@@ -13,7 +13,8 @@ import geojsonPOI from './geo/poi.json'
useGeographic(); useGeographic();
const styles = { async function main() {
const styles = {
lineOrange: new Style({ lineOrange: new Style({
stroke: new Stroke({ stroke: new Stroke({
color: '#FF9900', color: '#FF9900',
@@ -54,75 +55,77 @@ const styles = {
}), }),
}) })
}) })
} }
// //
// Route // Route
// //
const lastStageFinished = 4; const tourStatus = await fetch('https://r2b22.kip.pe/status.json').then(res => res.json());
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) { const lastStageFinished = tourStatus.lastStageFinished;
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)); vectorSourceStagesCompleted.addFeature(new GeoJSON().readFeature(stage));
} }
for (const stage of stagesAhead) { for (const stage of stagesAhead) {
vectorSourceStagesAhead.addFeature(new GeoJSON().readFeature(stage)); vectorSourceStagesAhead.addFeature(new GeoJSON().readFeature(stage));
} }
const stagesCompletedLayer = new VectorLayer({ const stagesCompletedLayer = new VectorLayer({
source: vectorSourceStagesCompleted, source: vectorSourceStagesCompleted,
style: styles.lineOrange style: styles.lineOrange
}); });
const stagesAheadLayer = new VectorLayer({ const stagesAheadLayer = new VectorLayer({
source: vectorSourceStagesAhead, source: vectorSourceStagesAhead,
style: styles.lineGrey style: styles.lineGrey
}); });
// //
// Points of Interest // Points of Interest
// //
const vectorSourcePOI = new VectorSource({ const vectorSourcePOI = new VectorSource({
features: new GeoJSON().readFeatures(geojsonPOI), features: new GeoJSON().readFeatures(geojsonPOI),
}); });
const poiLayer = new VectorLayer({ const poiLayer = new VectorLayer({
source: vectorSourcePOI, source: vectorSourcePOI,
style: styles.circleBlack, style: styles.circleBlack,
}); });
const vectorSourceTrackedPoints = new VectorSource(); const vectorSourceTrackedPoints = new VectorSource();
const vanFeature= new Feature({ const vanFeature= new Feature({
geometry: new Point([8.918618, 44.407408]), geometry: new Point([8.918618, 44.407408]),
name: 'Support Van', name: 'Support Van',
trackable: true trackable: true
}); });
vectorSourceTrackedPoints.addFeature(vanFeature); vectorSourceTrackedPoints.addFeature(vanFeature);
const trackedPointsLayer = new VectorLayer({ const trackedPointsLayer = new VectorLayer({
source: vectorSourceTrackedPoints, source: vectorSourceTrackedPoints,
style: styles.iconVan style: styles.iconVan
}); });
// //
// Map initialization // Map initialization
// //
const view = new View({ const view = new View({
center: [10.6, 46.9], center: [10.6, 46.9],
zoom: 6.6 zoom: 6.6
}) })
window.view = view; window.view = view;
const map = new Map({ const map = new Map({
target: 'map', target: 'map',
layers: [ layers: [
new TileLayer({ new TileLayer({
@@ -134,50 +137,59 @@ const map = new Map({
trackedPointsLayer trackedPointsLayer
], ],
view: view view: view
}); });
// //
// Popups // Center map on current/next stage
// //
const popupEl = document.getElementById('popup');
const popup = new Overlay({ setTimeout(() => {
const nextStageFeature = new GeoJSON().readFeature(stagesAhead[0]);
view.fit(nextStageFeature.getGeometry(), {
maxZoom: 10,
duration: 1000
});
}, 3000);
//
// Popups
//
const popupEl = document.getElementById('popup');
const popup = new Overlay({
element: popupEl, element: popupEl,
positioning: 'bottom-center', positioning: 'bottom-center',
stopEvent: false, stopEvent: false,
}); });
map.addOverlay(popup); map.addOverlay(popup);
let popover; let popover;
function disposePopover() { function disposePopover() {
if (popover) { if (popover) {
popover.dispose(); popover.dispose();
popover = undefined; popover = undefined;
} }
} }
function createPopoverHtml(feature) { function createPopoverHtml(feature) {
const container = document.createElement('div'); const container = document.createElement('div');
container.className = 'popover-content';
const title = document.createElement('div'); const title = document.createElement('div');
title.textContent = feature.get('name'); title.textContent = feature.get('name');
container.append(title); container.append(title);
return container.innerHTML;
if (feature.get('trackable')) { // if (feature.get('trackable')) {
const linkParent = document.createElement('div'); // const linkParent = document.createElement('div');
const followLink = document.createElement('a'); // const followLink = document.createElement('a');
followLink.textContent = "Follow"; // followLink.textContent = 'Follow';
followLink.addEventListener('click', console.log(feature, followLink)); // followLink.href = '#';
// followLink.addEventListener('click', startFollowing(feature, followLink)); // followLink.addEventListener('click', startFollowing(feature, followLink));
linkParent.append(followLink); // linkParent.append(followLink);
container.append(linkParent); // container.append(linkParent);
// }
} }
return container.innerHTML; // display popup on click
} map.on('click', function (evt) {
// display popup on click
map.on('click', function (evt) {
const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) { const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
return feature; return feature;
}); });
@@ -192,42 +204,44 @@ map.on('click', function (evt) {
content: createPopoverHtml(feature) content: createPopoverHtml(feature)
}); });
popover.show(); popover.show();
}); });
// change mouse cursor when over marker // change mouse cursor when over marker
map.on('pointermove', function (evt) { map.on('pointermove', function (evt) {
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel) map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel)
? 'pointer' ? 'pointer'
: ''; : '';
}); });
// 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 // Tracking
// //
const updateInterval = 5000; const updateInterval = 5000;
let followedFeature = vanFeature; // let followedFeature = vanFeature;
// let followedFeature = null; // let followedZoomed = false;
// let followedFeature = null;
function startFollowing(feature, followLink) { function startFollowing(feature, followLink) {
followedFeature = feature; followedFeature = feature;
followLink.textContent = 'Stop following'; followLink.textContent = 'Stop following';
// followLink.removeEventListener('click', startFollowing); // followLink.removeEventListener('click', startFollowing);
followLink.addEventListener('click', stopFollowing(feature, followLink)); followLink.addEventListener('click', stopFollowing(feature, followLink));
} }
function stopFollowing(feature, followLink) { function stopFollowing(feature, followLink) {
followedFeature = null; followedFeature = null;
followedZoomed = false;
followLink.textContent = 'Stop following'; followLink.textContent = 'Stop following';
// followLink.removeEventListener('click', stopFollowing); // followLink.removeEventListener('click', stopFollowing);
followLink.addEventListener('click', startFollowing(feature, followLink)); followLink.addEventListener('click', startFollowing(feature, followLink));
} }
function updateData(startInterval=false) { function updateData(startInterval=false) {
fetch('https://r2b22.kip.pe/last.json') fetch('https://r2b22.kip.pe/last.json')
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
@@ -235,18 +249,27 @@ function updateData(startInterval=false) {
const coords = [data.lon, data.lat]; const coords = [data.lon, data.lat];
vanFeature.getGeometry().setCoordinates(coords); vanFeature.getGeometry().setCoordinates(coords);
if (followedFeature) { // let zoomLevel;
view.animate({ // if (!followedZoomed) {
center: followedFeature.getGeometry().getCoordinates(), // zoomLevel = 13;
duration: 500, // followedZoomed = true;
zoom: 13 // }
});
} // if (followedFeature) {
// view.animate({
// center: followedFeature.getGeometry().getCoordinates(),
// duration: 500,
// zoom: zoomLevel
// });
// }
}); });
if (startInterval) { if (startInterval) {
setInterval(updateData, updateInterval); setInterval(updateData, updateInterval);
} }
}
updateData(true);
} }
updateData(true); main();
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "ol-vite", "name": "ol-vite",
"version": "1.1.0", "version": "1.4.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ol-vite", "name": "ol-vite",
"version": "1.1.0", "version": "1.4.0",
"dependencies": { "dependencies": {
"ol": "latest" "ol": "latest"
}, },
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "map", "name": "map",
"version": "1.1.0", "version": "1.4.0",
"scripts": { "scripts": {
"start": "vite", "start": "vite",
"build": "vite build", "build": "vite build",