maplibre-gl 2.3.1-pre.2 → 2.4.0
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/dist/maplibre-gl-csp-worker.js +1 -1
- package/dist/maplibre-gl-csp.js +1 -1
- package/dist/maplibre-gl-dev.js +60 -16
- package/dist/maplibre-gl.d.ts +12 -0
- package/dist/maplibre-gl.js +3 -3
- package/package.json +11 -10
- package/src/render/draw_debug.ts +1 -1
- package/src/render/draw_fill.ts +9 -1
- package/src/render/draw_fill_extrusion.ts +8 -1
- package/src/render/draw_heatmap.ts +5 -3
- package/src/render/draw_hillshade.ts +17 -2
- package/src/render/program/line_program.ts +1 -1
- package/src/style/style.ts +1 -0
- package/src/style/style_layer/symbol_style_layer.ts +4 -5
- package/src/style-spec/CHANGELOG.md +2 -2
- package/src/ui/camera.test.ts +64 -1
- package/src/ui/camera.ts +36 -0
- package/src/ui/control/attribution_control.test.ts +62 -0
- package/src/ui/control/attribution_control.ts +4 -2
- package/src/ui/control/terrain_control.test.ts +60 -0
- package/src/ui/handler/map_event.test.ts +65 -1
- package/src/ui/handler/map_event.ts +4 -1
- package/src/ui/map.test.ts +105 -0
- package/src/ui/map.ts +8 -1
|
@@ -104,6 +104,7 @@ export class MapEventHandler implements Handler {
|
|
|
104
104
|
export class BlockableMapEventHandler {
|
|
105
105
|
_map: Map;
|
|
106
106
|
_delayContextMenu: boolean;
|
|
107
|
+
_ignoreContextMenu: boolean;
|
|
107
108
|
_contextMenuEvent: MouseEvent;
|
|
108
109
|
|
|
109
110
|
constructor(map: Map) {
|
|
@@ -112,6 +113,7 @@ export class BlockableMapEventHandler {
|
|
|
112
113
|
|
|
113
114
|
reset() {
|
|
114
115
|
this._delayContextMenu = false;
|
|
116
|
+
this._ignoreContextMenu = true;
|
|
115
117
|
delete this._contextMenuEvent;
|
|
116
118
|
}
|
|
117
119
|
|
|
@@ -122,6 +124,7 @@ export class BlockableMapEventHandler {
|
|
|
122
124
|
|
|
123
125
|
mousedown() {
|
|
124
126
|
this._delayContextMenu = true;
|
|
127
|
+
this._ignoreContextMenu = false;
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
mouseup() {
|
|
@@ -135,7 +138,7 @@ export class BlockableMapEventHandler {
|
|
|
135
138
|
if (this._delayContextMenu) {
|
|
136
139
|
// Mac: contextmenu fired on mousedown; we save it until mouseup for consistency's sake
|
|
137
140
|
this._contextMenuEvent = e;
|
|
138
|
-
} else {
|
|
141
|
+
} else if (!this._ignoreContextMenu) {
|
|
139
142
|
// Windows: contextmenu fired on mouseup, so fire event now
|
|
140
143
|
this._map.fire(new MapMouseEvent(e.type, this._map, e));
|
|
141
144
|
}
|
package/src/ui/map.test.ts
CHANGED
|
@@ -13,6 +13,9 @@ import {LngLatBoundsLike} from '../geo/lng_lat_bounds';
|
|
|
13
13
|
import {IControl} from './control/control';
|
|
14
14
|
import EvaluationParameters from '../style/evaluation_parameters';
|
|
15
15
|
import {fakeServer, FakeServer} from 'nise';
|
|
16
|
+
import {CameraOptions} from './camera';
|
|
17
|
+
import Terrain, {} from '../render/terrain';
|
|
18
|
+
import {mercatorZfromAltitude} from '../geo/mercator_coordinate';
|
|
16
19
|
|
|
17
20
|
function createStyleSource() {
|
|
18
21
|
return {
|
|
@@ -2132,6 +2135,108 @@ describe('Map', () => {
|
|
|
2132
2135
|
map.fire(new Event('dataabort'));
|
|
2133
2136
|
});
|
|
2134
2137
|
|
|
2138
|
+
describe('#calculateCameraOptionsFromTo', () => {
|
|
2139
|
+
// Choose initial zoom to avoid center being constrained by mercator latitude limits.
|
|
2140
|
+
test('pitch 90 with terrain', () => {
|
|
2141
|
+
const map = createMap();
|
|
2142
|
+
|
|
2143
|
+
const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 111200);
|
|
2144
|
+
|
|
2145
|
+
const terrainStub = {} as Terrain;
|
|
2146
|
+
terrainStub.getElevation = mockedGetElevation;
|
|
2147
|
+
map.style.terrain = terrainStub;
|
|
2148
|
+
|
|
2149
|
+
// distance between lng x and lng x+1 is 111.2km at same lat
|
|
2150
|
+
// altitude same as center elevation => 90° pitch
|
|
2151
|
+
const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(1, 0), 111200, new LngLat(0, 0));
|
|
2152
|
+
expect(cameraOptions).toBeDefined();
|
|
2153
|
+
expect(cameraOptions.pitch).toBeCloseTo(90);
|
|
2154
|
+
expect(mockedGetElevation.mock.calls).toHaveLength(1);
|
|
2155
|
+
});
|
|
2156
|
+
|
|
2157
|
+
test('pitch 153.435 with terrain', () => {
|
|
2158
|
+
const map = createMap();
|
|
2159
|
+
|
|
2160
|
+
const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 111200 * 3);
|
|
2161
|
+
|
|
2162
|
+
const terrainStub = {} as Terrain;
|
|
2163
|
+
terrainStub.getElevation = mockedGetElevation;
|
|
2164
|
+
map.style.terrain = terrainStub;
|
|
2165
|
+
// distance between lng x and lng x+1 is 111.2km at same lat
|
|
2166
|
+
// (elevation difference of cam and center) / 2 = grounddistance =>
|
|
2167
|
+
// acos(111.2 / sqrt(111.2² + (111.2 * 2)²)) = acos(1/sqrt(5)) => 63.435 + 90 = 153.435
|
|
2168
|
+
const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(1, 0), 111200, new LngLat(0, 0));
|
|
2169
|
+
expect(cameraOptions).toBeDefined();
|
|
2170
|
+
expect(cameraOptions.pitch).toBeCloseTo(153.435);
|
|
2171
|
+
expect(mockedGetElevation.mock.calls).toHaveLength(1);
|
|
2172
|
+
});
|
|
2173
|
+
|
|
2174
|
+
test('pitch 63 with terrain', () => {
|
|
2175
|
+
const map = createMap();
|
|
2176
|
+
|
|
2177
|
+
const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 111200 / 2);
|
|
2178
|
+
|
|
2179
|
+
const terrainStub = {} as Terrain;
|
|
2180
|
+
terrainStub.getElevation = mockedGetElevation;
|
|
2181
|
+
map.style.terrain = terrainStub;
|
|
2182
|
+
|
|
2183
|
+
// distance between lng x and lng x+1 is 111.2km at same lat
|
|
2184
|
+
// (elevation difference of cam and center) * 2 = grounddistance =>
|
|
2185
|
+
// acos(111.2 / sqrt(111.2² + (111.2 * 0.5)²)) = acos(1/sqrt(1.25)) => 90 (looking down) - 26.565 = 63.435
|
|
2186
|
+
const cameraOptions: CameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 111200, new LngLat(1, 0));
|
|
2187
|
+
expect(cameraOptions).toBeDefined();
|
|
2188
|
+
expect(cameraOptions.pitch).toBeCloseTo(63.435);
|
|
2189
|
+
expect(mockedGetElevation.mock.calls).toHaveLength(1);
|
|
2190
|
+
});
|
|
2191
|
+
|
|
2192
|
+
test('zoom distance 1000', () => {
|
|
2193
|
+
const map = createMap();
|
|
2194
|
+
|
|
2195
|
+
const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 1000);
|
|
2196
|
+
|
|
2197
|
+
const terrainStub = {} as Terrain;
|
|
2198
|
+
terrainStub.getElevation = mockedGetElevation;
|
|
2199
|
+
map.style.terrain = terrainStub;
|
|
2200
|
+
|
|
2201
|
+
const expectedZoom = Math.log2(map.transform.cameraToCenterDistance / mercatorZfromAltitude(1000, 0) / map.transform.tileSize);
|
|
2202
|
+
const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(0, 0));
|
|
2203
|
+
|
|
2204
|
+
expect(cameraOptions).toBeDefined();
|
|
2205
|
+
expect(cameraOptions.zoom).toBeCloseTo(expectedZoom);
|
|
2206
|
+
expect(mockedGetElevation.mock.calls).toHaveLength(1);
|
|
2207
|
+
});
|
|
2208
|
+
|
|
2209
|
+
test('don\'t call getElevation when altitude supplied', () => {
|
|
2210
|
+
const map = createMap();
|
|
2211
|
+
|
|
2212
|
+
const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 0);
|
|
2213
|
+
|
|
2214
|
+
const terrainStub = {} as Terrain;
|
|
2215
|
+
terrainStub.getElevation = mockedGetElevation;
|
|
2216
|
+
map.style.terrain = terrainStub;
|
|
2217
|
+
|
|
2218
|
+
const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(0, 0), 1000);
|
|
2219
|
+
|
|
2220
|
+
expect(cameraOptions).toBeDefined();
|
|
2221
|
+
expect(mockedGetElevation.mock.calls).toHaveLength(0);
|
|
2222
|
+
});
|
|
2223
|
+
|
|
2224
|
+
test('don\'t call getElevation when altitude 0 supplied', () => {
|
|
2225
|
+
const map = createMap();
|
|
2226
|
+
|
|
2227
|
+
const mockedGetElevation = jest.fn((_tileID: OverscaledTileID, _x: number, _y: number, _extent?: number) => 0);
|
|
2228
|
+
|
|
2229
|
+
const terrainStub = {} as Terrain;
|
|
2230
|
+
terrainStub.getElevation = mockedGetElevation;
|
|
2231
|
+
map.style.terrain = terrainStub;
|
|
2232
|
+
|
|
2233
|
+
const cameraOptions = map.calculateCameraOptionsFromTo(new LngLat(0, 0), 0, new LngLat(1, 0), 0);
|
|
2234
|
+
|
|
2235
|
+
expect(cameraOptions).toBeDefined();
|
|
2236
|
+
expect(mockedGetElevation.mock.calls).toHaveLength(0);
|
|
2237
|
+
});
|
|
2238
|
+
});
|
|
2239
|
+
|
|
2135
2240
|
});
|
|
2136
2241
|
|
|
2137
2242
|
function createStyle() {
|
package/src/ui/map.ts
CHANGED
|
@@ -10,7 +10,7 @@ import Painter from '../render/painter';
|
|
|
10
10
|
import Transform from '../geo/transform';
|
|
11
11
|
import Hash from './hash';
|
|
12
12
|
import HandlerManager from './handler_manager';
|
|
13
|
-
import Camera from './camera';
|
|
13
|
+
import Camera, {CameraOptions} from './camera';
|
|
14
14
|
import LngLat from '../geo/lng_lat';
|
|
15
15
|
import LngLatBounds from '../geo/lng_lat_bounds';
|
|
16
16
|
import Point from '@mapbox/point-geometry';
|
|
@@ -603,6 +603,13 @@ class Map extends Camera {
|
|
|
603
603
|
return this._controls.indexOf(control) > -1;
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
+
calculateCameraOptionsFromTo(from: LngLat, altitudeFrom: number, to: LngLat, altitudeTo?: number) : CameraOptions {
|
|
607
|
+
if (altitudeTo == null && this.style.terrain) {
|
|
608
|
+
altitudeTo = this.transform.getElevation(to, this.style.terrain);
|
|
609
|
+
}
|
|
610
|
+
return super.calculateCameraOptionsFromTo(from, altitudeFrom, to, altitudeTo);
|
|
611
|
+
}
|
|
612
|
+
|
|
606
613
|
/**
|
|
607
614
|
* Resizes the map according to the dimensions of its
|
|
608
615
|
* `container` element.
|