7 Commits

Author SHA1 Message Date
Râu Cao
fc4c63b519 1.5.0 2022-09-13 07:55:53 +02:00
Râu Cao
fe1c9f6300 Adjust for multiple tracked POIs 2022-09-13 07:55:09 +02:00
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
11 changed files with 46582 additions and 52842 deletions

File diff suppressed because one or more lines are too long

11
dist/assets/index.892cac62.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
dist/img/avatars/raucao.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

BIN
dist/img/avatars/tobyyoungfox.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

3
dist/index.html vendored
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.03aa5401.js"></script> <script defer data-domain="r2b22.kip.pe" src="https://plausible.io/js/plausible.js"></script>
<script type="module" crossorigin src="/assets/index.892cac62.js"></script>
<link rel="stylesheet" href="/assets/index.eed9f443.css"> <link rel="stylesheet" href="/assets/index.eed9f443.css">
</head> </head>
<body> <body>

File diff suppressed because it is too large Load Diff

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>

469
main.js
View File

@@ -13,257 +13,264 @@ 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 van_data = data.find(i => i.name == 'satoshithevan');
const van_coords = [van_data.lon, van_data.lat];
vanFeature.getGeometry().setCoordinates(van_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();

4
package-lock.json generated
View File

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

View File

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