diff --git a/src/helpers.ts b/src/helpers.ts index 9aa76dc..2107967 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,4 +1,4 @@ -import { createGeoPoint, type GeoPoint, type GeoPointInterface } from '@mapconductor/js-sdk-core'; +import { createGeoPoint, overlayStackZ, type GeoPoint, type GeoPointInterface, type OverlayKind } from '@mapconductor/js-sdk-core'; import type { LatLngExpression, LeafletMouseEvent, Map as LeafletMap } from 'leaflet'; export const toLatLng = (point: GeoPointInterface): LatLngExpression => [ @@ -22,3 +22,17 @@ export function ensurePane( pane.style.pointerEvents = pointerEvents; return name; } + +/** + * Pane z-index for an overlay, from the shared stack (js-sdk-core OVERLAY_STACK_ORDER): + * raster < ground image < polygon < circle < polyline < marker, zIndex within the band. + * + * Bands of 60 from 211 to 569: above Leaflet's tilePane (200, the basemap) and below its + * markerPane (600, the native markers). zIndex is clamped to ±29 so it cannot cross a band. + * Polygons, circles and polylines used to share one range (400 ± zIndex), so with equal + * zIndexes whichever pane was created first was drawn under the others; a raster could go up + * to 350, over ground images (300) and low-zIndex shapes. + */ +export function overlayPaneZIndex(kind: OverlayKind, zIndex: number | null | undefined = 0): number { + return overlayStackZ(kind, zIndex, { base: 240, bandSize: 60 }); +} diff --git a/src/raster/LeafletRasterLayer.ts b/src/raster/LeafletRasterLayer.ts index 4b827ad..ea4cf03 100644 --- a/src/raster/LeafletRasterLayer.ts +++ b/src/raster/LeafletRasterLayer.ts @@ -20,7 +20,7 @@ import { type TileLayerOptions, } from 'leaflet'; import { LeafletMapViewHolder } from '../LeafletMapViewHolder'; -import { ensurePane } from '../helpers'; +import { ensurePane, overlayPaneZIndex } from '../helpers'; import { parseLocalTileTemplate, type LocalTileTemplate } from './localTileUrl'; const EMPTY_TILE = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; @@ -162,7 +162,9 @@ export class LeafletRasterLayerRenderer { const pane = ensurePane( this.holder.map, `mc-raster-${state.id}`, - 250 + Math.max(-100, Math.min(100, state.zIndex)), + // Marker tiles are mounted as a raster but belong with the markers (under the native + // marker pane, over the shapes). + state.id === 'mc-marker-tiles' ? overlayPaneZIndex('marker', 0) : overlayPaneZIndex('rasterLayer', state.zIndex), 'none', ); const baseOptions = { pane, opacity: state.opacity }; diff --git a/src/vector/LeafletVectorControllers.ts b/src/vector/LeafletVectorControllers.ts index c0aaa19..50d8d21 100644 --- a/src/vector/LeafletVectorControllers.ts +++ b/src/vector/LeafletVectorControllers.ts @@ -36,17 +36,15 @@ import { type Polyline as LeafletPolyline, } from 'leaflet'; import { LeafletMapViewHolder } from '../LeafletMapViewHolder'; -import { ensurePane } from '../helpers'; +import { ensurePane, overlayPaneZIndex } from '../helpers'; -const VECTOR_BASE_Z_INDEX = 400; -const GROUND_IMAGE_BASE_Z_INDEX = 300; - -function vectorPane(holder: LeafletMapViewHolder, kind: string, id: string, zIndex: number): string { - return ensurePane( - holder.map, - `mc-${kind}-${id}`, - VECTOR_BASE_Z_INDEX + Math.max(-100, Math.min(100, zIndex)), - ); +function vectorPane( + holder: LeafletMapViewHolder, + kind: 'circle' | 'polyline' | 'polygon', + id: string, + zIndex: number, +): string { + return ensurePane(holder.map, `mc-${kind}-${id}`, overlayPaneZIndex(kind, zIndex)); } export class LeafletCircleRenderer extends AbstractCircleOverlayRenderer< @@ -257,7 +255,7 @@ export class LeafletGroundImageRenderer extends AbstractGroundImageOverlayRender const pane = ensurePane( this.holder.map, `mc-ground-image-${state.id}`, - GROUND_IMAGE_BASE_Z_INDEX, + overlayPaneZIndex('groundImage'), ); // Non-interactive: clicks are resolved by the shared core geometric hit-test // (inside the image bounds) in the map click handler, like every other provider.