v0.3, 16-10-2025 pupicon added
This commit is contained in:
236
www/archive/index.html
Normal file
236
www/archive/index.html
Normal file
@@ -0,0 +1,236 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Pupmap by BoopLabs – v2025-10-03_2300</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" rel="stylesheet"/>
|
||||
<script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
|
||||
<script src="https://unpkg.com/pmtiles/dist/pmtiles.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<input id="searchBox" placeholder="Search place..." />
|
||||
<div id="map"></div>
|
||||
|
||||
<script>
|
||||
const protocol = new pmtiles.Protocol();
|
||||
maplibregl.addProtocol("pmtiles", protocol.tile);
|
||||
|
||||
const map = new maplibregl.Map({
|
||||
container: 'map',
|
||||
style: 'style.json',
|
||||
center: [10, 60],
|
||||
zoom: 4
|
||||
});
|
||||
|
||||
map.on('load', () => {
|
||||
// Roads
|
||||
map.addSource('roads', {
|
||||
type: 'geojson',
|
||||
data: 'data/roads_europe_clean.geojson'
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'roads-minor',
|
||||
type: 'line',
|
||||
source: 'roads',
|
||||
filter: ['==', ['get', 'type'], 'minor'],
|
||||
paint: {
|
||||
'line-color': '#cccccc',
|
||||
'line-width': 1,
|
||||
'line-opacity': 0.5
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'roads-major',
|
||||
type: 'line',
|
||||
source: 'roads',
|
||||
filter: ['==', ['get', 'type'], 'major'],
|
||||
paint: {
|
||||
'line-color': '#555555',
|
||||
'line-width': 2,
|
||||
'line-opacity': 0.7
|
||||
}
|
||||
});
|
||||
|
||||
// Cities
|
||||
map.addSource('cities', {
|
||||
type: 'geojson',
|
||||
data: 'data/world_cities_europe_clean.geojson'
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'city-points-small',
|
||||
type: 'circle',
|
||||
source: 'cities',
|
||||
filter: ['<', ['get','POP_MAX'], 100000],
|
||||
paint: {
|
||||
'circle-radius': 3,
|
||||
'circle-color': '#999999',
|
||||
'circle-stroke-width': 1,
|
||||
'circle-stroke-color': '#666666'
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'city-points-medium',
|
||||
type: 'circle',
|
||||
source: 'cities',
|
||||
filter: ['all', ['>=', ['get','POP_MAX'], 100000], ['<', ['get','POP_MAX'], 500000]],
|
||||
paint: {
|
||||
'circle-radius': 5,
|
||||
'circle-color': '#777777',
|
||||
'circle-stroke-width': 1,
|
||||
'circle-stroke-color': '#555555'
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'city-points-large',
|
||||
type: 'circle',
|
||||
source: 'cities',
|
||||
filter: ['>=', ['get','POP_MAX'], 500000],
|
||||
paint: {
|
||||
'circle-radius': 7,
|
||||
'circle-color': '#444444',
|
||||
'circle-stroke-width': 1,
|
||||
'circle-stroke-color': '#222222'
|
||||
}
|
||||
});
|
||||
|
||||
// City labels, zoom + population based
|
||||
map.addLayer({
|
||||
id: 'city-labels',
|
||||
type: 'symbol',
|
||||
source: 'cities',
|
||||
layout: {
|
||||
'text-field': ['get', 'NAME'],
|
||||
'text-font': ['Noto Sans Regular'],
|
||||
'text-size': [
|
||||
'interpolate', ['linear'], ['zoom'],
|
||||
4, 10,
|
||||
6, 12,
|
||||
10, 16
|
||||
],
|
||||
'text-offset': [0, 1.2],
|
||||
'text-anchor': 'top'
|
||||
},
|
||||
paint: {
|
||||
'text-color': '#222222',
|
||||
'text-halo-color': '#ffffff',
|
||||
'text-halo-width': 1
|
||||
},
|
||||
filter: [
|
||||
'>',
|
||||
['get','POP_MAX'],
|
||||
['interpolate', ['linear'], ['zoom'],
|
||||
4, 2000000, // at zoom 4, only megacities
|
||||
6, 1000000, // at zoom 6, large cities
|
||||
8, 500000, // at zoom 8, medium cities
|
||||
10, 100000 // at zoom 10+, small cities
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// City popups
|
||||
map.on('click', ['city-points-small','city-points-medium','city-points-large'], (e) => {
|
||||
const coordinates = e.features[0].geometry.coordinates.slice();
|
||||
const cityName = e.features[0].properties.NAME || "Unknown City";
|
||||
const population = e.features[0].properties.POP_MAX || "n/a";
|
||||
new maplibregl.Popup()
|
||||
.setLngLat(coordinates)
|
||||
.setHTML(`<strong>${cityName}</strong><br/>Population: ${population}`)
|
||||
.addTo(map);
|
||||
});
|
||||
|
||||
// Cursor for city dots
|
||||
['city-points-small','city-points-medium','city-points-large'].forEach(layer => {
|
||||
map.on('mouseenter', layer, () => { map.getCanvas().style.cursor = 'pointer'; });
|
||||
map.on('mouseleave', layer, () => { map.getCanvas().style.cursor = ''; });
|
||||
});
|
||||
|
||||
// POIs
|
||||
map.addSource('pois', {
|
||||
type: 'geojson',
|
||||
data: 'data/pois.geojson',
|
||||
cluster: true,
|
||||
clusterMaxZoom: 14,
|
||||
clusterRadius: 50
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'clusters',
|
||||
type: 'circle',
|
||||
source: 'pois',
|
||||
filter: ['has', 'point_count'],
|
||||
paint: {
|
||||
'circle-color': '#FF0000',
|
||||
'circle-radius': ['step', ['get','point_count'], 15, 10, 20, 50, 25],
|
||||
'circle-opacity': 0.7,
|
||||
'circle-stroke-width': 1,
|
||||
'circle-stroke-color': '#fff'
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'unclustered-point',
|
||||
type: 'circle',
|
||||
source: 'pois',
|
||||
filter: ['!', ['has','point_count']],
|
||||
paint: {
|
||||
'circle-color': '#FF0000',
|
||||
'circle-radius': 8,
|
||||
'circle-opacity': 0.7,
|
||||
'circle-stroke-width': 1,
|
||||
'circle-stroke-color': '#fff'
|
||||
}
|
||||
});
|
||||
|
||||
map.on('click', 'unclustered-point', (e) => {
|
||||
const coordinates = e.features[0].geometry.coordinates.slice();
|
||||
const popupContent = e.features[0].properties.popup || e.features[0].properties.names.join(', ');
|
||||
new maplibregl.Popup()
|
||||
.setLngLat(coordinates)
|
||||
.setHTML(`<strong>${popupContent}</strong>`)
|
||||
.addTo(map);
|
||||
});
|
||||
|
||||
map.on('click', 'clusters', (e) => {
|
||||
const features = map.queryRenderedFeatures(e.point, { layers: ['clusters'] });
|
||||
const clusterId = features[0].properties.cluster_id;
|
||||
map.getSource('pois').getClusterExpansionZoom(clusterId, (err, zoom) => {
|
||||
if (err) return;
|
||||
map.easeTo({ center: features[0].geometry.coordinates, zoom: zoom });
|
||||
});
|
||||
});
|
||||
|
||||
['clusters', 'unclustered-point'].forEach(layer => {
|
||||
map.on('mouseenter', layer, () => { map.getCanvas().style.cursor = 'pointer'; });
|
||||
map.on('mouseleave', layer, () => { map.getCanvas().style.cursor = ''; });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Nominatim search
|
||||
document.getElementById('searchBox').addEventListener('keypress', async function(e){
|
||||
if(e.key==='Enter'){
|
||||
const query = e.target.value;
|
||||
const url = `http://yourhost:7070/search?q=${encodeURIComponent(query)}&format=json`;
|
||||
try{
|
||||
const res = await fetch(url);
|
||||
const results = await res.json();
|
||||
if(results.length>0){
|
||||
const loc = results[0];
|
||||
map.flyTo({ center: [loc.lon, loc.lat], zoom: 12 });
|
||||
}else{ alert("No results found"); }
|
||||
}catch(err){ alert("Error connecting to search API"); console.error(err);}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user