Skip to content

Commit e3a76de

Browse files
committed
Add support for non Mercator projection in OL view
give the opportunity to translate the zoom level before giving it to MapLibre. This makes it possible to have OL functioning with a non-Mercator projection system, and still be able to have MapLibre receiving a valid Mercator zoom level to keep the maps in sync. You can see this code in action here : geoadmin/web-mapviewer#981 where we have our OL instance working in LV95.
1 parent 49e5336 commit e3a76de

2 files changed

Lines changed: 23 additions & 3 deletions

File tree

src/MapLibreLayer.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,20 @@ import getMapLibreAttributions from './getMapLibreAttributions.js';
1212

1313
export type MapLibreOptions = Omit<MapOptions, 'container'>;
1414

15+
/**
16+
* Receives the zoom level from the OpenLayers view
17+
* and can transform it for MapLibre in case the projection
18+
* system used by OL isn't using a standard Mercator pyramid.
19+
*
20+
* This enables the MapLibreLayer to work in Mercator zooms even if OL
21+
* is using a localized projection (such as LV95 for Switzerland)
22+
*/
23+
export type MapLibreLayerTranslateZoomFunction = (zoom: number) => number;
24+
1525
export type MapLibreLayerOptions = LayerOptions & {
1626
mapLibreOptions: MapLibreOptions;
1727
queryRenderedFeaturesOptions?: QueryRenderedFeaturesOptions;
28+
translateZoom?: MapLibreLayerTranslateZoomFunction
1829
};
1930

2031
export default class MapLibreLayer extends Layer {
@@ -105,6 +116,7 @@ export default class MapLibreLayer extends Layer {
105116
}
106117

107118
override createRenderer(): MapLibreLayerRenderer {
108-
return new MapLibreLayerRenderer(this);
119+
const translateZoom = this.get('translateZoom') as MapLibreLayerTranslateZoomFunction | undefined;
120+
return new MapLibreLayerRenderer(this, translateZoom);
109121
}
110122
}

src/MapLibreLayerRenderer.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {Geometry} from 'ol/geom.js';
1212
import {SimpleGeometry} from 'ol/geom.js';
1313
import type {Pixel} from 'ol/pixel.js';
1414
import type MapLibreLayer from './MapLibreLayer.js';
15+
import type { MapLibreLayerTranslateZoomFunction } from './MapLibreLayer.js'
1516

1617
const VECTOR_TILE_FEATURE_PROPERTY = 'vectorTileFeature';
1718

@@ -28,6 +29,13 @@ const formats: {
2829
* functionalities like map.getFeaturesAtPixel or map.hasFeatureAtPixel.
2930
*/
3031
export default class MapLibreLayerRenderer extends LayerRenderer<MapLibreLayer> {
32+
private readonly translateZoom: MapLibreLayerTranslateZoomFunction | undefined
33+
34+
constructor(layer: MapLibreLayer, translateZoom: MapLibreLayerTranslateZoomFunction | undefined) {
35+
super(layer)
36+
this.translateZoom = translateZoom
37+
}
38+
3139
getFeaturesAtCoordinate(
3240
coordinate: Coordinate | undefined,
3341
hitTolerance: number = 5,
@@ -71,8 +79,8 @@ export default class MapLibreLayerRenderer extends LayerRenderer<MapLibreLayer>
7179

7280
// adjust view parameters in MapLibre
7381
mapLibreMap.jumpTo({
74-
center: toLonLat(viewState.center) as [number, number],
75-
zoom: viewState.zoom - 1,
82+
center: toLonLat(viewState.center, viewState.projection) as [number, number],
83+
zoom: (this.translateZoom ? this.translateZoom(viewState.zoom) : viewState.zoom) - 1 ,
7684
bearing: toDegrees(-viewState.rotation),
7785
});
7886

0 commit comments

Comments
 (0)