From 354568984ad4c11add52f377580f80470da62efc Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sun, 8 Nov 2026 00:17:19 -0800 Subject: [PATCH] Give each overlay kind its own pane z-index band MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pane z-indexes come from overlayStackZ (js-sdk-core): bands of 60 from 211 to 569 in the shared order raster < ground image < polygon < circle < polyline < marker, zIndex clamped to ±29 inside a band, between Leaflet's tilePane (200) and markerPane (600). Polygons, circles and polylines used to share 400 ± zIndex, so with equal zIndexes the pane created first was drawn under the others (a circle added after a polygon was on top, added before it was under). A raster could reach 350, over ground images (300). Marker tiles, mounted as a raster, were in the raster band under every shape; they are in the marker band now. Needs the js-sdk-core release with overlayStackZ. --- src/helpers.ts | 16 +++++++++++++++- src/raster/LeafletRasterLayer.ts | 6 ++++-- src/vector/LeafletVectorControllers.ts | 20 +++++++++----------- 3 files changed, 28 insertions(+), 14 deletions(-) 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.