mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 14:44:51 +02:00
fix: contour overlay with pmtiles fork, absolute URL, extended zoom range
- Switch to @acalcutt/maplibre-contour-pmtiles for PMTiles support - Use absolute URL for DemSource so Web Worker can resolve path - Extend contour thresholds from z3-z15 for full zoom coverage - Improve line styling with zoom-dependent width - Improve label styling with bold font and better halo Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f3ec18bdf5
commit
400c485833
3 changed files with 56 additions and 31 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
|
@ -8,11 +8,11 @@
|
||||||
"name": "navi",
|
"name": "navi",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@acalcutt/maplibre-contour-pmtiles": "^0.1.2",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"lucide-react": "^1.8.0",
|
"lucide-react": "^1.8.0",
|
||||||
"maplibre-contour": "^0.1.0",
|
|
||||||
"maplibre-gl": "^5.23.0",
|
"maplibre-gl": "^5.23.0",
|
||||||
"opening_hours": "^3.12.0",
|
"opening_hours": "^3.12.0",
|
||||||
"pmtiles": "^4.4.1",
|
"pmtiles": "^4.4.1",
|
||||||
|
|
@ -38,6 +38,12 @@
|
||||||
"vite": "^8.0.9"
|
"vite": "^8.0.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@acalcutt/maplibre-contour-pmtiles": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@acalcutt/maplibre-contour-pmtiles/-/maplibre-contour-pmtiles-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-dCyJFLLM4NomLoJ22McRp7yETFmzUuA6iEMVJS6+mFyHoNk7Sv6RI4Hn0DhGKeyjcJgan3YnfSnzsqRinnXSug==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
"node_modules/@alloc/quick-lru": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
||||||
|
|
@ -2686,12 +2692,6 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/maplibre-contour": {
|
|
||||||
"version": "0.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/maplibre-contour/-/maplibre-contour-0.1.0.tgz",
|
|
||||||
"integrity": "sha512-H8muT7JWYE4oLbFv7L2RSbIM1NOu5JxjA9P/TQqhODDnRChE8ENoDkQIWOKgfcKNU77ypLk2ggGoh4/pt4UPLA==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/maplibre-gl": {
|
"node_modules/maplibre-gl": {
|
||||||
"version": "5.23.0",
|
"version": "5.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.23.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@acalcutt/maplibre-contour-pmtiles": "^0.1.2",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
"lucide-react": "^1.8.0",
|
"lucide-react": "^1.8.0",
|
||||||
"maplibre-contour": "^0.1.0",
|
|
||||||
"maplibre-gl": "^5.23.0",
|
"maplibre-gl": "^5.23.0",
|
||||||
"opening_hours": "^3.12.0",
|
"opening_hours": "^3.12.0",
|
||||||
"pmtiles": "^4.4.1",
|
"pmtiles": "^4.4.1",
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import { MapPin, Navigation, ArrowUpRight, ArrowDownLeft, Plus, Star, Ruler, X }
|
||||||
import RadialMenu from './RadialMenu'
|
import RadialMenu from './RadialMenu'
|
||||||
import useContextMenu from '../hooks/useContextMenu'
|
import useContextMenu from '../hooks/useContextMenu'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import mlcontour from 'maplibre-contour'
|
import mlcontour from '@acalcutt/maplibre-contour-pmtiles'
|
||||||
|
|
||||||
let demSourceInstance = null
|
let demSourceInstance = null
|
||||||
|
|
||||||
|
|
@ -565,19 +565,34 @@ function removePublicLands(map) {
|
||||||
|
|
||||||
/** Add topographic contours via maplibre-contour */
|
/** Add topographic contours via maplibre-contour */
|
||||||
function addContours(map) {
|
function addContours(map) {
|
||||||
console.log('[CONTOUR] addContours called, source exists:', !!map?.getSource(CONTOUR_SOURCE))
|
console.log('[CONTOUR] addContours called, source exists:', !!map?.getSource(CONTOUR_SOURCE), 'demSource:', !!demSourceInstance)
|
||||||
if (!map || map.getSource(CONTOUR_SOURCE)) return
|
if (!map || !demSourceInstance || map.getSource(CONTOUR_SOURCE)) return
|
||||||
|
const contourThresholds = {
|
||||||
|
3: [5000, 25000],
|
||||||
|
4: [2500, 10000],
|
||||||
|
5: [1000, 5000],
|
||||||
|
6: [1000, 5000],
|
||||||
|
7: [500, 2500],
|
||||||
|
8: [500, 2500],
|
||||||
|
9: [250, 1000],
|
||||||
|
10: [200, 1000],
|
||||||
|
11: [200, 1000],
|
||||||
|
12: [100, 500],
|
||||||
|
13: [100, 500],
|
||||||
|
14: [50, 200],
|
||||||
|
15: [20, 100],
|
||||||
|
}
|
||||||
map.addSource(CONTOUR_SOURCE, {
|
map.addSource(CONTOUR_SOURCE, {
|
||||||
type: 'vector',
|
type: 'vector',
|
||||||
tiles: [demSourceInstance.contourProtocolUrl({
|
tiles: [demSourceInstance.contourProtocolUrl({
|
||||||
multiplier: 3.28084,
|
multiplier: 3.28084,
|
||||||
thresholds: { 11: [200, 1000], 12: [100, 500], 13: [100, 500], 14: [50, 200] },
|
thresholds: contourThresholds,
|
||||||
})],
|
})],
|
||||||
maxzoom: 15,
|
maxzoom: 16,
|
||||||
})
|
})
|
||||||
console.log('[CONTOUR] protocol URL:', demSourceInstance.contourProtocolUrl({
|
console.log('[CONTOUR] protocol URL:', demSourceInstance.contourProtocolUrl({
|
||||||
multiplier: 3.28084,
|
multiplier: 3.28084,
|
||||||
thresholds: { 11: [200, 1000], 12: [100, 500], 13: [100, 500], 14: [50, 200] },
|
thresholds: contourThresholds,
|
||||||
}))
|
}))
|
||||||
console.log('[CONTOUR] source added:', !!map.getSource(CONTOUR_SOURCE))
|
console.log('[CONTOUR] source added:', !!map.getSource(CONTOUR_SOURCE))
|
||||||
let beforeId = undefined
|
let beforeId = undefined
|
||||||
|
|
@ -589,9 +604,13 @@ function addContours(map) {
|
||||||
id: CONTOUR_LINE, type: 'line', source: CONTOUR_SOURCE,
|
id: CONTOUR_LINE, type: 'line', source: CONTOUR_SOURCE,
|
||||||
'source-layer': 'contours',
|
'source-layer': 'contours',
|
||||||
paint: {
|
paint: {
|
||||||
'line-color': isDark ? '#c0b898' : '#8b6f47',
|
'line-color': 'rgba(0,0,0,0.35)',
|
||||||
'line-opacity': 0.7,
|
'line-width': [
|
||||||
'line-width': ['match', ['get', 'level'], 1, 1.5, 0.5],
|
'interpolate', ['linear'], ['zoom'],
|
||||||
|
7, ['match', ['get', 'level'], 1, 1, 0.3],
|
||||||
|
11, ['match', ['get', 'level'], 1, 1.5, 0.6],
|
||||||
|
14, ['match', ['get', 'level'], 1, 2, 0.8],
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}, beforeId)
|
}, beforeId)
|
||||||
map.addLayer({
|
map.addLayer({
|
||||||
|
|
@ -599,13 +618,15 @@ function addContours(map) {
|
||||||
'source-layer': 'contours',
|
'source-layer': 'contours',
|
||||||
filter: ['>', ['get', 'level'], 0],
|
filter: ['>', ['get', 'level'], 0],
|
||||||
layout: {
|
layout: {
|
||||||
'symbol-placement': 'line', 'text-size': 10,
|
'symbol-placement': 'line',
|
||||||
|
'text-size': ['interpolate', ['linear'], ['zoom'], 7, 9, 11, 11, 14, 13],
|
||||||
'text-field': ['concat', ['number-format', ['get', 'ele'], {}], "'"],
|
'text-field': ['concat', ['number-format', ['get', 'ele'], {}], "'"],
|
||||||
'text-font': ['Noto Sans Regular'],
|
'text-font': ['Noto Sans Bold'],
|
||||||
|
'text-max-angle': 25,
|
||||||
},
|
},
|
||||||
paint: {
|
paint: {
|
||||||
'text-color': isDark ? '#c0b898' : '#5a4020',
|
'text-color': 'rgba(0,0,0,0.7)',
|
||||||
'text-halo-color': isDark ? '#1a1a1a' : '#ffffff',
|
'text-halo-color': 'rgba(255,255,255,0.9)',
|
||||||
'text-halo-width': 1.5,
|
'text-halo-width': 1.5,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -2026,18 +2047,22 @@ const MapView = forwardRef(function MapView(_, ref) {
|
||||||
const protocol = new Protocol()
|
const protocol = new Protocol()
|
||||||
maplibregl.addProtocol('pmtiles', protocol.tile)
|
maplibregl.addProtocol('pmtiles', protocol.tile)
|
||||||
|
|
||||||
// Initialize DemSource for maplibre-contour
|
|
||||||
if (!demSourceInstance) {
|
|
||||||
demSourceInstance = new mlcontour.DemSource({
|
|
||||||
url: `${window.location.origin}/tiles/terrain/{z}/{x}/{y}`,
|
|
||||||
encoding: 'terrarium',
|
|
||||||
maxzoom: 14,
|
|
||||||
worker: true,
|
|
||||||
})
|
|
||||||
demSourceInstance.setupMaplibre(maplibregl)
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = getConfig()
|
const config = getConfig()
|
||||||
|
|
||||||
|
// Initialize DemSource for maplibre-contour (uses same PMTiles as hillshade)
|
||||||
|
if (!demSourceInstance) {
|
||||||
|
const hs = config?.tileset_hillshade
|
||||||
|
if (hs?.url) {
|
||||||
|
demSourceInstance = new mlcontour.DemSource({
|
||||||
|
url: `pmtiles://${window.location.origin}${hs.url}`,
|
||||||
|
encoding: hs.encoding || 'terrarium',
|
||||||
|
maxzoom: hs.max_zoom || 12,
|
||||||
|
worker: true,
|
||||||
|
cacheSize: 100,
|
||||||
|
})
|
||||||
|
demSourceInstance.setupMaplibre(maplibregl)
|
||||||
|
}
|
||||||
|
}
|
||||||
const DEFAULT_CENTER = config?.defaults?.center
|
const DEFAULT_CENTER = config?.defaults?.center
|
||||||
? [config.defaults.center[1], config.defaults.center[0]] // config is [lat,lon], MapLibre wants [lon,lat]
|
? [config.defaults.center[1], config.defaults.center[0]] // config is [lat,lon], MapLibre wants [lon,lat]
|
||||||
: [-114.6066, 42.5736]
|
: [-114.6066, 42.5736]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue