maplibre-gl 3.6.1 → 3.6.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,7 +1,7 @@
1
1
  {
2
2
  "name": "maplibre-gl",
3
3
  "description": "BSD licensed community fork of mapbox-gl, a WebGL interactive maps library",
4
- "version": "3.6.1",
4
+ "version": "3.6.2",
5
5
  "main": "dist/maplibre-gl.js",
6
6
  "style": "dist/maplibre-gl.css",
7
7
  "license": "BSD-3-Clause",
@@ -23,8 +23,8 @@
23
23
  "@maplibre/maplibre-gl-style-spec": "^19.3.3",
24
24
  "@types/geojson": "^7946.0.13",
25
25
  "@types/mapbox__point-geometry": "^0.1.4",
26
- "@types/mapbox__vector-tile": "^1.3.3",
27
- "@types/pbf": "^3.0.4",
26
+ "@types/mapbox__vector-tile": "^1.3.4",
27
+ "@types/pbf": "^3.0.5",
28
28
  "@types/supercluster": "^7.1.3",
29
29
  "earcut": "^2.2.4",
30
30
  "geojson-vt": "^3.2.1",
@@ -51,39 +51,39 @@
51
51
  "@rollup/plugin-typescript": "^11.1.5",
52
52
  "@types/benchmark": "^2.1.5",
53
53
  "@types/cssnano": "^5.0.0",
54
- "@types/d3": "^7.4.2",
54
+ "@types/d3": "^7.4.3",
55
55
  "@types/diff": "^5.0.8",
56
56
  "@types/earcut": "^2.1.4",
57
57
  "@types/eslint": "^8.44.7",
58
58
  "@types/geojson-vt": "3.2.4",
59
- "@types/gl": "^6.0.4",
59
+ "@types/gl": "^6.0.5",
60
60
  "@types/glob": "^8.1.0",
61
- "@types/jest": "^29.5.3",
61
+ "@types/jest": "^29.5.8",
62
62
  "@types/jsdom": "^21.1.5",
63
63
  "@types/minimist": "^1.2.5",
64
- "@types/murmurhash-js": "^1.0.5",
64
+ "@types/murmurhash-js": "^1.0.6",
65
65
  "@types/nise": "^1.4.4",
66
- "@types/node": "^20.8.3",
66
+ "@types/node": "^20.9.2",
67
67
  "@types/offscreencanvas": "^2019.7.3",
68
- "@types/pixelmatch": "^5.2.5",
68
+ "@types/pixelmatch": "^5.2.6",
69
69
  "@types/pngjs": "^6.0.4",
70
- "@types/react": "^18.2.35",
71
- "@types/react-dom": "^18.2.14",
70
+ "@types/react": "^18.2.37",
71
+ "@types/react-dom": "^18.2.15",
72
72
  "@types/request": "^2.48.12",
73
73
  "@types/shuffle-seed": "^1.1.2",
74
74
  "@types/window-or-global": "^1.0.6",
75
- "@typescript-eslint/eslint-plugin": "^6.10.0",
76
- "@typescript-eslint/parser": "^6.10.0",
75
+ "@typescript-eslint/eslint-plugin": "^6.11.0",
76
+ "@typescript-eslint/parser": "^6.11.0",
77
77
  "address": "^2.0.1",
78
78
  "benchmark": "^2.1.4",
79
79
  "canvas": "^2.11.2",
80
80
  "cssnano": "^6.0.1",
81
81
  "d3": "^7.8.5",
82
82
  "d3-queue": "^3.0.7",
83
- "devtools-protocol": "^0.0.1219864",
83
+ "devtools-protocol": "^0.0.1226504",
84
84
  "diff": "^5.1.0",
85
85
  "dts-bundle-generator": "^8.1.2",
86
- "eslint": "^8.53.0",
86
+ "eslint": "^8.54.0",
87
87
  "eslint-config-mourner": "^3.0.0",
88
88
  "eslint-plugin-html": "^7.1.0",
89
89
  "eslint-plugin-import": "^2.29.0",
@@ -94,9 +94,9 @@
94
94
  "gl": "^6.0.2",
95
95
  "glob": "^10.3.10",
96
96
  "is-builtin-module": "^3.2.1",
97
- "jest": "^29.6.2",
97
+ "jest": "^29.7.0",
98
98
  "jest-canvas-mock": "^2.5.2",
99
- "jest-environment-jsdom": "^29.6.2",
99
+ "jest-environment-jsdom": "^29.7.0",
100
100
  "jsdom": "^22.1.0",
101
101
  "json-stringify-pretty-compact": "^4.0.0",
102
102
  "minimist": "^1.2.8",
@@ -111,10 +111,10 @@
111
111
  "postcss-cli": "^10.1.0",
112
112
  "postcss-inline-svg": "^6.0.0",
113
113
  "pretty-bytes": "^6.1.1",
114
- "puppeteer": "^21.5.1",
114
+ "puppeteer": "^21.5.2",
115
115
  "react": "^18.2.0",
116
116
  "react-dom": "^18.2.0",
117
- "rollup": "^4.4.0",
117
+ "rollup": "^4.5.0",
118
118
  "rollup-plugin-sourcemaps": "^0.6.3",
119
119
  "rw": "^1.3.3",
120
120
  "semver": "^7.5.4",
@@ -15,10 +15,12 @@ import {LngLat} from '../geo/lng_lat';
15
15
 
16
16
  describe('Terrain', () => {
17
17
  test('pointCoordiate should not return null', () => {
18
+ expect.assertions(1);
18
19
  const painter = {
19
20
  context: new Context(gl(1, 1) as any),
20
21
  width: 1,
21
- height: 1
22
+ height: 1,
23
+ transform: {center: {lng: 0}}
22
24
  } as any as Painter;
23
25
  const sourceCache = {} as SourceCache;
24
26
  const getTileByID = (tileID) : Tile => {
@@ -50,6 +52,59 @@ describe('Terrain', () => {
50
52
  expect(coordinate).not.toBeNull();
51
53
  });
52
54
 
55
+ const setupMercatorOverflow = (centerLng: number) => {
56
+ const WORLD_WIDTH = 4;
57
+ const painter = {
58
+ context: new Context(gl(WORLD_WIDTH, 1) as any),
59
+ width: WORLD_WIDTH,
60
+ height: 1,
61
+ transform: {center: {lng: centerLng}}
62
+ } as any as Painter;
63
+ const sourceCache = {} as SourceCache;
64
+ const terrain = new Terrain(painter, sourceCache, {} as any as TerrainSpecification);
65
+ const mockTile = {tileID: {canonical: {x: 0, y: 0, z: 0}}};
66
+ terrain.sourceCache.getTileByID = () => mockTile as any as Tile;
67
+ terrain.getElevation = () => 0;
68
+ terrain.coordsIndex = ['abcd'];
69
+ terrain._coordsTextureSize = WORLD_WIDTH;
70
+ const pixels = new Uint8Array([2, 0, 0, 255, 3, 0, 0, 255, 0, 0, 0, 255, 1, 0, 0, 255]);
71
+ const image = new RGBAImage({width: WORLD_WIDTH, height: 1}, pixels);
72
+ const imageTexture = new Texture(painter.context, image, painter.context.gl.RGBA);
73
+ terrain.getFramebuffer('coords'); // allow init of frame buffers
74
+ terrain._fboCoordsTexture.texture = imageTexture.texture;
75
+ return terrain;
76
+ };
77
+
78
+ test(
79
+ `pointCoordiate should return negative mercator x
80
+ if center.lng is to the right of 180 meridian
81
+ and a given point is to the left of 180`,
82
+ () => {
83
+ expect.assertions(2);
84
+ const centerLng = -170;
85
+ const pointX = 1; // x in the left half of the 4-px world
86
+ const terrain = setupMercatorOverflow(centerLng);
87
+ const coordinate = terrain.pointCoordinate(new Point(pointX, 0));
88
+
89
+ expect(coordinate.x).toBeLessThan(0);
90
+ expect(coordinate.x).toBeGreaterThan(-1);
91
+ });
92
+
93
+ test(
94
+ `pointCoordiate should return mercator x greater than 1
95
+ if center.lng is to the left of 180 meridian
96
+ and a given point is to the right of 180`,
97
+ () => {
98
+ expect.assertions(2);
99
+ const centerLng = 170;
100
+ const pointX = 3; // x in the right half of the 4-px world
101
+ const terrain = setupMercatorOverflow(centerLng);
102
+ const coordinate = terrain.pointCoordinate(new Point(pointX, 0));
103
+
104
+ expect(coordinate.x).toBeGreaterThan(1);
105
+ expect(coordinate.x).toBeLessThan(2);
106
+ });
107
+
53
108
  test('Calculate tile minimum and maximum elevation', () => {
54
109
  const tileID = new OverscaledTileID(5, 0, 5, 17, 11);
55
110
  const tile = new Tile(tileID, 256);
@@ -13,7 +13,7 @@ import {Painter} from './painter';
13
13
  import {Texture} from '../render/texture';
14
14
  import type {Framebuffer} from '../gl/framebuffer';
15
15
  import Point from '@mapbox/point-geometry';
16
- import {MercatorCoordinate} from '../geo/mercator_coordinate';
16
+ import {MercatorCoordinate, lngFromMercatorX, mercatorXfromLng} from '../geo/mercator_coordinate';
17
17
  import {TerrainSourceCache} from '../source/terrain_source_cache';
18
18
  import {SourceCache} from '../source/source_cache';
19
19
  import {EXTENT} from '../data/extent';
@@ -341,8 +341,9 @@ export class Terrain {
341
341
  if (!tile) return null;
342
342
  const coordsSize = this._coordsTextureSize;
343
343
  const worldSize = (1 << tile.tileID.canonical.z) * coordsSize;
344
+ const mercatorX = (tile.tileID.canonical.x * coordsSize + x) / worldSize;
344
345
  return new MercatorCoordinate(
345
- (tile.tileID.canonical.x * coordsSize + x) / worldSize,
346
+ this._allowMercatorOverflow(p, mercatorX),
346
347
  (tile.tileID.canonical.y * coordsSize + y) / worldSize,
347
348
  this.getElevation(tile.tileID, x, y, coordsSize)
348
349
  );
@@ -441,4 +442,18 @@ export class Terrain {
441
442
  mercatorY
442
443
  };
443
444
  }
445
+
446
+ _allowMercatorOverflow(p: Point, mercatorX: number): number {
447
+ const inLeftHalf = p.x < (this.painter.width / 2);
448
+ let lng = lngFromMercatorX(mercatorX);
449
+ const centerLng = this.painter.transform.center.lng;
450
+ if (
451
+ (inLeftHalf && Math.sign(lng) > 0 && Math.sign(centerLng) < 0) ||
452
+ (!inLeftHalf && Math.sign(lng) < 0 && Math.sign(centerLng) > 0)
453
+ ) {
454
+ lng = 360 * Math.sign(centerLng) + lng;
455
+ return mercatorXfromLng(lng);
456
+ }
457
+ return mercatorX;
458
+ }
444
459
  }
@@ -0,0 +1,74 @@
1
+ import {Tile} from '../source/tile';
2
+ import {OverscaledTileID} from '../source/tile_id';
3
+ import {updatePatternPositionsInProgram} from './update_pattern_positions_in_program';
4
+ import {FillStyleLayer} from '../style/style_layer/fill_style_layer';
5
+ import type {CrossFaded} from '../style/properties';
6
+ import type {FillLayerSpecification, ResolvedImage} from '@maplibre/maplibre-gl-style-spec';
7
+ import type {ProgramConfiguration} from '../data/program_configuration';
8
+ import type {ImagePosition} from './image_atlas';
9
+ import type {Rect} from './glyph_atlas';
10
+
11
+ interface MockProgramConfiguration extends ProgramConfiguration {
12
+ patternPositions: {
13
+ posFrom: Rect;
14
+ posTo: Rect;
15
+ };
16
+ }
17
+
18
+ function constructMockProgramConfiguration(): MockProgramConfiguration {
19
+ const mockProgramConfiguration: MockProgramConfiguration = {patternPositions: {}} as any;
20
+ mockProgramConfiguration.updatePaintBuffers = jest.fn();
21
+ mockProgramConfiguration.setConstantPatternPositions = (posFrom: ImagePosition, posTo: ImagePosition) => {
22
+ // this does not exist on ProgramConfiguration but we want to test the resulting output
23
+ mockProgramConfiguration.patternPositions = {posFrom: posFrom.paddedRect, posTo: posTo.paddedRect};
24
+ };
25
+
26
+ return mockProgramConfiguration;
27
+ }
28
+
29
+ function constructMockFillStyleLayer(): FillStyleLayer {
30
+ const layerSpec = {
31
+ id: 'mock-layer',
32
+ source: 'empty-source',
33
+ type: 'fill',
34
+ layout: {},
35
+ 'paint': {
36
+ 'fill-pattern': [
37
+ 'step',
38
+ ['zoom'],
39
+ 'zoo_11',
40
+ 4,
41
+ 'volcano_11'
42
+ ]
43
+ }
44
+ } as FillLayerSpecification;
45
+ const layer = new FillStyleLayer(layerSpec);
46
+ return layer;
47
+ }
48
+
49
+ describe('updatePatternPositionsInProgram', () => {
50
+ test('geojson tile', () => {
51
+ const config = constructMockProgramConfiguration();
52
+ const tile = new Tile(new OverscaledTileID(3, 0, 2, 1, 2), undefined);
53
+ tile.imageAtlas = {} as any;
54
+ tile.imageAtlas.patternPositions = {
55
+ 'volcano_11': {paddedRect: {x: 0, y: 0, w: 0, h: 0}, version: 0, tl: [0, 0], pixelRatio: 1, br: [0, 0], tlbr: [0, 0, 0, 0], displaySize: [0, 0], stretchX: [], stretchY: [], content: [0, 0, 0, 0]},
56
+ };
57
+ const crossFadeResolveImage: CrossFaded<ResolvedImage> = {
58
+ from: {name: 'zoo_11', available: false, toString: () => 'zoo_11'},
59
+ to: {name: 'volcano_11', available: false, toString: () => 'volcano_11'}
60
+ };
61
+ updatePatternPositionsInProgram(
62
+ config,
63
+ 'fill-pattern',
64
+ crossFadeResolveImage,
65
+ tile,
66
+ constructMockFillStyleLayer()
67
+ );
68
+ // we added this property to just see what the update looks like
69
+ expect(config.patternPositions).toEqual({
70
+ posFrom: {x: 0, y: 0, w: 0, h: 0},
71
+ posTo: {x: 0, y: 0, w: 0, h: 0}
72
+ });
73
+ });
74
+ });
@@ -33,6 +33,10 @@ export function updatePatternPositionsInProgram(
33
33
  let posTo = patternPositions[constantPattern.to.toString()];
34
34
  let posFrom = patternPositions[constantPattern.from.toString()];
35
35
 
36
+ // https://github.com/maplibre/maplibre-gl-js/issues/3377
37
+ if (!posTo && posFrom) posTo = posFrom;
38
+ if (!posFrom && posTo) posFrom = posTo;
39
+
36
40
  // try again in case patternPositions has been updated by worker
37
41
  if (!posTo || !posFrom) {
38
42
  const transitioned = layer.getPaintProperty(propertyName) as string;
@@ -209,7 +209,7 @@ describe('Map', () => {
209
209
  await map.once('idle');
210
210
  idleTriggered = true;
211
211
  map.zoomTo(0.5, {duration: 100});
212
- spy.mockReset();
212
+ spy.mockRestore();
213
213
  });
214
214
  });
215
215
 
package/src/ui/map.ts CHANGED
@@ -103,7 +103,7 @@ export type MapOptions = {
103
103
  */
104
104
  attributionControl?: boolean;
105
105
  /**
106
- * Attribuition text to show in an {@link AttributionControl}. Only applicable if `options.attributionControl` is `true`.
106
+ * Attribution text to show in an {@link AttributionControl}. Only applicable if `options.attributionControl` is `true`.
107
107
  */
108
108
  customAttribution?: string | Array<string>;
109
109
  /**
@@ -45,7 +45,7 @@ export function setupFetchMock(): FetchMock {
45
45
 
46
46
  global.AbortController = AbortControllerMock;
47
47
  global.Request = RequestMock as unknown as typeof Request;
48
- global.fetch = fetchMock;
48
+ global.fetch = fetchMock as any;
49
49
 
50
50
  return fetchMock;
51
51
  }