sync: 2026-08-21 15:18:36

This commit is contained in:
2026-08-21 15:18:36 +02:00
parent aa5b994d31
commit 099c4032de

View File

@@ -8,7 +8,7 @@
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
href="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css"
>
<style>
@@ -612,30 +612,57 @@
/* =====================================================
LEAFLET
MAPLIBRE CONTROLS
===================================================== */
.leaflet-control-zoom {
margin-right: 18px !important;
margin-bottom: 82px !important;
.maplibregl-ctrl-group {
border: none !important;
box-shadow:
0 2px 7px rgba(0, 0, 0, 0.25) !important;
border-radius: 8px !important;
}
.leaflet-control-zoom a {
.maplibregl-ctrl-group button {
border: none !important;
}
.leaflet-control-attribution {
.maplibregl-ctrl-attrib {
font-size: 10px;
}
/* Position nav controls away from the search UI */
.maplibregl-ctrl-topleft {
top: 10px;
left: 10px;
}
.maplibregl-ctrl-topright {
top: 10px;
right: 10px;
}
/* =====================================================
MARKER STYLES
===================================================== */
/* Wrapper that holds both the label and the pin circle */
.poi-pin-wrapper {
position: relative;
cursor: pointer;
width: 34px;
height: 34px;
}
/* Permanent name label shown above each pin */
.pin-label {
position: absolute;
bottom: 38px;
left: 50%;
transform: translateX(-50%);
background: rgba(255, 255, 255, 0.92);
border: none;
border-radius: 4px;
@@ -645,18 +672,10 @@
font-weight: 500;
padding: 2px 7px;
white-space: nowrap;
}
.pin-label::before {
display: none;
pointer-events: none;
}
/* Custom circular pin that reflects the POI type */
.poi-pin {
background: transparent;
border: none;
}
.poi-pin-inner {
width: 34px;
height: 34px;
@@ -681,8 +700,7 @@
/* User location marker (blue dot) */
.user-loc-marker {
background: transparent;
border: none;
cursor: default;
}
.user-loc-dot {
@@ -762,10 +780,6 @@
right: 12px;
bottom: 72px;
}
.leaflet-control-zoom {
margin-bottom: 125px !important;
}
}
</style>
</head>
@@ -929,7 +943,7 @@
</button>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js"></script>
<script>
@@ -949,30 +963,26 @@
*/
const CLICK_ZOOM = 15;
const MAPTILER_KEY = "aUftDXS9UHdRVbSuaUWz";
/* =========================================================
MAP
========================================================= */
const map =
L.map("map").setView(
[
AMSTERDAM_LAT,
AMSTERDAM_LON
],
DEFAULT_ZOOM
);
const map = new maplibregl.Map({
container: "map",
style:
"https://api.maptiler.com/maps/streets-v4/style.json?key=" +
MAPTILER_KEY,
center: [AMSTERDAM_LON, AMSTERDAM_LAT],
zoom: DEFAULT_ZOOM
});
L.tileLayer(
"https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=aUftDXS9UHdRVbSuaUWz",
{
maxZoom: 19,
attribution:
"&copy; OpenStreetMap contributors"
}
).addTo(map);
map.addControl(
new maplibregl.NavigationControl(),
"top-right"
);
/* =========================================================
@@ -1014,6 +1024,8 @@
let selectedMarker = null;
let selectedPopup = null;
let userLocationMarker = null;
let zoomMessageTimer = null;
@@ -1052,13 +1064,13 @@
// Build a viewbox from the currently visible map area so
// results are restricted to what the user can see.
const visibleBounds = map.getBounds();
const mb = map.getBounds();
const viewbox = [
visibleBounds.getWest(),
visibleBounds.getNorth(),
visibleBounds.getEast(),
visibleBounds.getSouth()
mb.west,
mb.north,
mb.east,
mb.south
].join(",");
@@ -1182,27 +1194,42 @@
);
// Build the marker element with label + pin
const el =
document.createElement(
"div"
);
el.className =
"poi-pin-wrapper";
el.innerHTML = `
<div class="pin-label">
${escapeHtml(
getName(place)
)}
</div>
<div
class="poi-pin-inner"
style="background:${getPoiColor(place)};"
>
${getIcon(place)}
</div>
`;
const marker =
L.marker([
place.lat,
place.lon
], {
icon: createPoiIcon(place)
}).addTo(map);
new maplibregl.Marker({
element: el
})
.setLngLat([
place.lon,
place.lat
])
.addTo(map);
marker.bindTooltip(
escapeHtml(getName(place)),
{
permanent: true,
direction: "top",
offset: [0, -20],
className: "pin-label"
}
);
marker.on(
marker.getElement().addEventListener(
"click",
() => {
@@ -1231,26 +1258,36 @@
const zoom = getZoomForPlace(data[0]);
map.flyTo(
bounds[0],
zoom,
{
duration: 0.7
}
);
map.flyTo({
center: [
bounds[0][1],
bounds[0][0]
],
zoom: zoom,
duration: 700
});
}
else {
map.fitBounds(
bounds,
{
padding: [
80,
80
]
}
);
const lons =
bounds.map(b => b[1]);
const lats =
bounds.map(b => b[0]);
map.fitBounds([
[
Math.min(...lons),
Math.min(...lats)
],
[
Math.max(...lons),
Math.max(...lats)
]
], {
padding: 80
});
}
}
@@ -1361,47 +1398,66 @@
"none";
if (selectedMarker) {
map.removeLayer(
selectedMarker
);
}
clearSelection();
selectedMarker =
L.marker([
place.lat,
place.lon
]).addTo(map);
new maplibregl.Marker()
.setLngLat([
place.lon,
place.lat
])
.addTo(map);
const zoom = getZoomForPlace(place);
map.flyTo(
[
place.lat,
place.lon
map.flyTo({
center: [
place.lon,
place.lat
],
zoom,
{
duration: 0.7
}
);
zoom: zoom,
duration: 700
});
renderPlace(place);
}
/* =========================================================
CLEAR SELECTION
========================================================= */
function clearSelection() {
if (selectedMarker) {
selectedMarker.remove();
selectedMarker =
null;
}
if (selectedPopup) {
selectedPopup.remove();
selectedPopup =
null;
}
}
/* =========================================================
MAP CLICK
========================================================= */
map.on(
"click",
async event => {
async e => {
/*
* Don't reverse-geocode at low zoom.
@@ -1418,10 +1474,10 @@
const lat =
event.latlng.lat;
e.lngLat.lat;
const lon =
event.latlng.lng;
e.lngLat.lng;
resultsCard.style.display =
@@ -1441,19 +1497,16 @@
`;
if (selectedMarker) {
map.removeLayer(
selectedMarker
);
}
clearSelection();
selectedMarker =
L.marker([
lat,
lon
]).addTo(map);
new maplibregl.Marker()
.setLngLat([
lon,
lat
])
.addTo(map);
try {
@@ -1496,11 +1549,20 @@
}
selectedMarker.bindPopup(
escapeHtml(
getName(place)
selectedPopup =
new maplibregl.Popup({
offset: 25
})
.setHTML(
escapeHtml(
getName(place)
)
)
).openPopup();
.setLngLat([
lon,
lat
])
.addTo(map);
renderPlace(place);
@@ -1923,15 +1985,7 @@
"none";
if (selectedMarker) {
map.removeLayer(
selectedMarker
);
selectedMarker =
null;
}
clearSelection();
}
@@ -2185,30 +2239,41 @@
function showUserLocation(lat, lon) {
const coords = [lat, lon];
const coords = [lon, lat];
if (!userLocationMarker) {
const el =
document.createElement(
"div"
);
el.className =
"user-loc-marker";
el.innerHTML =
'<div class="user-loc-dot"></div>';
userLocationMarker =
L.marker(coords, {
icon: createUserLocationIcon(),
zIndexOffset: 1000
}).addTo(map);
new maplibregl.Marker({
element: el
})
.setLngLat(coords)
.addTo(map);
} else {
userLocationMarker.setLatLng(coords);
userLocationMarker.setLngLat(coords);
}
map.flyTo(
coords,
16,
{
duration: 0.8
}
);
map.flyTo({
center: coords,
zoom: 16,
duration: 800
});
}
@@ -2340,24 +2405,14 @@
markers.forEach(
marker =>
map.removeLayer(
marker
)
marker.remove()
);
markers = [];
if (selectedMarker) {
map.removeLayer(
selectedMarker
);
selectedMarker =
null;
}
clearSelection();
}
@@ -2481,7 +2536,7 @@
road +=
" " +
address.house_number;
address.house_number;
}
@@ -2655,38 +2710,6 @@
}
function createPoiIcon(place) {
const html = `
<div
class="poi-pin-inner"
style="background:${getPoiColor(place)};"
>
${getIcon(place)}
</div>
`;
return L.divIcon({
className: "poi-pin",
html: html,
iconSize: [34, 34],
iconAnchor: [17, 17]
});
}
function createUserLocationIcon() {
return L.divIcon({
className: "user-loc-marker",
html: `<div class="user-loc-dot"></div>`,
iconSize: [18, 18],
iconAnchor: [9, 9]
});
}
function safeUrl(url) {
if (!url)