@map-zero/ol 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@map-zero/ol",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "description": "OpenLayers integration helper for map-zero packages.",
6
6
  "license": "MIT",
@@ -22,10 +22,10 @@
22
22
  "README.md"
23
23
  ],
24
24
  "dependencies": {
25
- "@map-zero/raster": "0.3.1"
25
+ "@map-zero/raster": "0.3.2"
26
26
  },
27
27
  "peerDependencies": {
28
- "ol": "^10.9.0",
29
- "pmtiles": "^4.4.1"
28
+ "ol": "10.10.0",
29
+ "pmtiles": "4.4.1"
30
30
  }
31
31
  }
package/src/index.js CHANGED
@@ -10,6 +10,7 @@ import { PMTiles } from 'pmtiles';
10
10
  import { isAipLayer, layerAlias } from '../../raster/src/shared/layers.js';
11
11
  import { pmtilesInfo } from '../../raster/src/shared/manifest.js';
12
12
  import { clampInteger, clampNumber } from '../../raster/src/shared/math.js';
13
+ import { maxZoomExpression, minZoomExpression, zoomInterpolateExpression } from './zoom.js';
13
14
 
14
15
  import {
15
16
  activeLabelLayerIdsForZoom,
@@ -57,6 +58,7 @@ const ROAD_HIGHWAY_DRAW_ORDER = [
57
58
  * visibleLayers?: string[] | Set<string>,
58
59
  * source?: 'auto' | 'pmtiles' | 'dynamic',
59
60
  * renderMode?: 'vector' | 'raster-worker',
61
+ * hitDetection?: boolean,
60
62
  * workerUrl?: string | URL,
61
63
  * rasterPixelRatio?: number,
62
64
  * overzoomLevels?: number,
@@ -144,6 +146,7 @@ export async function createMapZeroOpenLayersLayers(options) {
144
146
  source,
145
147
  preload: 0,
146
148
  useInterimTilesOnError: false,
149
+ disableHitDetection: options.hitDetection === false,
147
150
  style: createWebGlStyles(context)
148
151
  });
149
152
  tagOpenLayersLayer(layer, instanceId, orderedLayers.map((item) => item.id), 'geometry');
@@ -1252,7 +1255,7 @@ function onewayFilter(filter) {
1252
1255
  * @returns {unknown[]}
1253
1256
  */
1254
1257
  function minZoomFilter(filter, zoom) {
1255
- return Number.isFinite(zoom) ? ['all', filter, ['>=', ['zoom'], zoom]] : filter;
1258
+ return Number.isFinite(zoom) ? ['all', filter, minZoomExpression(zoom)] : filter;
1256
1259
  }
1257
1260
 
1258
1261
  /**
@@ -1423,10 +1426,10 @@ function roadOverrideZoomFilter(filter, override) {
1423
1426
  const normalized = normalizeStyleRule(/** @type {Record<string, unknown>} */ (override));
1424
1427
  let next = filter;
1425
1428
  if (Number.isFinite(normalized.minZoom)) {
1426
- next = ['all', next, ['>=', ['zoom'], Number(normalized.minZoom)]];
1429
+ next = ['all', next, minZoomExpression(Number(normalized.minZoom))];
1427
1430
  }
1428
1431
  if (Number.isFinite(normalized.maxZoom)) {
1429
- next = ['all', next, ['<=', ['zoom'], Number(normalized.maxZoom)]];
1432
+ next = ['all', next, maxZoomExpression(Number(normalized.maxZoom))];
1430
1433
  }
1431
1434
  return next;
1432
1435
  }
@@ -1647,11 +1650,11 @@ function createLayerFilter(layerId, rule) {
1647
1650
  ];
1648
1651
 
1649
1652
  if (Number.isFinite(rule.minZoom)) {
1650
- filters.push(['>=', ['zoom'], Number(rule.minZoom)]);
1653
+ filters.push(minZoomExpression(Number(rule.minZoom)));
1651
1654
  }
1652
1655
 
1653
1656
  if (Number.isFinite(rule.maxZoom)) {
1654
- filters.push(['<=', ['zoom'], Number(rule.maxZoom)]);
1657
+ filters.push(maxZoomExpression(Number(rule.maxZoom)));
1655
1658
  }
1656
1659
 
1657
1660
  if (layerId === 'pois') {
@@ -1836,7 +1839,7 @@ function zoomWidthScale(rule) {
1836
1839
  return null;
1837
1840
  }
1838
1841
 
1839
- const expression = ['interpolate', ['linear'], ['zoom']];
1842
+ const validStops = [];
1840
1843
  for (const stop of stops) {
1841
1844
  if (!Array.isArray(stop) || stop.length < 2) {
1842
1845
  continue;
@@ -1845,11 +1848,11 @@ function zoomWidthScale(rule) {
1845
1848
  const zoom = Number(stop[0]);
1846
1849
  const scale = Number(stop[1]);
1847
1850
  if (Number.isFinite(zoom) && Number.isFinite(scale) && scale >= 0) {
1848
- expression.push(zoom, scale);
1851
+ validStops.push([zoom, scale]);
1849
1852
  }
1850
1853
  }
1851
1854
 
1852
- return expression.length > 4 ? expression : null;
1855
+ return zoomInterpolateExpression(validStops);
1853
1856
  }
1854
1857
 
1855
1858
  /**
package/src/labels.js CHANGED
@@ -155,7 +155,10 @@ export class LabelAtlas {
155
155
  * @returns {{ layer: VectorTileLayer, source: VectorTileSource, attachMap: () => void, detachMap: () => void, refresh: () => void, destroy: () => void }}
156
156
  */
157
157
  export function createMapZeroLabelLayer(options) {
158
- const format = new MVT({ featureClass: Feature });
158
+ // The geometry layer already decodes every map layer. Labels only need these
159
+ // source layers, so do not create Canvas features for buildings, water or
160
+ // other non-label data a second time.
161
+ const format = new MVT({ featureClass: Feature, layers: LABEL_SOURCE_LAYERS });
159
162
  const source = new VectorTileSource({
160
163
  format,
161
164
  maxZoom: 22,
package/src/zoom.js ADDED
@@ -0,0 +1,36 @@
1
+ const WEB_MERCATOR_RESOLUTION_AT_ZOOM_0 = 156543.03392804097;
2
+
3
+ /**
4
+ * The WebGL style compiler exposes resolution in all supported render paths.
5
+ * Convert the standard Web Mercator zoom thresholds used by map-zero styles.
6
+ *
7
+ * @param {number} zoom
8
+ * @returns {number}
9
+ */
10
+ export function resolutionForZoom(zoom) {
11
+ return WEB_MERCATOR_RESOLUTION_AT_ZOOM_0 / (2 ** zoom);
12
+ }
13
+
14
+ /** @param {number} zoom @returns {unknown[]} */
15
+ export function minZoomExpression(zoom) {
16
+ return ['<=', ['resolution'], resolutionForZoom(zoom)];
17
+ }
18
+
19
+ /** @param {number} zoom @returns {unknown[]} */
20
+ export function maxZoomExpression(zoom) {
21
+ return ['>=', ['resolution'], resolutionForZoom(zoom)];
22
+ }
23
+
24
+ /**
25
+ * @param {Array<[number, number]>} stops
26
+ * @returns {unknown[] | null}
27
+ */
28
+ export function zoomInterpolateExpression(stops) {
29
+ const entries = stops
30
+ .filter(([zoom, value]) => Number.isFinite(zoom) && Number.isFinite(value))
31
+ .map(([zoom, value]) => ({ resolution: resolutionForZoom(zoom), value }))
32
+ .sort((left, right) => left.resolution - right.resolution);
33
+
34
+ if (entries.length < 2) return null;
35
+ return ['interpolate', ['linear'], ['resolution'], ...entries.flatMap(({ resolution, value }) => [resolution, value])];
36
+ }