@deck.gl/arcgis 9.3.4 → 9.3.6
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/commons.d.ts +2 -4
- package/dist/commons.d.ts.map +1 -1
- package/dist/commons.js +62 -22
- package/dist/commons.js.map +1 -1
- package/dist/deck-renderer.d.ts +6 -3
- package/dist/deck-renderer.d.ts.map +1 -1
- package/dist/deck-renderer.js +186 -35
- package/dist/deck-renderer.js.map +1 -1
- package/dist/dist.dev.js +7821 -98
- package/dist/index.cjs +2823 -68
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/load-modules.js +7 -7
- package/dist/load-modules.js.map +1 -1
- package/dist.min.js +6 -4
- package/package.json +2 -2
- package/src/commons.ts +73 -24
- package/src/deck-renderer.ts +230 -37
- package/src/index.ts +2 -2
- package/src/load-modules.ts +7 -7
package/dist/index.cjs
CHANGED
|
@@ -17,15 +17,15 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
}
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
|
-
var __toESM = (
|
|
20
|
+
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
21
21
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
22
|
// file that has been converted to a CommonJS file using a Babel-
|
|
23
23
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
24
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !
|
|
26
|
-
|
|
25
|
+
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
|
|
26
|
+
mod2
|
|
27
27
|
));
|
|
28
|
-
var __toCommonJS = (
|
|
28
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
29
29
|
|
|
30
30
|
// dist/index.js
|
|
31
31
|
var dist_exports = {};
|
|
@@ -171,7 +171,9 @@ out vec4 fragColor;
|
|
|
171
171
|
|
|
172
172
|
void main(void) {
|
|
173
173
|
vec4 imageColor = texture(deckglTexture, v_texcoord);
|
|
174
|
-
|
|
174
|
+
// FBO stores premultiplied RGBA (rgb already multiplied by alpha).
|
|
175
|
+
// The composite blend (ONE, ONE_MINUS_SRC_ALPHA) handles premultiplied
|
|
176
|
+
// input correctly; multiplying again here would darken overlays.
|
|
175
177
|
fragColor = imageColor;
|
|
176
178
|
}
|
|
177
179
|
`,
|
|
@@ -179,8 +181,8 @@ void main(void) {
|
|
|
179
181
|
deckglTexture: texture
|
|
180
182
|
},
|
|
181
183
|
parameters: {
|
|
182
|
-
depthWriteEnabled:
|
|
183
|
-
depthCompare: "
|
|
184
|
+
depthWriteEnabled: false,
|
|
185
|
+
depthCompare: "always",
|
|
184
186
|
blendColorSrcFactor: "one",
|
|
185
187
|
blendColorDstFactor: "one-minus-src-alpha",
|
|
186
188
|
blendAlphaSrcFactor: "one",
|
|
@@ -209,6 +211,8 @@ void main(void) {
|
|
|
209
211
|
_framebuffer: fbo,
|
|
210
212
|
_customRender: (redrawReason) => {
|
|
211
213
|
if (redrawReason === "arcgis") {
|
|
214
|
+
const glCtx = device.gl;
|
|
215
|
+
glCtx.blendFuncSeparate(glCtx.ONE, glCtx.ONE_MINUS_SRC_ALPHA, glCtx.ONE, glCtx.ONE_MINUS_SRC_ALPHA);
|
|
212
216
|
deckInstance._drawLayers(redrawReason);
|
|
213
217
|
} else {
|
|
214
218
|
this.redraw();
|
|
@@ -218,33 +222,48 @@ void main(void) {
|
|
|
218
222
|
return { deck: deckInstance, texture, fbo, model };
|
|
219
223
|
}
|
|
220
224
|
function render(resources, viewport) {
|
|
221
|
-
var _a, _b;
|
|
222
225
|
const { model, deck, fbo } = resources;
|
|
223
226
|
const device = model.device;
|
|
224
227
|
if (device instanceof import_webgl.WebGLDevice) {
|
|
225
|
-
const
|
|
228
|
+
const rawScreenFbo = device.getParametersWebGL(36006);
|
|
229
|
+
const { width, height, views, viewState, ...defaultViewState } = viewport;
|
|
226
230
|
const dpr = window.devicePixelRatio;
|
|
227
231
|
const pixelWidth = Math.round(width * dpr);
|
|
228
232
|
const pixelHeight = Math.round(height * dpr);
|
|
229
|
-
const externalFbo = device.getParametersWebGL(36006);
|
|
230
|
-
let screenFbo = null;
|
|
231
|
-
if (externalFbo) {
|
|
232
|
-
if (((_a = resources._externalFramebuffer) == null ? void 0 : _a.handle) !== externalFbo) {
|
|
233
|
-
(_b = resources._externalFramebuffer) == null ? void 0 : _b.wrapper.destroy();
|
|
234
|
-
const wrapper = device.createFramebuffer({
|
|
235
|
-
handle: externalFbo,
|
|
236
|
-
width: pixelWidth,
|
|
237
|
-
height: pixelHeight
|
|
238
|
-
});
|
|
239
|
-
resources._externalFramebuffer = { handle: externalFbo, wrapper };
|
|
240
|
-
}
|
|
241
|
-
screenFbo = resources._externalFramebuffer.wrapper;
|
|
242
|
-
}
|
|
243
233
|
fbo.resize({ width: pixelWidth, height: pixelHeight });
|
|
244
|
-
|
|
234
|
+
const currentTexture = fbo.colorAttachments[0].texture ?? fbo.colorAttachments[0];
|
|
235
|
+
if (currentTexture !== resources.texture) {
|
|
236
|
+
resources.texture = currentTexture;
|
|
237
|
+
model.setBindings({ deckglTexture: currentTexture });
|
|
238
|
+
}
|
|
239
|
+
const deckProps = {
|
|
240
|
+
width,
|
|
241
|
+
height,
|
|
242
|
+
viewState: viewState || defaultViewState
|
|
243
|
+
};
|
|
244
|
+
if (views) {
|
|
245
|
+
deckProps.views = views;
|
|
246
|
+
}
|
|
247
|
+
deck.setProps(deckProps);
|
|
245
248
|
deck.redraw("arcgis");
|
|
249
|
+
const { gl } = device;
|
|
250
|
+
if (rawScreenFbo) {
|
|
251
|
+
gl.bindFramebuffer(36160, rawScreenFbo);
|
|
252
|
+
gl.drawBuffers([36064]);
|
|
253
|
+
} else {
|
|
254
|
+
gl.drawBuffers([1029]);
|
|
255
|
+
}
|
|
256
|
+
gl.enable(3042);
|
|
257
|
+
gl.blendFuncSeparate(1, 771, 1, 771);
|
|
258
|
+
gl.blendEquationSeparate(32774, 32774);
|
|
259
|
+
const screenFboAdapter = {
|
|
260
|
+
handle: rawScreenFbo,
|
|
261
|
+
width: pixelWidth,
|
|
262
|
+
height: pixelHeight,
|
|
263
|
+
colorAttachments: [null]
|
|
264
|
+
};
|
|
246
265
|
const textureToScreenPass = device.beginRenderPass({
|
|
247
|
-
framebuffer:
|
|
266
|
+
framebuffer: screenFboAdapter,
|
|
248
267
|
parameters: { viewport: [0, 0, pixelWidth, pixelHeight] },
|
|
249
268
|
clearColor: false,
|
|
250
269
|
clearDepth: false
|
|
@@ -257,12 +276,10 @@ function render(resources, viewport) {
|
|
|
257
276
|
}
|
|
258
277
|
}
|
|
259
278
|
function finalizeResources(resources) {
|
|
260
|
-
var _a;
|
|
261
279
|
resources.deck.finalize();
|
|
262
280
|
resources.model.destroy();
|
|
263
281
|
resources.fbo.destroy();
|
|
264
282
|
resources.texture.destroy();
|
|
265
|
-
(_a = resources._externalFramebuffer) == null ? void 0 : _a.wrapper.destroy();
|
|
266
283
|
}
|
|
267
284
|
|
|
268
285
|
// dist/deck-layer-view-2d.js
|
|
@@ -318,55 +335,2793 @@ function createDeckLayerView2D(BaseLayerViewGL2D2) {
|
|
|
318
335
|
});
|
|
319
336
|
}
|
|
320
337
|
|
|
338
|
+
// ../core/src/utils/positions.ts
|
|
339
|
+
var NUMBER_REGEX = /^(?:\d+\.?\d*|\.\d+)$/;
|
|
340
|
+
function parsePosition(value) {
|
|
341
|
+
switch (typeof value) {
|
|
342
|
+
case "number":
|
|
343
|
+
if (!Number.isFinite(value)) {
|
|
344
|
+
throw new Error(`Could not parse position string ${value}`);
|
|
345
|
+
}
|
|
346
|
+
return { type: "literal", value };
|
|
347
|
+
case "string":
|
|
348
|
+
try {
|
|
349
|
+
const tokens = tokenize(value);
|
|
350
|
+
const parser = new LayoutExpressionParser(tokens);
|
|
351
|
+
return parser.parseExpression();
|
|
352
|
+
} catch (error) {
|
|
353
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
354
|
+
throw new Error(`Could not parse position string ${value}: ${reason}`);
|
|
355
|
+
}
|
|
356
|
+
default:
|
|
357
|
+
throw new Error(`Could not parse position string ${value}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function evaluateLayoutExpression(expression, extent) {
|
|
361
|
+
switch (expression.type) {
|
|
362
|
+
case "literal":
|
|
363
|
+
return expression.value;
|
|
364
|
+
case "percentage":
|
|
365
|
+
return Math.round(expression.value * extent);
|
|
366
|
+
case "binary":
|
|
367
|
+
const left = evaluateLayoutExpression(expression.left, extent);
|
|
368
|
+
const right = evaluateLayoutExpression(expression.right, extent);
|
|
369
|
+
return expression.operator === "+" ? left + right : left - right;
|
|
370
|
+
default:
|
|
371
|
+
throw new Error("Unknown layout expression type");
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
function getPosition(expression, extent) {
|
|
375
|
+
return evaluateLayoutExpression(expression, extent);
|
|
376
|
+
}
|
|
377
|
+
function tokenize(input) {
|
|
378
|
+
const tokens = [];
|
|
379
|
+
let index = 0;
|
|
380
|
+
while (index < input.length) {
|
|
381
|
+
const char = input[index];
|
|
382
|
+
if (/\s/.test(char)) {
|
|
383
|
+
index++;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
if (char === "+" || char === "-" || char === "(" || char === ")" || char === "%") {
|
|
387
|
+
tokens.push({ type: "symbol", value: char });
|
|
388
|
+
index++;
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (isDigit(char) || char === ".") {
|
|
392
|
+
const start = index;
|
|
393
|
+
let hasDecimal = char === ".";
|
|
394
|
+
index++;
|
|
395
|
+
while (index < input.length) {
|
|
396
|
+
const next = input[index];
|
|
397
|
+
if (isDigit(next)) {
|
|
398
|
+
index++;
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
if (next === "." && !hasDecimal) {
|
|
402
|
+
hasDecimal = true;
|
|
403
|
+
index++;
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
const numberString = input.slice(start, index);
|
|
409
|
+
if (!NUMBER_REGEX.test(numberString)) {
|
|
410
|
+
throw new Error("Invalid number token");
|
|
411
|
+
}
|
|
412
|
+
tokens.push({ type: "number", value: parseFloat(numberString) });
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
if (isAlpha(char)) {
|
|
416
|
+
const start = index;
|
|
417
|
+
while (index < input.length && isAlpha(input[index])) {
|
|
418
|
+
index++;
|
|
419
|
+
}
|
|
420
|
+
const word = input.slice(start, index).toLowerCase();
|
|
421
|
+
tokens.push({ type: "word", value: word });
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
throw new Error("Invalid token in position string");
|
|
425
|
+
}
|
|
426
|
+
return tokens;
|
|
427
|
+
}
|
|
428
|
+
var LayoutExpressionParser = class {
|
|
429
|
+
constructor(tokens) {
|
|
430
|
+
this.index = 0;
|
|
431
|
+
this.tokens = tokens;
|
|
432
|
+
}
|
|
433
|
+
parseExpression() {
|
|
434
|
+
const expression = this.parseBinaryExpression();
|
|
435
|
+
if (this.index < this.tokens.length) {
|
|
436
|
+
throw new Error("Unexpected token at end of expression");
|
|
437
|
+
}
|
|
438
|
+
return expression;
|
|
439
|
+
}
|
|
440
|
+
parseBinaryExpression() {
|
|
441
|
+
let expression = this.parseFactor();
|
|
442
|
+
let token = this.peek();
|
|
443
|
+
while (isAddSubSymbol(token)) {
|
|
444
|
+
this.index++;
|
|
445
|
+
const right = this.parseFactor();
|
|
446
|
+
expression = { type: "binary", operator: token.value, left: expression, right };
|
|
447
|
+
token = this.peek();
|
|
448
|
+
}
|
|
449
|
+
return expression;
|
|
450
|
+
}
|
|
451
|
+
parseFactor() {
|
|
452
|
+
const token = this.peek();
|
|
453
|
+
if (!token) {
|
|
454
|
+
throw new Error("Unexpected end of expression");
|
|
455
|
+
}
|
|
456
|
+
if (token.type === "symbol" && token.value === "+") {
|
|
457
|
+
this.index++;
|
|
458
|
+
return this.parseFactor();
|
|
459
|
+
}
|
|
460
|
+
if (token.type === "symbol" && token.value === "-") {
|
|
461
|
+
this.index++;
|
|
462
|
+
const factor = this.parseFactor();
|
|
463
|
+
return { type: "binary", operator: "-", left: { type: "literal", value: 0 }, right: factor };
|
|
464
|
+
}
|
|
465
|
+
if (token.type === "symbol" && token.value === "(") {
|
|
466
|
+
this.index++;
|
|
467
|
+
const expression = this.parseBinaryExpression();
|
|
468
|
+
if (!this.consumeSymbol(")")) {
|
|
469
|
+
throw new Error("Missing closing parenthesis");
|
|
470
|
+
}
|
|
471
|
+
return expression;
|
|
472
|
+
}
|
|
473
|
+
if (token.type === "word" && token.value === "calc") {
|
|
474
|
+
this.index++;
|
|
475
|
+
if (!this.consumeSymbol("(")) {
|
|
476
|
+
throw new Error("Missing opening parenthesis after calc");
|
|
477
|
+
}
|
|
478
|
+
const expression = this.parseBinaryExpression();
|
|
479
|
+
if (!this.consumeSymbol(")")) {
|
|
480
|
+
throw new Error("Missing closing parenthesis");
|
|
481
|
+
}
|
|
482
|
+
return expression;
|
|
483
|
+
}
|
|
484
|
+
if (token.type === "number") {
|
|
485
|
+
this.index++;
|
|
486
|
+
const numberValue = token.value;
|
|
487
|
+
const nextToken = this.peek();
|
|
488
|
+
if (nextToken && nextToken.type === "symbol" && nextToken.value === "%") {
|
|
489
|
+
this.index++;
|
|
490
|
+
return { type: "percentage", value: numberValue / 100 };
|
|
491
|
+
}
|
|
492
|
+
if (nextToken && nextToken.type === "word" && nextToken.value === "px") {
|
|
493
|
+
this.index++;
|
|
494
|
+
return { type: "literal", value: numberValue };
|
|
495
|
+
}
|
|
496
|
+
return { type: "literal", value: numberValue };
|
|
497
|
+
}
|
|
498
|
+
throw new Error("Unexpected token in expression");
|
|
499
|
+
}
|
|
500
|
+
consumeSymbol(value) {
|
|
501
|
+
const token = this.peek();
|
|
502
|
+
if (token && token.type === "symbol" && token.value === value) {
|
|
503
|
+
this.index++;
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
508
|
+
peek() {
|
|
509
|
+
return this.tokens[this.index] || null;
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
function isDigit(char) {
|
|
513
|
+
return char >= "0" && char <= "9";
|
|
514
|
+
}
|
|
515
|
+
function isAlpha(char) {
|
|
516
|
+
return char >= "a" && char <= "z" || char >= "A" && char <= "Z";
|
|
517
|
+
}
|
|
518
|
+
function isAddSubSymbol(token) {
|
|
519
|
+
return Boolean(token && token.type === "symbol" && (token.value === "+" || token.value === "-"));
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// ../core/src/utils/deep-equal.ts
|
|
523
|
+
function deepEqual(a, b, depth) {
|
|
524
|
+
if (a === b) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
if (!depth || !a || !b) {
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
if (Array.isArray(a)) {
|
|
531
|
+
if (!Array.isArray(b) || a.length !== b.length) {
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
for (let i = 0; i < a.length; i++) {
|
|
535
|
+
if (!deepEqual(a[i], b[i], depth - 1)) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
if (Array.isArray(b)) {
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
if (typeof a === "object" && typeof b === "object") {
|
|
545
|
+
const aKeys = Object.keys(a);
|
|
546
|
+
const bKeys = Object.keys(b);
|
|
547
|
+
if (aKeys.length !== bKeys.length) {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
for (const key of aKeys) {
|
|
551
|
+
if (!b.hasOwnProperty(key)) {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
if (!deepEqual(a[key], b[key], depth - 1)) {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// ../core/src/utils/deep-merge.ts
|
|
564
|
+
function deepMergeViewState(a, b) {
|
|
565
|
+
const result = { ...a };
|
|
566
|
+
for (const key in b) {
|
|
567
|
+
if (key === "id")
|
|
568
|
+
continue;
|
|
569
|
+
if (Array.isArray(result[key]) && Array.isArray(b[key])) {
|
|
570
|
+
result[key] = mergeNumericArray(result[key], b[key]);
|
|
571
|
+
} else {
|
|
572
|
+
result[key] = b[key];
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return result;
|
|
576
|
+
}
|
|
577
|
+
function mergeNumericArray(target, source) {
|
|
578
|
+
target = target.slice();
|
|
579
|
+
for (let i = 0; i < source.length; i++) {
|
|
580
|
+
const v = source[i];
|
|
581
|
+
if (Number.isFinite(v)) {
|
|
582
|
+
target[i] = v;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return target;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// ../core/src/views/view.ts
|
|
589
|
+
var View = class {
|
|
590
|
+
constructor(props) {
|
|
591
|
+
const { id, x = 0, y = 0, width = "100%", height = "100%", padding = null } = props;
|
|
592
|
+
this.id = id || this.constructor.displayName || "view";
|
|
593
|
+
this.props = { ...props, id: this.id };
|
|
594
|
+
this._x = parsePosition(x);
|
|
595
|
+
this._y = parsePosition(y);
|
|
596
|
+
this._width = parsePosition(width);
|
|
597
|
+
this._height = parsePosition(height);
|
|
598
|
+
this._padding = padding && {
|
|
599
|
+
left: parsePosition(padding.left || 0),
|
|
600
|
+
right: parsePosition(padding.right || 0),
|
|
601
|
+
top: parsePosition(padding.top || 0),
|
|
602
|
+
bottom: parsePosition(padding.bottom || 0)
|
|
603
|
+
};
|
|
604
|
+
this.equals = this.equals.bind(this);
|
|
605
|
+
Object.seal(this);
|
|
606
|
+
}
|
|
607
|
+
equals(view) {
|
|
608
|
+
if (this === view) {
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
return this.constructor === view.constructor && deepEqual(this.props, view.props, 2);
|
|
612
|
+
}
|
|
613
|
+
/** Clone this view with modified props */
|
|
614
|
+
clone(newProps) {
|
|
615
|
+
const ViewConstructor = this.constructor;
|
|
616
|
+
return new ViewConstructor({ ...this.props, ...newProps });
|
|
617
|
+
}
|
|
618
|
+
/** Make viewport from canvas dimensions and view state */
|
|
619
|
+
makeViewport({ width, height, viewState }) {
|
|
620
|
+
viewState = this.filterViewState(viewState);
|
|
621
|
+
const viewportDimensions = this.getDimensions({ width, height });
|
|
622
|
+
if (!viewportDimensions.height || !viewportDimensions.width) {
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
const ViewportType = this.getViewportType(viewState);
|
|
626
|
+
return new ViewportType({ ...viewState, ...this.props, ...viewportDimensions });
|
|
627
|
+
}
|
|
628
|
+
getViewStateId() {
|
|
629
|
+
const { viewState } = this.props;
|
|
630
|
+
if (typeof viewState === "string") {
|
|
631
|
+
return viewState;
|
|
632
|
+
}
|
|
633
|
+
return (viewState == null ? void 0 : viewState.id) || this.id;
|
|
634
|
+
}
|
|
635
|
+
// Allows view to override (or completely define) viewState
|
|
636
|
+
filterViewState(viewState) {
|
|
637
|
+
if (this.props.viewState && typeof this.props.viewState === "object") {
|
|
638
|
+
if (!this.props.viewState.id) {
|
|
639
|
+
return this.props.viewState;
|
|
640
|
+
}
|
|
641
|
+
return deepMergeViewState(viewState, this.props.viewState);
|
|
642
|
+
}
|
|
643
|
+
return viewState;
|
|
644
|
+
}
|
|
645
|
+
/** Resolve the dimensions of the view from overall canvas dimensions */
|
|
646
|
+
getDimensions({ width, height }) {
|
|
647
|
+
const dimensions = {
|
|
648
|
+
x: getPosition(this._x, width),
|
|
649
|
+
y: getPosition(this._y, height),
|
|
650
|
+
width: getPosition(this._width, width),
|
|
651
|
+
height: getPosition(this._height, height)
|
|
652
|
+
};
|
|
653
|
+
if (this._padding) {
|
|
654
|
+
dimensions.padding = {
|
|
655
|
+
left: getPosition(this._padding.left, width),
|
|
656
|
+
top: getPosition(this._padding.top, height),
|
|
657
|
+
right: getPosition(this._padding.right, width),
|
|
658
|
+
bottom: getPosition(this._padding.bottom, height)
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
return dimensions;
|
|
662
|
+
}
|
|
663
|
+
// Used by sub classes to resolve controller props
|
|
664
|
+
get controller() {
|
|
665
|
+
const opts = this.props.controller;
|
|
666
|
+
if (!opts) {
|
|
667
|
+
return null;
|
|
668
|
+
}
|
|
669
|
+
if (opts === true) {
|
|
670
|
+
return { type: this.ControllerType };
|
|
671
|
+
}
|
|
672
|
+
if (typeof opts === "function") {
|
|
673
|
+
return { type: opts };
|
|
674
|
+
}
|
|
675
|
+
return { type: this.ControllerType, ...opts };
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
// ../core/src/utils/log.ts
|
|
680
|
+
var import_log = require("@probe.gl/log");
|
|
681
|
+
var defaultLogger = new import_log.Log({ id: "deck" });
|
|
682
|
+
var log_default = defaultLogger;
|
|
683
|
+
|
|
684
|
+
// ../core/src/utils/math-utils.ts
|
|
685
|
+
var import_core2 = require("@math.gl/core");
|
|
686
|
+
function createMat4() {
|
|
687
|
+
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
688
|
+
}
|
|
689
|
+
function mod(value, divisor) {
|
|
690
|
+
const modulus = value % divisor;
|
|
691
|
+
return modulus < 0 ? divisor + modulus : modulus;
|
|
692
|
+
}
|
|
693
|
+
function getCameraPosition(viewMatrixInverse) {
|
|
694
|
+
return [viewMatrixInverse[12], viewMatrixInverse[13], viewMatrixInverse[14]];
|
|
695
|
+
}
|
|
696
|
+
function getFrustumPlanes(viewProjectionMatrix) {
|
|
697
|
+
return {
|
|
698
|
+
left: getFrustumPlane(
|
|
699
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[0],
|
|
700
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[4],
|
|
701
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[8],
|
|
702
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[12]
|
|
703
|
+
),
|
|
704
|
+
right: getFrustumPlane(
|
|
705
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[0],
|
|
706
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[4],
|
|
707
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[8],
|
|
708
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[12]
|
|
709
|
+
),
|
|
710
|
+
bottom: getFrustumPlane(
|
|
711
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[1],
|
|
712
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[5],
|
|
713
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[9],
|
|
714
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[13]
|
|
715
|
+
),
|
|
716
|
+
top: getFrustumPlane(
|
|
717
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[1],
|
|
718
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[5],
|
|
719
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[9],
|
|
720
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[13]
|
|
721
|
+
),
|
|
722
|
+
near: getFrustumPlane(
|
|
723
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[2],
|
|
724
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[6],
|
|
725
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[10],
|
|
726
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[14]
|
|
727
|
+
),
|
|
728
|
+
far: getFrustumPlane(
|
|
729
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[2],
|
|
730
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[6],
|
|
731
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[10],
|
|
732
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[14]
|
|
733
|
+
)
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
var scratchVector = new import_core2.Vector3();
|
|
737
|
+
function getFrustumPlane(a, b, c, d) {
|
|
738
|
+
scratchVector.set(a, b, c);
|
|
739
|
+
const L = scratchVector.len();
|
|
740
|
+
return { distance: d / L, normal: new import_core2.Vector3(-a / L, -b / L, -c / L) };
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// ../core/src/viewports/viewport.ts
|
|
744
|
+
var import_core3 = require("@math.gl/core");
|
|
745
|
+
var import_web_mercator = require("@math.gl/web-mercator");
|
|
746
|
+
|
|
747
|
+
// ../core/src/lib/constants.ts
|
|
748
|
+
var import_mjolnir = require("mjolnir.js");
|
|
749
|
+
var COORDINATE_SYSTEM = {
|
|
750
|
+
/**
|
|
751
|
+
* `LNGLAT` if rendering into a geospatial viewport, `CARTESIAN` otherwise
|
|
752
|
+
*/
|
|
753
|
+
DEFAULT: "default",
|
|
754
|
+
/**
|
|
755
|
+
* Positions are interpreted as [longitude, latitude, elevation]
|
|
756
|
+
* longitude/latitude are in degrees, elevation is in meters.
|
|
757
|
+
* Dimensions are in meters.
|
|
758
|
+
*/
|
|
759
|
+
LNGLAT: "lnglat",
|
|
760
|
+
/**
|
|
761
|
+
* Positions are interpreted as [x, y, z] in meter offsets from the coordinate origin.
|
|
762
|
+
* Dimensions are in meters.
|
|
763
|
+
*/
|
|
764
|
+
METER_OFFSETS: "meter-offsets",
|
|
765
|
+
/**
|
|
766
|
+
* Positions are interpreted as [deltaLng, deltaLat, elevation] from the coordinate origin.
|
|
767
|
+
* deltaLng/deltaLat are in degrees, elevation is in meters.
|
|
768
|
+
* Dimensions are in meters.
|
|
769
|
+
*/
|
|
770
|
+
LNGLAT_OFFSETS: "lnglat-offsets",
|
|
771
|
+
/**
|
|
772
|
+
* Positions and dimensions are in the common units of the viewport.
|
|
773
|
+
*/
|
|
774
|
+
CARTESIAN: "cartesian"
|
|
775
|
+
};
|
|
776
|
+
Object.defineProperty(COORDINATE_SYSTEM, "IDENTITY", {
|
|
777
|
+
get: () => {
|
|
778
|
+
log_default.deprecated("COORDINATE_SYSTEM.IDENTITY", "COORDINATE_SYSTEM.CARTESIAN")();
|
|
779
|
+
return COORDINATE_SYSTEM.CARTESIAN;
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
var PROJECTION_MODE = {
|
|
783
|
+
/**
|
|
784
|
+
* Render geospatial data in Web Mercator projection
|
|
785
|
+
*/
|
|
786
|
+
WEB_MERCATOR: 1,
|
|
787
|
+
/**
|
|
788
|
+
* Render geospatial data as a 3D globe
|
|
789
|
+
*/
|
|
790
|
+
GLOBE: 2,
|
|
791
|
+
/**
|
|
792
|
+
* (Internal use only) Web Mercator projection at high zoom
|
|
793
|
+
*/
|
|
794
|
+
WEB_MERCATOR_AUTO_OFFSET: 4,
|
|
795
|
+
/**
|
|
796
|
+
* No transformation
|
|
797
|
+
*/
|
|
798
|
+
IDENTITY: 0
|
|
799
|
+
};
|
|
800
|
+
var RECOGNIZERS = {
|
|
801
|
+
multipan: [import_mjolnir.Pan, { threshold: 10, direction: import_mjolnir.InputDirection.Vertical, pointers: 2 }],
|
|
802
|
+
pinch: [import_mjolnir.Pinch, {}, null, ["multipan"]],
|
|
803
|
+
pan: [import_mjolnir.Pan, { threshold: 1 }, ["pinch"], ["multipan"]],
|
|
804
|
+
dblclick: [import_mjolnir.Tap, { event: "dblclick", taps: 2 }],
|
|
805
|
+
click: [import_mjolnir.Tap, { event: "click" }, null, ["dblclick"]]
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
// ../core/src/viewports/viewport.ts
|
|
809
|
+
var DEGREES_TO_RADIANS = Math.PI / 180;
|
|
810
|
+
var IDENTITY = createMat4();
|
|
811
|
+
var ZERO_VECTOR = [0, 0, 0];
|
|
812
|
+
var DEFAULT_DISTANCE_SCALES = {
|
|
813
|
+
unitsPerMeter: [1, 1, 1],
|
|
814
|
+
metersPerUnit: [1, 1, 1]
|
|
815
|
+
};
|
|
816
|
+
function createProjectionMatrix({
|
|
817
|
+
width,
|
|
818
|
+
height,
|
|
819
|
+
orthographic,
|
|
820
|
+
fovyRadians,
|
|
821
|
+
focalDistance,
|
|
822
|
+
padding,
|
|
823
|
+
near,
|
|
824
|
+
far
|
|
825
|
+
}) {
|
|
826
|
+
const aspect = width / height;
|
|
827
|
+
const matrix = orthographic ? new import_core3.Matrix4().orthographic({ fovy: fovyRadians, aspect, focalDistance, near, far }) : new import_core3.Matrix4().perspective({ fovy: fovyRadians, aspect, near, far });
|
|
828
|
+
if (padding) {
|
|
829
|
+
const { left = 0, right = 0, top = 0, bottom = 0 } = padding;
|
|
830
|
+
const offsetX = (0, import_core3.clamp)((left + width - right) / 2, 0, width) - width / 2;
|
|
831
|
+
const offsetY = (0, import_core3.clamp)((top + height - bottom) / 2, 0, height) - height / 2;
|
|
832
|
+
matrix[8] -= offsetX * 2 / width;
|
|
833
|
+
matrix[9] += offsetY * 2 / height;
|
|
834
|
+
}
|
|
835
|
+
return matrix;
|
|
836
|
+
}
|
|
837
|
+
var _Viewport = class {
|
|
838
|
+
// eslint-disable-next-line complexity
|
|
839
|
+
constructor(opts = {}) {
|
|
840
|
+
this._frustumPlanes = {};
|
|
841
|
+
this.id = opts.id || this.constructor.displayName || "viewport";
|
|
842
|
+
this.x = opts.x || 0;
|
|
843
|
+
this.y = opts.y || 0;
|
|
844
|
+
this.width = opts.width || 1;
|
|
845
|
+
this.height = opts.height || 1;
|
|
846
|
+
this.zoom = opts.zoom || 0;
|
|
847
|
+
this.padding = opts.padding;
|
|
848
|
+
this.distanceScales = opts.distanceScales || DEFAULT_DISTANCE_SCALES;
|
|
849
|
+
this.focalDistance = opts.focalDistance || 1;
|
|
850
|
+
this.position = opts.position || ZERO_VECTOR;
|
|
851
|
+
this.modelMatrix = opts.modelMatrix || null;
|
|
852
|
+
const { longitude, latitude } = opts;
|
|
853
|
+
this.isGeospatial = Number.isFinite(latitude) && Number.isFinite(longitude);
|
|
854
|
+
this._initProps(opts);
|
|
855
|
+
this._initMatrices(opts);
|
|
856
|
+
this.equals = this.equals.bind(this);
|
|
857
|
+
this.project = this.project.bind(this);
|
|
858
|
+
this.unproject = this.unproject.bind(this);
|
|
859
|
+
this.projectPosition = this.projectPosition.bind(this);
|
|
860
|
+
this.unprojectPosition = this.unprojectPosition.bind(this);
|
|
861
|
+
this.projectFlat = this.projectFlat.bind(this);
|
|
862
|
+
this.unprojectFlat = this.unprojectFlat.bind(this);
|
|
863
|
+
}
|
|
864
|
+
get subViewports() {
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
get metersPerPixel() {
|
|
868
|
+
return this.distanceScales.metersPerUnit[2] / this.scale;
|
|
869
|
+
}
|
|
870
|
+
get projectionMode() {
|
|
871
|
+
if (this.isGeospatial) {
|
|
872
|
+
return this.zoom < 12 ? PROJECTION_MODE.WEB_MERCATOR : PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET;
|
|
873
|
+
}
|
|
874
|
+
return PROJECTION_MODE.IDENTITY;
|
|
875
|
+
}
|
|
876
|
+
// Two viewports are equal if width and height are identical, and if
|
|
877
|
+
// their view and projection matrices are (approximately) equal.
|
|
878
|
+
equals(viewport) {
|
|
879
|
+
if (!(viewport instanceof _Viewport)) {
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
if (this === viewport) {
|
|
883
|
+
return true;
|
|
884
|
+
}
|
|
885
|
+
return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && (0, import_core3.equals)(viewport.projectionMatrix, this.projectionMatrix) && (0, import_core3.equals)(viewport.viewMatrix, this.viewMatrix);
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Projects xyz (possibly latitude and longitude) to pixel coordinates in window
|
|
889
|
+
* using viewport projection parameters
|
|
890
|
+
* - [longitude, latitude] to [x, y]
|
|
891
|
+
* - [longitude, latitude, Z] => [x, y, z]
|
|
892
|
+
* Note: By default, returns top-left coordinates for canvas/SVG type render
|
|
893
|
+
*
|
|
894
|
+
* @param {Array} lngLatZ - [lng, lat] or [lng, lat, Z]
|
|
895
|
+
* @param {Object} opts - options
|
|
896
|
+
* @param {Object} opts.topLeft=true - Whether projected coords are top left
|
|
897
|
+
* @return {Array} - [x, y] or [x, y, z] in top left coords
|
|
898
|
+
*/
|
|
899
|
+
project(xyz, { topLeft = true } = {}) {
|
|
900
|
+
const worldPosition = this.projectPosition(xyz);
|
|
901
|
+
const coord = (0, import_web_mercator.worldToPixels)(worldPosition, this.pixelProjectionMatrix);
|
|
902
|
+
const [x, y] = coord;
|
|
903
|
+
const y2 = topLeft ? y : this.height - y;
|
|
904
|
+
return xyz.length === 2 ? [x, y2] : [x, y2, coord[2]];
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Unproject pixel coordinates on screen onto world coordinates,
|
|
908
|
+
* (possibly [lon, lat]) on map.
|
|
909
|
+
* - [x, y] => [lng, lat]
|
|
910
|
+
* - [x, y, z] => [lng, lat, Z]
|
|
911
|
+
* @param {Array} xyz -
|
|
912
|
+
* @param {Object} opts - options
|
|
913
|
+
* @param {Object} opts.topLeft=true - Whether origin is top left
|
|
914
|
+
* @return {Array|null} - [lng, lat, Z] or [X, Y, Z]
|
|
915
|
+
*/
|
|
916
|
+
unproject(xyz, { topLeft = true, targetZ } = {}) {
|
|
917
|
+
const [x, y, z] = xyz;
|
|
918
|
+
const y2 = topLeft ? y : this.height - y;
|
|
919
|
+
const targetZWorld = targetZ && targetZ * this.distanceScales.unitsPerMeter[2];
|
|
920
|
+
const coord = (0, import_web_mercator.pixelsToWorld)([x, y2, z], this.pixelUnprojectionMatrix, targetZWorld);
|
|
921
|
+
const [X, Y, Z] = this.unprojectPosition(coord);
|
|
922
|
+
if (Number.isFinite(z)) {
|
|
923
|
+
return [X, Y, Z];
|
|
924
|
+
}
|
|
925
|
+
return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
|
|
926
|
+
}
|
|
927
|
+
// NON_LINEAR PROJECTION HOOKS
|
|
928
|
+
// Used for web meractor projection
|
|
929
|
+
projectPosition(xyz) {
|
|
930
|
+
const [X, Y] = this.projectFlat(xyz);
|
|
931
|
+
const Z = (xyz[2] || 0) * this.distanceScales.unitsPerMeter[2];
|
|
932
|
+
return [X, Y, Z];
|
|
933
|
+
}
|
|
934
|
+
unprojectPosition(xyz) {
|
|
935
|
+
const [X, Y] = this.unprojectFlat(xyz);
|
|
936
|
+
const Z = (xyz[2] || 0) * this.distanceScales.metersPerUnit[2];
|
|
937
|
+
return [X, Y, Z];
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
|
|
941
|
+
* Performs the nonlinear part of the web mercator projection.
|
|
942
|
+
* Remaining projection is done with 4x4 matrices which also handles
|
|
943
|
+
* perspective.
|
|
944
|
+
* @param {Array} lngLat - [lng, lat] coordinates
|
|
945
|
+
* Specifies a point on the sphere to project onto the map.
|
|
946
|
+
* @return {Array} [x,y] coordinates.
|
|
947
|
+
*/
|
|
948
|
+
projectFlat(xyz) {
|
|
949
|
+
if (this.isGeospatial) {
|
|
950
|
+
const result = (0, import_web_mercator.lngLatToWorld)(xyz);
|
|
951
|
+
result[1] = (0, import_core3.clamp)(result[1], -318, 830);
|
|
952
|
+
return result;
|
|
953
|
+
}
|
|
954
|
+
return xyz;
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Unproject world point [x,y] on map onto {lat, lon} on sphere
|
|
958
|
+
* @param {object|Vector} xy - object with {x,y} members
|
|
959
|
+
* representing point on projected map plane
|
|
960
|
+
* @return {GeoCoordinates} - object with {lat,lon} of point on sphere.
|
|
961
|
+
* Has toArray method if you need a GeoJSON Array.
|
|
962
|
+
* Per cartographic tradition, lat and lon are specified as degrees.
|
|
963
|
+
*/
|
|
964
|
+
unprojectFlat(xyz) {
|
|
965
|
+
if (this.isGeospatial) {
|
|
966
|
+
return (0, import_web_mercator.worldToLngLat)(xyz);
|
|
967
|
+
}
|
|
968
|
+
return xyz;
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* Get bounds of the current viewport
|
|
972
|
+
* @return {Array} - [minX, minY, maxX, maxY]
|
|
973
|
+
*/
|
|
974
|
+
getBounds(options = {}) {
|
|
975
|
+
const unprojectOption = { targetZ: options.z || 0 };
|
|
976
|
+
const topLeft = this.unproject([0, 0], unprojectOption);
|
|
977
|
+
const topRight = this.unproject([this.width, 0], unprojectOption);
|
|
978
|
+
const bottomLeft = this.unproject([0, this.height], unprojectOption);
|
|
979
|
+
const bottomRight = this.unproject([this.width, this.height], unprojectOption);
|
|
980
|
+
return [
|
|
981
|
+
Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
|
|
982
|
+
Math.min(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]),
|
|
983
|
+
Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
|
|
984
|
+
Math.max(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1])
|
|
985
|
+
];
|
|
986
|
+
}
|
|
987
|
+
getDistanceScales(coordinateOrigin) {
|
|
988
|
+
if (coordinateOrigin && this.isGeospatial) {
|
|
989
|
+
return (0, import_web_mercator.getDistanceScales)({
|
|
990
|
+
longitude: coordinateOrigin[0],
|
|
991
|
+
latitude: coordinateOrigin[1],
|
|
992
|
+
highPrecision: true
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
return this.distanceScales;
|
|
996
|
+
}
|
|
997
|
+
containsPixel({
|
|
998
|
+
x,
|
|
999
|
+
y,
|
|
1000
|
+
width = 1,
|
|
1001
|
+
height = 1
|
|
1002
|
+
}) {
|
|
1003
|
+
return x < this.x + this.width && this.x < x + width && y < this.y + this.height && this.y < y + height;
|
|
1004
|
+
}
|
|
1005
|
+
// Extract frustum planes in common space
|
|
1006
|
+
getFrustumPlanes() {
|
|
1007
|
+
if (this._frustumPlanes.near) {
|
|
1008
|
+
return this._frustumPlanes;
|
|
1009
|
+
}
|
|
1010
|
+
Object.assign(this._frustumPlanes, getFrustumPlanes(this.viewProjectionMatrix));
|
|
1011
|
+
return this._frustumPlanes;
|
|
1012
|
+
}
|
|
1013
|
+
// EXPERIMENTAL METHODS
|
|
1014
|
+
/**
|
|
1015
|
+
* Needed by panning and linear transition
|
|
1016
|
+
* Pan the viewport to place a given world coordinate at screen point [x, y]
|
|
1017
|
+
*
|
|
1018
|
+
* @param {Array} coords - world coordinates
|
|
1019
|
+
* @param {Array} pixel - [x,y] coordinates on screen
|
|
1020
|
+
* @param {Array} startPixel - [x,y] screen position where pan started (optional, for delta-based panning)
|
|
1021
|
+
* @return {Object} props of the new viewport
|
|
1022
|
+
*/
|
|
1023
|
+
panByPosition(coords, pixel, startPixel) {
|
|
1024
|
+
return null;
|
|
1025
|
+
}
|
|
1026
|
+
// INTERNAL METHODS
|
|
1027
|
+
/* eslint-disable complexity, max-statements */
|
|
1028
|
+
_initProps(opts) {
|
|
1029
|
+
const longitude = opts.longitude;
|
|
1030
|
+
const latitude = opts.latitude;
|
|
1031
|
+
if (this.isGeospatial) {
|
|
1032
|
+
if (!Number.isFinite(opts.zoom)) {
|
|
1033
|
+
this.zoom = (0, import_web_mercator.getMeterZoom)({ latitude }) + Math.log2(this.focalDistance);
|
|
1034
|
+
}
|
|
1035
|
+
this.distanceScales = opts.distanceScales || (0, import_web_mercator.getDistanceScales)({ latitude, longitude });
|
|
1036
|
+
}
|
|
1037
|
+
const scale = Math.pow(2, this.zoom);
|
|
1038
|
+
this.scale = scale;
|
|
1039
|
+
const { position, modelMatrix } = opts;
|
|
1040
|
+
let meterOffset = ZERO_VECTOR;
|
|
1041
|
+
if (position) {
|
|
1042
|
+
meterOffset = modelMatrix ? new import_core3.Matrix4(modelMatrix).transformAsVector(position, []) : position;
|
|
1043
|
+
}
|
|
1044
|
+
if (this.isGeospatial) {
|
|
1045
|
+
const center = this.projectPosition([longitude, latitude, 0]);
|
|
1046
|
+
this.center = new import_core3.Vector3(meterOffset).scale(this.distanceScales.unitsPerMeter).add(center);
|
|
1047
|
+
} else {
|
|
1048
|
+
this.center = this.projectPosition(meterOffset);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
/* eslint-enable complexity, max-statements */
|
|
1052
|
+
_initMatrices(opts) {
|
|
1053
|
+
const {
|
|
1054
|
+
// View matrix
|
|
1055
|
+
viewMatrix = IDENTITY,
|
|
1056
|
+
// Projection matrix
|
|
1057
|
+
projectionMatrix = null,
|
|
1058
|
+
// Projection matrix parameters, used if projectionMatrix not supplied
|
|
1059
|
+
orthographic = false,
|
|
1060
|
+
fovyRadians,
|
|
1061
|
+
fovy = 75,
|
|
1062
|
+
near = 0.1,
|
|
1063
|
+
// Distance of near clipping plane
|
|
1064
|
+
far = 1e3,
|
|
1065
|
+
// Distance of far clipping plane
|
|
1066
|
+
padding = null,
|
|
1067
|
+
// Center offset in pixels
|
|
1068
|
+
focalDistance = 1
|
|
1069
|
+
} = opts;
|
|
1070
|
+
this.viewMatrixUncentered = viewMatrix;
|
|
1071
|
+
this.viewMatrix = new import_core3.Matrix4().multiplyRight(viewMatrix).translate(new import_core3.Vector3(this.center).negate());
|
|
1072
|
+
this.projectionMatrix = projectionMatrix || createProjectionMatrix({
|
|
1073
|
+
width: this.width,
|
|
1074
|
+
height: this.height,
|
|
1075
|
+
orthographic,
|
|
1076
|
+
fovyRadians: fovyRadians || fovy * DEGREES_TO_RADIANS,
|
|
1077
|
+
focalDistance,
|
|
1078
|
+
padding,
|
|
1079
|
+
near,
|
|
1080
|
+
far
|
|
1081
|
+
});
|
|
1082
|
+
const vpm = createMat4();
|
|
1083
|
+
import_core3.mat4.multiply(vpm, vpm, this.projectionMatrix);
|
|
1084
|
+
import_core3.mat4.multiply(vpm, vpm, this.viewMatrix);
|
|
1085
|
+
this.viewProjectionMatrix = vpm;
|
|
1086
|
+
this.viewMatrixInverse = import_core3.mat4.invert([], this.viewMatrix) || this.viewMatrix;
|
|
1087
|
+
this.cameraPosition = getCameraPosition(this.viewMatrixInverse);
|
|
1088
|
+
const viewportMatrix = createMat4();
|
|
1089
|
+
const pixelProjectionMatrix = createMat4();
|
|
1090
|
+
import_core3.mat4.scale(viewportMatrix, viewportMatrix, [this.width / 2, -this.height / 2, 1]);
|
|
1091
|
+
import_core3.mat4.translate(viewportMatrix, viewportMatrix, [1, -1, 0]);
|
|
1092
|
+
import_core3.mat4.multiply(pixelProjectionMatrix, viewportMatrix, this.viewProjectionMatrix);
|
|
1093
|
+
this.pixelProjectionMatrix = pixelProjectionMatrix;
|
|
1094
|
+
this.pixelUnprojectionMatrix = import_core3.mat4.invert(createMat4(), this.pixelProjectionMatrix);
|
|
1095
|
+
if (!this.pixelUnprojectionMatrix) {
|
|
1096
|
+
log_default.warn("Pixel project matrix not invertible")();
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
var Viewport = _Viewport;
|
|
1101
|
+
Viewport.displayName = "Viewport";
|
|
1102
|
+
|
|
1103
|
+
// ../core/src/viewports/web-mercator-viewport.ts
|
|
1104
|
+
var import_web_mercator2 = require("@math.gl/web-mercator");
|
|
1105
|
+
var import_core4 = require("@math.gl/core");
|
|
1106
|
+
var _WebMercatorViewport = class extends Viewport {
|
|
1107
|
+
/* eslint-disable complexity, max-statements */
|
|
1108
|
+
constructor(opts = {}) {
|
|
1109
|
+
const {
|
|
1110
|
+
latitude = 0,
|
|
1111
|
+
longitude = 0,
|
|
1112
|
+
zoom = 0,
|
|
1113
|
+
pitch = 0,
|
|
1114
|
+
bearing = 0,
|
|
1115
|
+
nearZMultiplier = 0.1,
|
|
1116
|
+
farZMultiplier = 1.01,
|
|
1117
|
+
nearZ,
|
|
1118
|
+
farZ,
|
|
1119
|
+
orthographic = false,
|
|
1120
|
+
projectionMatrix,
|
|
1121
|
+
repeat = false,
|
|
1122
|
+
worldOffset = 0,
|
|
1123
|
+
position,
|
|
1124
|
+
padding,
|
|
1125
|
+
// backward compatibility
|
|
1126
|
+
// TODO: remove in v9
|
|
1127
|
+
legacyMeterSizes = false
|
|
1128
|
+
} = opts;
|
|
1129
|
+
let { width, height, altitude = 1.5 } = opts;
|
|
1130
|
+
const scale = Math.pow(2, zoom);
|
|
1131
|
+
width = width || 1;
|
|
1132
|
+
height = height || 1;
|
|
1133
|
+
let fovy;
|
|
1134
|
+
let projectionParameters = null;
|
|
1135
|
+
if (projectionMatrix) {
|
|
1136
|
+
altitude = projectionMatrix[5] / 2;
|
|
1137
|
+
fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
|
|
1138
|
+
} else {
|
|
1139
|
+
if (opts.fovy) {
|
|
1140
|
+
fovy = opts.fovy;
|
|
1141
|
+
altitude = (0, import_web_mercator2.fovyToAltitude)(fovy);
|
|
1142
|
+
} else {
|
|
1143
|
+
fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
|
|
1144
|
+
}
|
|
1145
|
+
let offset;
|
|
1146
|
+
if (padding) {
|
|
1147
|
+
const { top = 0, bottom = 0 } = padding;
|
|
1148
|
+
offset = [0, (0, import_core4.clamp)((top + height - bottom) / 2, 0, height) - height / 2];
|
|
1149
|
+
}
|
|
1150
|
+
projectionParameters = (0, import_web_mercator2.getProjectionParameters)({
|
|
1151
|
+
width,
|
|
1152
|
+
height,
|
|
1153
|
+
scale,
|
|
1154
|
+
center: position && [0, 0, position[2] * (0, import_web_mercator2.unitsPerMeter)(latitude)],
|
|
1155
|
+
offset,
|
|
1156
|
+
pitch,
|
|
1157
|
+
fovy,
|
|
1158
|
+
nearZMultiplier,
|
|
1159
|
+
farZMultiplier
|
|
1160
|
+
});
|
|
1161
|
+
if (Number.isFinite(nearZ)) {
|
|
1162
|
+
projectionParameters.near = nearZ;
|
|
1163
|
+
}
|
|
1164
|
+
if (Number.isFinite(farZ)) {
|
|
1165
|
+
projectionParameters.far = farZ;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
let viewMatrixUncentered = (0, import_web_mercator2.getViewMatrix)({
|
|
1169
|
+
height,
|
|
1170
|
+
pitch,
|
|
1171
|
+
bearing,
|
|
1172
|
+
scale,
|
|
1173
|
+
altitude
|
|
1174
|
+
});
|
|
1175
|
+
if (worldOffset) {
|
|
1176
|
+
const viewOffset = new import_core4.Matrix4().translate([512 * worldOffset, 0, 0]);
|
|
1177
|
+
viewMatrixUncentered = viewOffset.multiplyLeft(viewMatrixUncentered);
|
|
1178
|
+
}
|
|
1179
|
+
super({
|
|
1180
|
+
...opts,
|
|
1181
|
+
// x, y,
|
|
1182
|
+
width,
|
|
1183
|
+
height,
|
|
1184
|
+
// view matrix
|
|
1185
|
+
viewMatrix: viewMatrixUncentered,
|
|
1186
|
+
longitude,
|
|
1187
|
+
latitude,
|
|
1188
|
+
zoom,
|
|
1189
|
+
// projection matrix parameters
|
|
1190
|
+
...projectionParameters,
|
|
1191
|
+
fovy,
|
|
1192
|
+
focalDistance: altitude
|
|
1193
|
+
});
|
|
1194
|
+
this.latitude = latitude;
|
|
1195
|
+
this.longitude = longitude;
|
|
1196
|
+
this.zoom = zoom;
|
|
1197
|
+
this.pitch = pitch;
|
|
1198
|
+
this.bearing = bearing;
|
|
1199
|
+
this.altitude = altitude;
|
|
1200
|
+
this.fovy = fovy;
|
|
1201
|
+
this.orthographic = orthographic;
|
|
1202
|
+
this._subViewports = repeat ? [] : null;
|
|
1203
|
+
this._pseudoMeters = legacyMeterSizes;
|
|
1204
|
+
Object.freeze(this);
|
|
1205
|
+
}
|
|
1206
|
+
/* eslint-enable complexity, max-statements */
|
|
1207
|
+
get subViewports() {
|
|
1208
|
+
if (this._subViewports && !this._subViewports.length) {
|
|
1209
|
+
const bounds = this.getBounds();
|
|
1210
|
+
const minOffset = Math.floor((bounds[0] + 180) / 360);
|
|
1211
|
+
const maxOffset = Math.ceil((bounds[2] - 180) / 360);
|
|
1212
|
+
for (let x = minOffset; x <= maxOffset; x++) {
|
|
1213
|
+
const offsetViewport = x ? new _WebMercatorViewport({
|
|
1214
|
+
...this,
|
|
1215
|
+
worldOffset: x
|
|
1216
|
+
}) : this;
|
|
1217
|
+
this._subViewports.push(offsetViewport);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
return this._subViewports;
|
|
1221
|
+
}
|
|
1222
|
+
projectPosition(xyz) {
|
|
1223
|
+
if (this._pseudoMeters) {
|
|
1224
|
+
return super.projectPosition(xyz);
|
|
1225
|
+
}
|
|
1226
|
+
const [X, Y] = this.projectFlat(xyz);
|
|
1227
|
+
const Z = (xyz[2] || 0) * (0, import_web_mercator2.unitsPerMeter)(xyz[1]);
|
|
1228
|
+
return [X, Y, Z];
|
|
1229
|
+
}
|
|
1230
|
+
unprojectPosition(xyz) {
|
|
1231
|
+
if (this._pseudoMeters) {
|
|
1232
|
+
return super.unprojectPosition(xyz);
|
|
1233
|
+
}
|
|
1234
|
+
const [X, Y] = this.unprojectFlat(xyz);
|
|
1235
|
+
const Z = (xyz[2] || 0) / (0, import_web_mercator2.unitsPerMeter)(Y);
|
|
1236
|
+
return [X, Y, Z];
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Add a meter delta to a base lnglat coordinate, returning a new lnglat array
|
|
1240
|
+
*
|
|
1241
|
+
* Note: Uses simple linear approximation around the viewport center
|
|
1242
|
+
* Error increases with size of offset (roughly 1% per 100km)
|
|
1243
|
+
*
|
|
1244
|
+
* @param {[Number,Number]|[Number,Number,Number]) lngLatZ - base coordinate
|
|
1245
|
+
* @param {[Number,Number]|[Number,Number,Number]) xyz - array of meter deltas
|
|
1246
|
+
* @return {[Number,Number]|[Number,Number,Number]) array of [lng,lat,z] deltas
|
|
1247
|
+
*/
|
|
1248
|
+
addMetersToLngLat(lngLatZ, xyz) {
|
|
1249
|
+
return (0, import_web_mercator2.addMetersToLngLat)(lngLatZ, xyz);
|
|
1250
|
+
}
|
|
1251
|
+
panByPosition(coords, pixel, startPixel) {
|
|
1252
|
+
const fromLocation = (0, import_web_mercator2.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
|
|
1253
|
+
const toLocation = this.projectFlat(coords);
|
|
1254
|
+
const translate = import_core4.vec2.add([], toLocation, import_core4.vec2.negate([], fromLocation));
|
|
1255
|
+
const newCenter = import_core4.vec2.add([], this.center, translate);
|
|
1256
|
+
const [longitude, latitude] = this.unprojectFlat(newCenter);
|
|
1257
|
+
return { longitude, latitude };
|
|
1258
|
+
}
|
|
1259
|
+
/**
|
|
1260
|
+
* Returns a new longitude and latitude that keeps a 3D world coordinate at a given screen pixel
|
|
1261
|
+
* This version handles the z-component (altitude) properly for cameras positioned above ground
|
|
1262
|
+
*/
|
|
1263
|
+
panByPosition3D(coords, pixel) {
|
|
1264
|
+
const targetZ = coords[2] || 0;
|
|
1265
|
+
const deltaLngLat = import_core4.vec2.sub([], coords, this.unproject(pixel, { targetZ }));
|
|
1266
|
+
return { longitude: this.longitude + deltaLngLat[0], latitude: this.latitude + deltaLngLat[1] };
|
|
1267
|
+
}
|
|
1268
|
+
getBounds(options = {}) {
|
|
1269
|
+
const corners = (0, import_web_mercator2.getBounds)(this, options.z || 0);
|
|
1270
|
+
return [
|
|
1271
|
+
Math.min(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
|
|
1272
|
+
Math.min(corners[0][1], corners[1][1], corners[2][1], corners[3][1]),
|
|
1273
|
+
Math.max(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
|
|
1274
|
+
Math.max(corners[0][1], corners[1][1], corners[2][1], corners[3][1])
|
|
1275
|
+
];
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Returns a new viewport that fit around the given rectangle.
|
|
1279
|
+
* Only supports non-perspective mode.
|
|
1280
|
+
*/
|
|
1281
|
+
fitBounds(bounds, options = {}) {
|
|
1282
|
+
const { width, height } = this;
|
|
1283
|
+
const { longitude, latitude, zoom } = (0, import_web_mercator2.fitBounds)({ width, height, bounds, ...options });
|
|
1284
|
+
return new _WebMercatorViewport({ width, height, longitude, latitude, zoom });
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1287
|
+
var WebMercatorViewport = _WebMercatorViewport;
|
|
1288
|
+
WebMercatorViewport.displayName = "WebMercatorViewport";
|
|
1289
|
+
|
|
1290
|
+
// ../core/src/controllers/map-controller.ts
|
|
1291
|
+
var import_core9 = require("@math.gl/core");
|
|
1292
|
+
|
|
1293
|
+
// ../core/src/transitions/transition.ts
|
|
1294
|
+
var Transition = class {
|
|
1295
|
+
/**
|
|
1296
|
+
* @params timeline {Timeline}
|
|
1297
|
+
*/
|
|
1298
|
+
constructor(timeline) {
|
|
1299
|
+
this._inProgress = false;
|
|
1300
|
+
this._handle = null;
|
|
1301
|
+
this.time = 0;
|
|
1302
|
+
// @ts-expect-error
|
|
1303
|
+
this.settings = {
|
|
1304
|
+
duration: 0
|
|
1305
|
+
};
|
|
1306
|
+
this._timeline = timeline;
|
|
1307
|
+
}
|
|
1308
|
+
/* Public API */
|
|
1309
|
+
get inProgress() {
|
|
1310
|
+
return this._inProgress;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* (re)start this transition.
|
|
1314
|
+
* @params props {object} - optional overriding props. see constructor
|
|
1315
|
+
*/
|
|
1316
|
+
start(settings) {
|
|
1317
|
+
var _a, _b;
|
|
1318
|
+
this.cancel();
|
|
1319
|
+
this.settings = settings;
|
|
1320
|
+
this._inProgress = true;
|
|
1321
|
+
(_b = (_a = this.settings).onStart) == null ? void 0 : _b.call(_a, this);
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* end this transition if it is in progress.
|
|
1325
|
+
*/
|
|
1326
|
+
end() {
|
|
1327
|
+
var _a, _b;
|
|
1328
|
+
if (this._inProgress) {
|
|
1329
|
+
this._timeline.removeChannel(this._handle);
|
|
1330
|
+
this._handle = null;
|
|
1331
|
+
this._inProgress = false;
|
|
1332
|
+
(_b = (_a = this.settings).onEnd) == null ? void 0 : _b.call(_a, this);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* cancel this transition if it is in progress.
|
|
1337
|
+
*/
|
|
1338
|
+
cancel() {
|
|
1339
|
+
var _a, _b;
|
|
1340
|
+
if (this._inProgress) {
|
|
1341
|
+
(_b = (_a = this.settings).onInterrupt) == null ? void 0 : _b.call(_a, this);
|
|
1342
|
+
this._timeline.removeChannel(this._handle);
|
|
1343
|
+
this._handle = null;
|
|
1344
|
+
this._inProgress = false;
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* update this transition. Returns `true` if updated.
|
|
1349
|
+
*/
|
|
1350
|
+
update() {
|
|
1351
|
+
var _a, _b;
|
|
1352
|
+
if (!this._inProgress) {
|
|
1353
|
+
return false;
|
|
1354
|
+
}
|
|
1355
|
+
if (this._handle === null) {
|
|
1356
|
+
const { _timeline: timeline, settings } = this;
|
|
1357
|
+
this._handle = timeline.addChannel({
|
|
1358
|
+
delay: timeline.getTime(),
|
|
1359
|
+
duration: settings.duration
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
this.time = this._timeline.getTime(this._handle);
|
|
1363
|
+
this._onUpdate();
|
|
1364
|
+
(_b = (_a = this.settings).onUpdate) == null ? void 0 : _b.call(_a, this);
|
|
1365
|
+
if (this._timeline.isFinished(this._handle)) {
|
|
1366
|
+
this.end();
|
|
1367
|
+
}
|
|
1368
|
+
return true;
|
|
1369
|
+
}
|
|
1370
|
+
/* Private API */
|
|
1371
|
+
_onUpdate() {
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
|
|
1375
|
+
// ../core/src/controllers/transition-manager.ts
|
|
1376
|
+
var noop = () => {
|
|
1377
|
+
};
|
|
1378
|
+
var TRANSITION_EVENTS = {
|
|
1379
|
+
BREAK: 1,
|
|
1380
|
+
SNAP_TO_END: 2,
|
|
1381
|
+
IGNORE: 3
|
|
1382
|
+
};
|
|
1383
|
+
var DEFAULT_EASING = (t) => t;
|
|
1384
|
+
var DEFAULT_INTERRUPTION = TRANSITION_EVENTS.BREAK;
|
|
1385
|
+
var TransitionManager = class {
|
|
1386
|
+
constructor(opts) {
|
|
1387
|
+
this._onTransitionUpdate = (transition) => {
|
|
1388
|
+
const {
|
|
1389
|
+
time,
|
|
1390
|
+
settings: { interpolator, startProps, endProps, duration, easing }
|
|
1391
|
+
} = transition;
|
|
1392
|
+
const t = easing(time / duration);
|
|
1393
|
+
const viewport = interpolator.interpolateProps(startProps, endProps, t);
|
|
1394
|
+
this.propsInTransition = this.getControllerState({
|
|
1395
|
+
...this.props,
|
|
1396
|
+
...viewport
|
|
1397
|
+
}).getViewportProps();
|
|
1398
|
+
this.onViewStateChange({
|
|
1399
|
+
viewState: this.propsInTransition,
|
|
1400
|
+
oldViewState: this.props
|
|
1401
|
+
});
|
|
1402
|
+
};
|
|
1403
|
+
this.getControllerState = opts.getControllerState;
|
|
1404
|
+
this.propsInTransition = null;
|
|
1405
|
+
this.transition = new Transition(opts.timeline);
|
|
1406
|
+
this.onViewStateChange = opts.onViewStateChange || noop;
|
|
1407
|
+
this.onStateChange = opts.onStateChange || noop;
|
|
1408
|
+
}
|
|
1409
|
+
finalize() {
|
|
1410
|
+
this.transition.cancel();
|
|
1411
|
+
}
|
|
1412
|
+
// Returns current transitioned viewport.
|
|
1413
|
+
getViewportInTransition() {
|
|
1414
|
+
return this.propsInTransition;
|
|
1415
|
+
}
|
|
1416
|
+
// Process the vewiport change, either ignore or trigger a new transition.
|
|
1417
|
+
// Return true if a new transition is triggered, false otherwise.
|
|
1418
|
+
processViewStateChange(nextProps) {
|
|
1419
|
+
let transitionTriggered = false;
|
|
1420
|
+
const currentProps = this.props;
|
|
1421
|
+
this.props = nextProps;
|
|
1422
|
+
if (!currentProps || this._shouldIgnoreViewportChange(currentProps, nextProps)) {
|
|
1423
|
+
return false;
|
|
1424
|
+
}
|
|
1425
|
+
if (this._isTransitionEnabled(nextProps)) {
|
|
1426
|
+
let startProps = currentProps;
|
|
1427
|
+
if (this.transition.inProgress) {
|
|
1428
|
+
const { interruption, endProps } = this.transition.settings;
|
|
1429
|
+
startProps = {
|
|
1430
|
+
...currentProps,
|
|
1431
|
+
...interruption === TRANSITION_EVENTS.SNAP_TO_END ? endProps : this.propsInTransition || currentProps
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
this._triggerTransition(startProps, nextProps);
|
|
1435
|
+
transitionTriggered = true;
|
|
1436
|
+
} else {
|
|
1437
|
+
this.transition.cancel();
|
|
1438
|
+
}
|
|
1439
|
+
return transitionTriggered;
|
|
1440
|
+
}
|
|
1441
|
+
updateTransition() {
|
|
1442
|
+
this.transition.update();
|
|
1443
|
+
}
|
|
1444
|
+
// Helper methods
|
|
1445
|
+
_isTransitionEnabled(props) {
|
|
1446
|
+
const { transitionDuration, transitionInterpolator } = props;
|
|
1447
|
+
return (transitionDuration > 0 || transitionDuration === "auto") && Boolean(transitionInterpolator);
|
|
1448
|
+
}
|
|
1449
|
+
_isUpdateDueToCurrentTransition(props) {
|
|
1450
|
+
if (this.transition.inProgress && this.propsInTransition) {
|
|
1451
|
+
return this.transition.settings.interpolator.arePropsEqual(
|
|
1452
|
+
props,
|
|
1453
|
+
this.propsInTransition
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
return false;
|
|
1457
|
+
}
|
|
1458
|
+
_shouldIgnoreViewportChange(currentProps, nextProps) {
|
|
1459
|
+
if (this.transition.inProgress) {
|
|
1460
|
+
const transitionSettings = this.transition.settings;
|
|
1461
|
+
return transitionSettings.interruption === TRANSITION_EVENTS.IGNORE || // Ignore update if it is due to current active transition.
|
|
1462
|
+
this._isUpdateDueToCurrentTransition(nextProps);
|
|
1463
|
+
}
|
|
1464
|
+
if (this._isTransitionEnabled(nextProps)) {
|
|
1465
|
+
return nextProps.transitionInterpolator.arePropsEqual(
|
|
1466
|
+
currentProps,
|
|
1467
|
+
nextProps
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
return true;
|
|
1471
|
+
}
|
|
1472
|
+
_triggerTransition(startProps, endProps) {
|
|
1473
|
+
const startViewstate = this.getControllerState(startProps);
|
|
1474
|
+
const endViewStateProps = this.getControllerState(endProps).shortestPathFrom(startViewstate);
|
|
1475
|
+
const transitionInterpolator = endProps.transitionInterpolator;
|
|
1476
|
+
const duration = transitionInterpolator.getDuration ? transitionInterpolator.getDuration(startProps, endProps) : endProps.transitionDuration;
|
|
1477
|
+
if (duration === 0) {
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
const initialProps = transitionInterpolator.initializeProps(startProps, endViewStateProps);
|
|
1481
|
+
this.propsInTransition = {};
|
|
1482
|
+
const transitionSettings = {
|
|
1483
|
+
duration,
|
|
1484
|
+
easing: endProps.transitionEasing || DEFAULT_EASING,
|
|
1485
|
+
interpolator: transitionInterpolator,
|
|
1486
|
+
interruption: endProps.transitionInterruption || DEFAULT_INTERRUPTION,
|
|
1487
|
+
startProps: initialProps.start,
|
|
1488
|
+
endProps: initialProps.end,
|
|
1489
|
+
onStart: endProps.onTransitionStart,
|
|
1490
|
+
onUpdate: this._onTransitionUpdate,
|
|
1491
|
+
onInterrupt: this._onTransitionEnd(endProps.onTransitionInterrupt),
|
|
1492
|
+
onEnd: this._onTransitionEnd(endProps.onTransitionEnd)
|
|
1493
|
+
};
|
|
1494
|
+
this.transition.start(transitionSettings);
|
|
1495
|
+
this.onStateChange({ inTransition: true });
|
|
1496
|
+
this.updateTransition();
|
|
1497
|
+
}
|
|
1498
|
+
_onTransitionEnd(callback) {
|
|
1499
|
+
return (transition) => {
|
|
1500
|
+
this.propsInTransition = null;
|
|
1501
|
+
this.onStateChange({
|
|
1502
|
+
inTransition: false,
|
|
1503
|
+
isZooming: false,
|
|
1504
|
+
isPanning: false,
|
|
1505
|
+
isRotating: false
|
|
1506
|
+
});
|
|
1507
|
+
callback == null ? void 0 : callback(transition);
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
|
|
1512
|
+
// ../core/src/transitions/transition-interpolator.ts
|
|
1513
|
+
var import_core5 = require("@math.gl/core");
|
|
1514
|
+
|
|
1515
|
+
// ../core/src/utils/assert.ts
|
|
1516
|
+
function assert(condition, message) {
|
|
1517
|
+
if (!condition) {
|
|
1518
|
+
throw new Error(message || "deck.gl: assertion failed.");
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
// ../core/src/transitions/transition-interpolator.ts
|
|
1523
|
+
var TransitionInterpolator = class {
|
|
1524
|
+
/**
|
|
1525
|
+
* @param opts {array|object}
|
|
1526
|
+
* @param opts.compare {array} - prop names used in equality check
|
|
1527
|
+
* @param opts.extract {array} - prop names needed for interpolation
|
|
1528
|
+
* @param opts.required {array} - prop names that must be supplied
|
|
1529
|
+
* alternatively, supply one list of prop names as `opts` if all of the above are the same.
|
|
1530
|
+
*/
|
|
1531
|
+
constructor(opts) {
|
|
1532
|
+
const { compare, extract, required } = opts;
|
|
1533
|
+
this._propsToCompare = compare;
|
|
1534
|
+
this._propsToExtract = extract || compare;
|
|
1535
|
+
this._requiredProps = required;
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Checks if two sets of props need transition in between
|
|
1539
|
+
* @param currentProps {object} - a list of viewport props
|
|
1540
|
+
* @param nextProps {object} - a list of viewport props
|
|
1541
|
+
* @returns {bool} - true if two props are equivalent
|
|
1542
|
+
*/
|
|
1543
|
+
arePropsEqual(currentProps, nextProps) {
|
|
1544
|
+
for (const key of this._propsToCompare) {
|
|
1545
|
+
if (!(key in currentProps) || !(key in nextProps) || !(0, import_core5.equals)(currentProps[key], nextProps[key])) {
|
|
1546
|
+
return false;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
return true;
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Called before transition starts to validate/pre-process start and end props
|
|
1553
|
+
* @param startProps {object} - a list of starting viewport props
|
|
1554
|
+
* @param endProps {object} - a list of target viewport props
|
|
1555
|
+
* @returns {Object} {start, end} - start and end props to be passed
|
|
1556
|
+
* to `interpolateProps`
|
|
1557
|
+
*/
|
|
1558
|
+
initializeProps(startProps, endProps) {
|
|
1559
|
+
const startViewStateProps = {};
|
|
1560
|
+
const endViewStateProps = {};
|
|
1561
|
+
for (const key of this._propsToExtract) {
|
|
1562
|
+
if (key in startProps || key in endProps) {
|
|
1563
|
+
startViewStateProps[key] = startProps[key];
|
|
1564
|
+
endViewStateProps[key] = endProps[key];
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
this._checkRequiredProps(startViewStateProps);
|
|
1568
|
+
this._checkRequiredProps(endViewStateProps);
|
|
1569
|
+
return { start: startViewStateProps, end: endViewStateProps };
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* Returns transition duration
|
|
1573
|
+
* @param startProps {object} - a list of starting viewport props
|
|
1574
|
+
* @param endProps {object} - a list of target viewport props
|
|
1575
|
+
* @returns {Number} - transition duration in milliseconds
|
|
1576
|
+
*/
|
|
1577
|
+
getDuration(startProps, endProps) {
|
|
1578
|
+
return endProps.transitionDuration;
|
|
1579
|
+
}
|
|
1580
|
+
_checkRequiredProps(props) {
|
|
1581
|
+
if (!this._requiredProps) {
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
this._requiredProps.forEach((propName) => {
|
|
1585
|
+
const value = props[propName];
|
|
1586
|
+
assert(
|
|
1587
|
+
Number.isFinite(value) || Array.isArray(value),
|
|
1588
|
+
`${propName} is required for transition`
|
|
1589
|
+
);
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
};
|
|
1593
|
+
|
|
1594
|
+
// ../core/src/transitions/linear-interpolator.ts
|
|
1595
|
+
var import_core8 = require("@math.gl/core");
|
|
1596
|
+
|
|
1597
|
+
// ../core/src/viewports/globe-viewport.ts
|
|
1598
|
+
var import_core6 = require("@math.gl/core");
|
|
1599
|
+
var import_web_mercator3 = require("@math.gl/web-mercator");
|
|
1600
|
+
var import_web_mercator4 = require("@math.gl/web-mercator");
|
|
1601
|
+
var import_core7 = require("@math.gl/core");
|
|
1602
|
+
var DEGREES_TO_RADIANS2 = Math.PI / 180;
|
|
1603
|
+
var RADIANS_TO_DEGREES = 180 / Math.PI;
|
|
1604
|
+
var EARTH_RADIUS = 6370972;
|
|
1605
|
+
var GLOBE_RADIUS = 256;
|
|
1606
|
+
function getDistanceScales2() {
|
|
1607
|
+
const unitsPerMeter2 = GLOBE_RADIUS / EARTH_RADIUS;
|
|
1608
|
+
const unitsPerDegree = Math.PI / 180 * GLOBE_RADIUS;
|
|
1609
|
+
return {
|
|
1610
|
+
unitsPerMeter: [unitsPerMeter2, unitsPerMeter2, unitsPerMeter2],
|
|
1611
|
+
unitsPerMeter2: [0, 0, 0],
|
|
1612
|
+
metersPerUnit: [1 / unitsPerMeter2, 1 / unitsPerMeter2, 1 / unitsPerMeter2],
|
|
1613
|
+
unitsPerDegree: [unitsPerDegree, unitsPerDegree, unitsPerMeter2],
|
|
1614
|
+
unitsPerDegree2: [0, 0, 0],
|
|
1615
|
+
degreesPerUnit: [1 / unitsPerDegree, 1 / unitsPerDegree, 1 / unitsPerMeter2]
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
var GlobeViewport = class extends Viewport {
|
|
1619
|
+
constructor(opts = {}) {
|
|
1620
|
+
const {
|
|
1621
|
+
longitude = 0,
|
|
1622
|
+
zoom = 0,
|
|
1623
|
+
// Matches Maplibre defaults
|
|
1624
|
+
// https://github.com/maplibre/maplibre-gl-js/blob/f8ab4b48d59ab8fe7b068b102538793bbdd4c848/src/geo/projection/globe_transform.ts#L632-L633
|
|
1625
|
+
nearZMultiplier = 0.5,
|
|
1626
|
+
farZMultiplier = 1,
|
|
1627
|
+
resolution = 10
|
|
1628
|
+
} = opts;
|
|
1629
|
+
let { latitude = 0, height, altitude = 1.5, fovy } = opts;
|
|
1630
|
+
latitude = Math.max(Math.min(latitude, import_web_mercator4.MAX_LATITUDE), -import_web_mercator4.MAX_LATITUDE);
|
|
1631
|
+
height = height || 1;
|
|
1632
|
+
if (fovy) {
|
|
1633
|
+
altitude = (0, import_web_mercator3.fovyToAltitude)(fovy);
|
|
1634
|
+
} else {
|
|
1635
|
+
fovy = (0, import_web_mercator3.altitudeToFovy)(altitude);
|
|
1636
|
+
}
|
|
1637
|
+
const scale = Math.pow(2, zoom - zoomAdjust(latitude));
|
|
1638
|
+
const nearZ = opts.nearZ ?? nearZMultiplier;
|
|
1639
|
+
const farZ = opts.farZ ?? (altitude + GLOBE_RADIUS * 2 * scale / height) * farZMultiplier;
|
|
1640
|
+
const viewMatrix = new import_core6.Matrix4().lookAt({ eye: [0, -altitude, 0], up: [0, 0, 1] });
|
|
1641
|
+
viewMatrix.rotateX(latitude * DEGREES_TO_RADIANS2);
|
|
1642
|
+
viewMatrix.rotateZ(-longitude * DEGREES_TO_RADIANS2);
|
|
1643
|
+
viewMatrix.scale(scale / height);
|
|
1644
|
+
super({
|
|
1645
|
+
...opts,
|
|
1646
|
+
// x, y, width,
|
|
1647
|
+
height,
|
|
1648
|
+
// view matrix
|
|
1649
|
+
viewMatrix,
|
|
1650
|
+
longitude,
|
|
1651
|
+
latitude,
|
|
1652
|
+
zoom,
|
|
1653
|
+
// projection matrix parameters
|
|
1654
|
+
distanceScales: getDistanceScales2(),
|
|
1655
|
+
fovy,
|
|
1656
|
+
focalDistance: altitude,
|
|
1657
|
+
near: nearZ,
|
|
1658
|
+
far: farZ
|
|
1659
|
+
});
|
|
1660
|
+
this.scale = scale;
|
|
1661
|
+
this.latitude = latitude;
|
|
1662
|
+
this.longitude = longitude;
|
|
1663
|
+
this.fovy = fovy;
|
|
1664
|
+
this.resolution = resolution;
|
|
1665
|
+
}
|
|
1666
|
+
get projectionMode() {
|
|
1667
|
+
return PROJECTION_MODE.GLOBE;
|
|
1668
|
+
}
|
|
1669
|
+
getDistanceScales() {
|
|
1670
|
+
return this.distanceScales;
|
|
1671
|
+
}
|
|
1672
|
+
getBounds(options = {}) {
|
|
1673
|
+
const unprojectOption = { targetZ: options.z || 0 };
|
|
1674
|
+
const left = this.unproject([0, this.height / 2], unprojectOption);
|
|
1675
|
+
const top = this.unproject([this.width / 2, 0], unprojectOption);
|
|
1676
|
+
const right = this.unproject([this.width, this.height / 2], unprojectOption);
|
|
1677
|
+
const bottom = this.unproject([this.width / 2, this.height], unprojectOption);
|
|
1678
|
+
if (right[0] < this.longitude)
|
|
1679
|
+
right[0] += 360;
|
|
1680
|
+
if (left[0] > this.longitude)
|
|
1681
|
+
left[0] -= 360;
|
|
1682
|
+
return [
|
|
1683
|
+
Math.min(left[0], right[0], top[0], bottom[0]),
|
|
1684
|
+
Math.min(left[1], right[1], top[1], bottom[1]),
|
|
1685
|
+
Math.max(left[0], right[0], top[0], bottom[0]),
|
|
1686
|
+
Math.max(left[1], right[1], top[1], bottom[1])
|
|
1687
|
+
];
|
|
1688
|
+
}
|
|
1689
|
+
unproject(xyz, { topLeft = true, targetZ } = {}) {
|
|
1690
|
+
const [x, y, z] = xyz;
|
|
1691
|
+
const y2 = topLeft ? y : this.height - y;
|
|
1692
|
+
const { pixelUnprojectionMatrix } = this;
|
|
1693
|
+
let coord;
|
|
1694
|
+
if (Number.isFinite(z)) {
|
|
1695
|
+
coord = transformVector(pixelUnprojectionMatrix, [x, y2, z, 1]);
|
|
1696
|
+
} else {
|
|
1697
|
+
const coord0 = transformVector(pixelUnprojectionMatrix, [x, y2, -1, 1]);
|
|
1698
|
+
const coord1 = transformVector(pixelUnprojectionMatrix, [x, y2, 1, 1]);
|
|
1699
|
+
const lt = ((targetZ || 0) / EARTH_RADIUS + 1) * GLOBE_RADIUS;
|
|
1700
|
+
const lSqr = import_core7.vec3.sqrLen(import_core7.vec3.sub([], coord0, coord1));
|
|
1701
|
+
const l0Sqr = import_core7.vec3.sqrLen(coord0);
|
|
1702
|
+
const l1Sqr = import_core7.vec3.sqrLen(coord1);
|
|
1703
|
+
const sSqr = (4 * l0Sqr * l1Sqr - (lSqr - l0Sqr - l1Sqr) ** 2) / 16;
|
|
1704
|
+
const dSqr = 4 * sSqr / lSqr;
|
|
1705
|
+
const r0 = Math.sqrt(l0Sqr - dSqr);
|
|
1706
|
+
const dr = Math.sqrt(Math.max(0, lt * lt - dSqr));
|
|
1707
|
+
const t = (r0 - dr) / Math.sqrt(lSqr);
|
|
1708
|
+
coord = import_core7.vec3.lerp([], coord0, coord1, t);
|
|
1709
|
+
}
|
|
1710
|
+
const [X, Y, Z] = this.unprojectPosition(coord);
|
|
1711
|
+
if (Number.isFinite(z)) {
|
|
1712
|
+
return [X, Y, Z];
|
|
1713
|
+
}
|
|
1714
|
+
return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
|
|
1715
|
+
}
|
|
1716
|
+
projectPosition(xyz) {
|
|
1717
|
+
const [lng, lat, Z = 0] = xyz;
|
|
1718
|
+
const lambda = lng * DEGREES_TO_RADIANS2;
|
|
1719
|
+
const phi = lat * DEGREES_TO_RADIANS2;
|
|
1720
|
+
const cosPhi = Math.cos(phi);
|
|
1721
|
+
const D = (Z / EARTH_RADIUS + 1) * GLOBE_RADIUS;
|
|
1722
|
+
return [Math.sin(lambda) * cosPhi * D, -Math.cos(lambda) * cosPhi * D, Math.sin(phi) * D];
|
|
1723
|
+
}
|
|
1724
|
+
unprojectPosition(xyz) {
|
|
1725
|
+
const [x, y, z] = xyz;
|
|
1726
|
+
const D = import_core7.vec3.len(xyz);
|
|
1727
|
+
const phi = Math.asin(z / D);
|
|
1728
|
+
const lambda = Math.atan2(x, -y);
|
|
1729
|
+
const lng = lambda * RADIANS_TO_DEGREES;
|
|
1730
|
+
const lat = phi * RADIANS_TO_DEGREES;
|
|
1731
|
+
const Z = (D / GLOBE_RADIUS - 1) * EARTH_RADIUS;
|
|
1732
|
+
return [lng, lat, Z];
|
|
1733
|
+
}
|
|
1734
|
+
projectFlat(xyz) {
|
|
1735
|
+
return xyz;
|
|
1736
|
+
}
|
|
1737
|
+
unprojectFlat(xyz) {
|
|
1738
|
+
return xyz;
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Pan the globe using delta-based movement
|
|
1742
|
+
* @param coords - the geographic coordinates where the pan started
|
|
1743
|
+
* @param pixel - the current screen position
|
|
1744
|
+
* @param startPixel - the screen position where the pan started
|
|
1745
|
+
* @returns updated viewport options with new longitude/latitude
|
|
1746
|
+
*/
|
|
1747
|
+
panByPosition([startLng, startLat, startZoom], pixel, startPixel) {
|
|
1748
|
+
const scale = Math.pow(2, this.zoom - zoomAdjust(this.latitude));
|
|
1749
|
+
const rotationSpeed = 0.25 / scale;
|
|
1750
|
+
const longitude = startLng + rotationSpeed * (startPixel[0] - pixel[0]);
|
|
1751
|
+
let latitude = startLat - rotationSpeed * (startPixel[1] - pixel[1]);
|
|
1752
|
+
latitude = Math.max(Math.min(latitude, import_web_mercator4.MAX_LATITUDE), -import_web_mercator4.MAX_LATITUDE);
|
|
1753
|
+
const out = { longitude, latitude, zoom: startZoom - zoomAdjust(startLat) };
|
|
1754
|
+
out.zoom += zoomAdjust(out.latitude);
|
|
1755
|
+
return out;
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
GlobeViewport.displayName = "GlobeViewport";
|
|
1759
|
+
function zoomAdjust(latitude) {
|
|
1760
|
+
const scaleAdjust = Math.PI * Math.cos(latitude * Math.PI / 180);
|
|
1761
|
+
return Math.log2(scaleAdjust);
|
|
1762
|
+
}
|
|
1763
|
+
function transformVector(matrix, vector) {
|
|
1764
|
+
const result = import_core7.vec4.transformMat4([], vector, matrix);
|
|
1765
|
+
import_core7.vec4.scale(result, result, 1 / result[3]);
|
|
1766
|
+
return result;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
// ../core/src/transitions/linear-interpolator.ts
|
|
1770
|
+
var DEFAULT_PROPS = ["longitude", "latitude", "zoom", "bearing", "pitch"];
|
|
1771
|
+
var DEFAULT_REQUIRED_PROPS = ["longitude", "latitude", "zoom"];
|
|
1772
|
+
var LinearInterpolator = class extends TransitionInterpolator {
|
|
1773
|
+
/**
|
|
1774
|
+
* @param {Object} opts
|
|
1775
|
+
* @param {Array} opts.transitionProps - list of props to apply linear transition to.
|
|
1776
|
+
* @param {Array} opts.around - a screen point to zoom/rotate around.
|
|
1777
|
+
* @param {Function} opts.makeViewport - construct a viewport instance with given props.
|
|
1778
|
+
*/
|
|
1779
|
+
constructor(opts = {}) {
|
|
1780
|
+
const transitionProps = Array.isArray(opts) ? opts : opts.transitionProps;
|
|
1781
|
+
const normalizedOpts = Array.isArray(opts) ? {} : opts;
|
|
1782
|
+
normalizedOpts.transitionProps = Array.isArray(transitionProps) ? {
|
|
1783
|
+
compare: transitionProps,
|
|
1784
|
+
required: transitionProps
|
|
1785
|
+
} : transitionProps || {
|
|
1786
|
+
compare: DEFAULT_PROPS,
|
|
1787
|
+
required: DEFAULT_REQUIRED_PROPS
|
|
1788
|
+
};
|
|
1789
|
+
super(normalizedOpts.transitionProps);
|
|
1790
|
+
this.opts = normalizedOpts;
|
|
1791
|
+
}
|
|
1792
|
+
initializeProps(startProps, endProps) {
|
|
1793
|
+
const result = super.initializeProps(startProps, endProps);
|
|
1794
|
+
const { makeViewport, around } = this.opts;
|
|
1795
|
+
if (makeViewport && around) {
|
|
1796
|
+
const TestViewport = makeViewport(startProps);
|
|
1797
|
+
if (TestViewport instanceof GlobeViewport) {
|
|
1798
|
+
log_default.warn("around not supported in GlobeView")();
|
|
1799
|
+
} else {
|
|
1800
|
+
const startViewport = makeViewport(startProps);
|
|
1801
|
+
const endViewport = makeViewport(endProps);
|
|
1802
|
+
const aroundPosition = startViewport.unproject(around);
|
|
1803
|
+
result.start.around = around;
|
|
1804
|
+
Object.assign(result.end, {
|
|
1805
|
+
around: endViewport.project(aroundPosition),
|
|
1806
|
+
aroundPosition,
|
|
1807
|
+
width: endProps.width,
|
|
1808
|
+
height: endProps.height
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
return result;
|
|
1813
|
+
}
|
|
1814
|
+
interpolateProps(startProps, endProps, t) {
|
|
1815
|
+
const propsInTransition = {};
|
|
1816
|
+
for (const key of this._propsToExtract) {
|
|
1817
|
+
propsInTransition[key] = (0, import_core8.lerp)(startProps[key] || 0, endProps[key] || 0, t);
|
|
1818
|
+
}
|
|
1819
|
+
if (endProps.aroundPosition && this.opts.makeViewport) {
|
|
1820
|
+
const viewport = this.opts.makeViewport({ ...endProps, ...propsInTransition });
|
|
1821
|
+
Object.assign(
|
|
1822
|
+
propsInTransition,
|
|
1823
|
+
viewport.panByPosition(
|
|
1824
|
+
endProps.aroundPosition,
|
|
1825
|
+
// anchor point in current screen coordinates
|
|
1826
|
+
(0, import_core8.lerp)(startProps.around, endProps.around, t)
|
|
1827
|
+
)
|
|
1828
|
+
);
|
|
1829
|
+
}
|
|
1830
|
+
return propsInTransition;
|
|
1831
|
+
}
|
|
1832
|
+
};
|
|
1833
|
+
|
|
1834
|
+
// ../core/src/controllers/controller.ts
|
|
1835
|
+
var NO_TRANSITION_PROPS = {
|
|
1836
|
+
transitionDuration: 0
|
|
1837
|
+
};
|
|
1838
|
+
var DEFAULT_INERTIA = 300;
|
|
1839
|
+
var INERTIA_EASING = (t) => 1 - (1 - t) * (1 - t);
|
|
1840
|
+
var EVENT_TYPES = {
|
|
1841
|
+
WHEEL: ["wheel"],
|
|
1842
|
+
PAN: ["panstart", "panmove", "panend"],
|
|
1843
|
+
PINCH: ["pinchstart", "pinchmove", "pinchend"],
|
|
1844
|
+
MULTI_PAN: ["multipanstart", "multipanmove", "multipanend"],
|
|
1845
|
+
DOUBLE_CLICK: ["dblclick"],
|
|
1846
|
+
KEYBOARD: ["keydown"]
|
|
1847
|
+
};
|
|
1848
|
+
var pinchEventWorkaround = {};
|
|
1849
|
+
var Controller = class {
|
|
1850
|
+
constructor(opts) {
|
|
1851
|
+
this.state = {};
|
|
1852
|
+
this._events = {};
|
|
1853
|
+
this._interactionState = {
|
|
1854
|
+
isDragging: false
|
|
1855
|
+
};
|
|
1856
|
+
this._customEvents = [];
|
|
1857
|
+
this._eventStartBlocked = null;
|
|
1858
|
+
this._panMove = false;
|
|
1859
|
+
this.invertPan = false;
|
|
1860
|
+
this.dragMode = "rotate";
|
|
1861
|
+
this.inertia = 0;
|
|
1862
|
+
this.scrollZoom = true;
|
|
1863
|
+
this.dragPan = true;
|
|
1864
|
+
this.dragRotate = true;
|
|
1865
|
+
this.doubleClickZoom = true;
|
|
1866
|
+
this.touchZoom = true;
|
|
1867
|
+
this.touchRotate = false;
|
|
1868
|
+
this.keyboard = true;
|
|
1869
|
+
this.transitionManager = new TransitionManager({
|
|
1870
|
+
...opts,
|
|
1871
|
+
getControllerState: (props) => new this.ControllerState(props),
|
|
1872
|
+
onViewStateChange: this._onTransition.bind(this),
|
|
1873
|
+
onStateChange: this._setInteractionState.bind(this)
|
|
1874
|
+
});
|
|
1875
|
+
this.handleEvent = this.handleEvent.bind(this);
|
|
1876
|
+
this.eventManager = opts.eventManager;
|
|
1877
|
+
this.onViewStateChange = opts.onViewStateChange || (() => {
|
|
1878
|
+
});
|
|
1879
|
+
this.onStateChange = opts.onStateChange || (() => {
|
|
1880
|
+
});
|
|
1881
|
+
this.makeViewport = opts.makeViewport;
|
|
1882
|
+
this.pickPosition = opts.pickPosition;
|
|
1883
|
+
}
|
|
1884
|
+
set events(customEvents) {
|
|
1885
|
+
this.toggleEvents(this._customEvents, false);
|
|
1886
|
+
this.toggleEvents(customEvents, true);
|
|
1887
|
+
this._customEvents = customEvents;
|
|
1888
|
+
if (this.props) {
|
|
1889
|
+
this.setProps(this.props);
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
finalize() {
|
|
1893
|
+
var _a;
|
|
1894
|
+
for (const eventName in this._events) {
|
|
1895
|
+
if (this._events[eventName]) {
|
|
1896
|
+
(_a = this.eventManager) == null ? void 0 : _a.off(eventName, this.handleEvent);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
this.transitionManager.finalize();
|
|
1900
|
+
}
|
|
1901
|
+
/**
|
|
1902
|
+
* Callback for events
|
|
1903
|
+
*/
|
|
1904
|
+
handleEvent(event) {
|
|
1905
|
+
this._controllerState = void 0;
|
|
1906
|
+
const eventStartBlocked = this._eventStartBlocked;
|
|
1907
|
+
switch (event.type) {
|
|
1908
|
+
case "panstart":
|
|
1909
|
+
return eventStartBlocked ? false : this._onPanStart(event);
|
|
1910
|
+
case "panmove":
|
|
1911
|
+
return this._onPan(event);
|
|
1912
|
+
case "panend":
|
|
1913
|
+
return this._onPanEnd(event);
|
|
1914
|
+
case "pinchstart":
|
|
1915
|
+
return eventStartBlocked ? false : this._onPinchStart(event);
|
|
1916
|
+
case "pinchmove":
|
|
1917
|
+
return this._onPinch(event);
|
|
1918
|
+
case "pinchend":
|
|
1919
|
+
return this._onPinchEnd(event);
|
|
1920
|
+
case "multipanstart":
|
|
1921
|
+
return eventStartBlocked ? false : this._onMultiPanStart(event);
|
|
1922
|
+
case "multipanmove":
|
|
1923
|
+
return this._onMultiPan(event);
|
|
1924
|
+
case "multipanend":
|
|
1925
|
+
return this._onMultiPanEnd(event);
|
|
1926
|
+
case "dblclick":
|
|
1927
|
+
return this._onDoubleClick(event);
|
|
1928
|
+
case "wheel":
|
|
1929
|
+
return this._onWheel(event);
|
|
1930
|
+
case "keydown":
|
|
1931
|
+
return this._onKeyDown(event);
|
|
1932
|
+
default:
|
|
1933
|
+
return false;
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
/* Event utils */
|
|
1937
|
+
// Event object: http://hammerjs.github.io/api/#event-object
|
|
1938
|
+
get controllerState() {
|
|
1939
|
+
this._controllerState = this._controllerState || new this.ControllerState({
|
|
1940
|
+
makeViewport: this.makeViewport,
|
|
1941
|
+
...this.props,
|
|
1942
|
+
...this.state
|
|
1943
|
+
});
|
|
1944
|
+
return this._controllerState;
|
|
1945
|
+
}
|
|
1946
|
+
getCenter(event) {
|
|
1947
|
+
const { x, y } = this.props;
|
|
1948
|
+
const { offsetCenter } = event;
|
|
1949
|
+
return [offsetCenter.x - x, offsetCenter.y - y];
|
|
1950
|
+
}
|
|
1951
|
+
isPointInBounds(pos, event) {
|
|
1952
|
+
const { width, height } = this.props;
|
|
1953
|
+
if (event && event.handled) {
|
|
1954
|
+
return false;
|
|
1955
|
+
}
|
|
1956
|
+
const inside = pos[0] >= 0 && pos[0] <= width && pos[1] >= 0 && pos[1] <= height;
|
|
1957
|
+
if (inside && event) {
|
|
1958
|
+
event.stopPropagation();
|
|
1959
|
+
}
|
|
1960
|
+
return inside;
|
|
1961
|
+
}
|
|
1962
|
+
isFunctionKeyPressed(event) {
|
|
1963
|
+
const { srcEvent } = event;
|
|
1964
|
+
return Boolean(srcEvent.metaKey || srcEvent.altKey || srcEvent.ctrlKey || srcEvent.shiftKey);
|
|
1965
|
+
}
|
|
1966
|
+
isDragging() {
|
|
1967
|
+
return this._interactionState.isDragging || false;
|
|
1968
|
+
}
|
|
1969
|
+
// When a multi-touch event ends, e.g. pinch, not all pointers are lifted at the same time.
|
|
1970
|
+
// This triggers a brief `pan` event.
|
|
1971
|
+
// Calling this method will temporarily disable *start events to avoid conflicting transitions.
|
|
1972
|
+
blockEvents(timeout) {
|
|
1973
|
+
const timer = setTimeout(() => {
|
|
1974
|
+
if (this._eventStartBlocked === timer) {
|
|
1975
|
+
this._eventStartBlocked = null;
|
|
1976
|
+
}
|
|
1977
|
+
}, timeout);
|
|
1978
|
+
this._eventStartBlocked = timer;
|
|
1979
|
+
}
|
|
1980
|
+
/**
|
|
1981
|
+
* Extract interactivity options
|
|
1982
|
+
*/
|
|
1983
|
+
setProps(props) {
|
|
1984
|
+
if (props.dragMode) {
|
|
1985
|
+
this.dragMode = props.dragMode;
|
|
1986
|
+
}
|
|
1987
|
+
const oldProps = this.props;
|
|
1988
|
+
this.props = props;
|
|
1989
|
+
if (!("transitionInterpolator" in props)) {
|
|
1990
|
+
props.transitionInterpolator = this._getTransitionProps().transitionInterpolator;
|
|
1991
|
+
}
|
|
1992
|
+
this.transitionManager.processViewStateChange(props);
|
|
1993
|
+
const { inertia } = props;
|
|
1994
|
+
this.inertia = Number.isFinite(inertia) ? inertia : inertia === true ? DEFAULT_INERTIA : 0;
|
|
1995
|
+
const {
|
|
1996
|
+
scrollZoom = true,
|
|
1997
|
+
dragPan = true,
|
|
1998
|
+
dragRotate = true,
|
|
1999
|
+
doubleClickZoom = true,
|
|
2000
|
+
touchZoom = true,
|
|
2001
|
+
touchRotate = false,
|
|
2002
|
+
keyboard = true
|
|
2003
|
+
} = props;
|
|
2004
|
+
const isInteractive = Boolean(this.onViewStateChange);
|
|
2005
|
+
this.toggleEvents(EVENT_TYPES.WHEEL, isInteractive && scrollZoom);
|
|
2006
|
+
this.toggleEvents(EVENT_TYPES.PAN, isInteractive);
|
|
2007
|
+
this.toggleEvents(EVENT_TYPES.PINCH, isInteractive && (touchZoom || touchRotate));
|
|
2008
|
+
this.toggleEvents(EVENT_TYPES.MULTI_PAN, isInteractive && touchRotate);
|
|
2009
|
+
this.toggleEvents(EVENT_TYPES.DOUBLE_CLICK, isInteractive && doubleClickZoom);
|
|
2010
|
+
this.toggleEvents(EVENT_TYPES.KEYBOARD, isInteractive && keyboard);
|
|
2011
|
+
this.scrollZoom = scrollZoom;
|
|
2012
|
+
this.dragPan = dragPan;
|
|
2013
|
+
this.dragRotate = dragRotate;
|
|
2014
|
+
this.doubleClickZoom = doubleClickZoom;
|
|
2015
|
+
this.touchZoom = touchZoom;
|
|
2016
|
+
this.touchRotate = touchRotate;
|
|
2017
|
+
this.keyboard = keyboard;
|
|
2018
|
+
const dimensionChanged = !oldProps || oldProps.height !== props.height || oldProps.width !== props.width || oldProps.maxBounds !== props.maxBounds;
|
|
2019
|
+
if (dimensionChanged && props.maxBounds) {
|
|
2020
|
+
const controllerState = new this.ControllerState({ ...props, makeViewport: this.makeViewport });
|
|
2021
|
+
const normalizedProps = controllerState.getViewportProps();
|
|
2022
|
+
const changed = Object.keys(normalizedProps).some((key) => !deepEqual(normalizedProps[key], props[key], 1));
|
|
2023
|
+
if (changed) {
|
|
2024
|
+
this.updateViewport(controllerState);
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
updateTransition() {
|
|
2029
|
+
this.transitionManager.updateTransition();
|
|
2030
|
+
}
|
|
2031
|
+
toggleEvents(eventNames, enabled) {
|
|
2032
|
+
if (this.eventManager) {
|
|
2033
|
+
eventNames.forEach((eventName) => {
|
|
2034
|
+
if (this._events[eventName] !== enabled) {
|
|
2035
|
+
this._events[eventName] = enabled;
|
|
2036
|
+
if (enabled) {
|
|
2037
|
+
this.eventManager.on(eventName, this.handleEvent);
|
|
2038
|
+
} else {
|
|
2039
|
+
this.eventManager.off(eventName, this.handleEvent);
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
// Private Methods
|
|
2046
|
+
/* Callback util */
|
|
2047
|
+
// formats map state and invokes callback function
|
|
2048
|
+
updateViewport(newControllerState, extraProps = null, interactionState = {}) {
|
|
2049
|
+
const viewState = { ...newControllerState.getViewportProps(), ...extraProps };
|
|
2050
|
+
const changed = this.controllerState !== newControllerState;
|
|
2051
|
+
this.state = newControllerState.getState();
|
|
2052
|
+
this._setInteractionState(interactionState);
|
|
2053
|
+
if (changed) {
|
|
2054
|
+
const oldViewState = this.controllerState && this.controllerState.getViewportProps();
|
|
2055
|
+
if (this.onViewStateChange) {
|
|
2056
|
+
this.onViewStateChange({ viewState, interactionState: this._interactionState, oldViewState, viewId: this.props.id });
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
_onTransition(params) {
|
|
2061
|
+
this.onViewStateChange({ ...params, interactionState: this._interactionState, viewId: this.props.id });
|
|
2062
|
+
}
|
|
2063
|
+
_setInteractionState(newStates) {
|
|
2064
|
+
Object.assign(this._interactionState, newStates);
|
|
2065
|
+
this.onStateChange(this._interactionState);
|
|
2066
|
+
}
|
|
2067
|
+
/* Event handlers */
|
|
2068
|
+
// Default handler for the `panstart` event.
|
|
2069
|
+
_onPanStart(event) {
|
|
2070
|
+
const pos = this.getCenter(event);
|
|
2071
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
2072
|
+
return false;
|
|
2073
|
+
}
|
|
2074
|
+
let alternateMode = this.isFunctionKeyPressed(event) || event.rightButton || false;
|
|
2075
|
+
if (this.invertPan || this.dragMode === "pan") {
|
|
2076
|
+
alternateMode = !alternateMode;
|
|
2077
|
+
}
|
|
2078
|
+
const newControllerState = this.controllerState[alternateMode ? "panStart" : "rotateStart"]({
|
|
2079
|
+
pos
|
|
2080
|
+
});
|
|
2081
|
+
this._panMove = alternateMode;
|
|
2082
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
|
|
2083
|
+
return true;
|
|
2084
|
+
}
|
|
2085
|
+
// Default handler for the `panmove` and `panend` event.
|
|
2086
|
+
_onPan(event) {
|
|
2087
|
+
if (!this.isDragging()) {
|
|
2088
|
+
return false;
|
|
2089
|
+
}
|
|
2090
|
+
return this._panMove ? this._onPanMove(event) : this._onPanRotate(event);
|
|
2091
|
+
}
|
|
2092
|
+
_onPanEnd(event) {
|
|
2093
|
+
if (!this.isDragging()) {
|
|
2094
|
+
return false;
|
|
2095
|
+
}
|
|
2096
|
+
return this._panMove ? this._onPanMoveEnd(event) : this._onPanRotateEnd(event);
|
|
2097
|
+
}
|
|
2098
|
+
// Default handler for panning to move.
|
|
2099
|
+
// Called by `_onPan` when panning without function key pressed.
|
|
2100
|
+
_onPanMove(event) {
|
|
2101
|
+
if (!this.dragPan) {
|
|
2102
|
+
return false;
|
|
2103
|
+
}
|
|
2104
|
+
const pos = this.getCenter(event);
|
|
2105
|
+
const newControllerState = this.controllerState.pan({ pos });
|
|
2106
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
2107
|
+
isDragging: true,
|
|
2108
|
+
isPanning: true
|
|
2109
|
+
});
|
|
2110
|
+
return true;
|
|
2111
|
+
}
|
|
2112
|
+
_onPanMoveEnd(event) {
|
|
2113
|
+
const { inertia } = this;
|
|
2114
|
+
if (this.dragPan && inertia && event.velocity) {
|
|
2115
|
+
const pos = this.getCenter(event);
|
|
2116
|
+
const endPos = [
|
|
2117
|
+
pos[0] + event.velocityX * inertia / 2,
|
|
2118
|
+
pos[1] + event.velocityY * inertia / 2
|
|
2119
|
+
];
|
|
2120
|
+
const newControllerState = this.controllerState.pan({ pos: endPos }).panEnd();
|
|
2121
|
+
this.updateViewport(
|
|
2122
|
+
newControllerState,
|
|
2123
|
+
{
|
|
2124
|
+
...this._getTransitionProps(),
|
|
2125
|
+
transitionDuration: inertia,
|
|
2126
|
+
transitionEasing: INERTIA_EASING
|
|
2127
|
+
},
|
|
2128
|
+
{
|
|
2129
|
+
isDragging: false,
|
|
2130
|
+
isPanning: true
|
|
2131
|
+
}
|
|
2132
|
+
);
|
|
2133
|
+
} else {
|
|
2134
|
+
const newControllerState = this.controllerState.panEnd();
|
|
2135
|
+
this.updateViewport(newControllerState, null, {
|
|
2136
|
+
isDragging: false,
|
|
2137
|
+
isPanning: false
|
|
2138
|
+
});
|
|
2139
|
+
}
|
|
2140
|
+
return true;
|
|
2141
|
+
}
|
|
2142
|
+
// Default handler for panning to rotate.
|
|
2143
|
+
// Called by `_onPan` when panning with function key pressed.
|
|
2144
|
+
_onPanRotate(event) {
|
|
2145
|
+
if (!this.dragRotate) {
|
|
2146
|
+
return false;
|
|
2147
|
+
}
|
|
2148
|
+
const pos = this.getCenter(event);
|
|
2149
|
+
const newControllerState = this.controllerState.rotate({ pos });
|
|
2150
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
2151
|
+
isDragging: true,
|
|
2152
|
+
isRotating: true
|
|
2153
|
+
});
|
|
2154
|
+
return true;
|
|
2155
|
+
}
|
|
2156
|
+
_onPanRotateEnd(event) {
|
|
2157
|
+
const { inertia } = this;
|
|
2158
|
+
if (this.dragRotate && inertia && event.velocity) {
|
|
2159
|
+
const pos = this.getCenter(event);
|
|
2160
|
+
const endPos = [
|
|
2161
|
+
pos[0] + event.velocityX * inertia / 2,
|
|
2162
|
+
pos[1] + event.velocityY * inertia / 2
|
|
2163
|
+
];
|
|
2164
|
+
const newControllerState = this.controllerState.rotate({ pos: endPos }).rotateEnd();
|
|
2165
|
+
this.updateViewport(
|
|
2166
|
+
newControllerState,
|
|
2167
|
+
{
|
|
2168
|
+
...this._getTransitionProps(),
|
|
2169
|
+
transitionDuration: inertia,
|
|
2170
|
+
transitionEasing: INERTIA_EASING
|
|
2171
|
+
},
|
|
2172
|
+
{
|
|
2173
|
+
isDragging: false,
|
|
2174
|
+
isRotating: true
|
|
2175
|
+
}
|
|
2176
|
+
);
|
|
2177
|
+
} else {
|
|
2178
|
+
const newControllerState = this.controllerState.rotateEnd();
|
|
2179
|
+
this.updateViewport(newControllerState, null, {
|
|
2180
|
+
isDragging: false,
|
|
2181
|
+
isRotating: false
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
return true;
|
|
2185
|
+
}
|
|
2186
|
+
// Default handler for the `wheel` event.
|
|
2187
|
+
_onWheel(event) {
|
|
2188
|
+
if (!this.scrollZoom) {
|
|
2189
|
+
return false;
|
|
2190
|
+
}
|
|
2191
|
+
const pos = this.getCenter(event);
|
|
2192
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
2193
|
+
return false;
|
|
2194
|
+
}
|
|
2195
|
+
event.srcEvent.preventDefault();
|
|
2196
|
+
const { speed = 0.01, smooth = false } = this.scrollZoom === true ? {} : this.scrollZoom;
|
|
2197
|
+
const { delta } = event;
|
|
2198
|
+
let scale = 2 / (1 + Math.exp(-Math.abs(delta * speed)));
|
|
2199
|
+
if (delta < 0 && scale !== 0) {
|
|
2200
|
+
scale = 1 / scale;
|
|
2201
|
+
}
|
|
2202
|
+
const transitionProps = smooth ? { ...this._getTransitionProps({ around: pos }), transitionDuration: 250 } : NO_TRANSITION_PROPS;
|
|
2203
|
+
const newControllerState = this.controllerState.zoom({ pos, scale });
|
|
2204
|
+
this.updateViewport(
|
|
2205
|
+
newControllerState,
|
|
2206
|
+
transitionProps,
|
|
2207
|
+
{
|
|
2208
|
+
isZooming: true,
|
|
2209
|
+
isPanning: true
|
|
2210
|
+
}
|
|
2211
|
+
);
|
|
2212
|
+
if (!smooth) {
|
|
2213
|
+
this._setInteractionState({ isZooming: false, isPanning: false });
|
|
2214
|
+
}
|
|
2215
|
+
return true;
|
|
2216
|
+
}
|
|
2217
|
+
_onMultiPanStart(event) {
|
|
2218
|
+
const pos = this.getCenter(event);
|
|
2219
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
2220
|
+
return false;
|
|
2221
|
+
}
|
|
2222
|
+
const newControllerState = this.controllerState.rotateStart({ pos });
|
|
2223
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
|
|
2224
|
+
return true;
|
|
2225
|
+
}
|
|
2226
|
+
_onMultiPan(event) {
|
|
2227
|
+
if (!this.touchRotate) {
|
|
2228
|
+
return false;
|
|
2229
|
+
}
|
|
2230
|
+
if (!this.isDragging()) {
|
|
2231
|
+
return false;
|
|
2232
|
+
}
|
|
2233
|
+
const pos = this.getCenter(event);
|
|
2234
|
+
pos[0] -= event.deltaX;
|
|
2235
|
+
const newControllerState = this.controllerState.rotate({ pos });
|
|
2236
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
2237
|
+
isDragging: true,
|
|
2238
|
+
isRotating: true
|
|
2239
|
+
});
|
|
2240
|
+
return true;
|
|
2241
|
+
}
|
|
2242
|
+
_onMultiPanEnd(event) {
|
|
2243
|
+
if (!this.isDragging()) {
|
|
2244
|
+
return false;
|
|
2245
|
+
}
|
|
2246
|
+
const { inertia } = this;
|
|
2247
|
+
if (this.touchRotate && inertia && event.velocityY) {
|
|
2248
|
+
const pos = this.getCenter(event);
|
|
2249
|
+
const endPos = [pos[0], pos[1] += event.velocityY * inertia / 2];
|
|
2250
|
+
const newControllerState = this.controllerState.rotate({ pos: endPos });
|
|
2251
|
+
this.updateViewport(
|
|
2252
|
+
newControllerState,
|
|
2253
|
+
{
|
|
2254
|
+
...this._getTransitionProps(),
|
|
2255
|
+
transitionDuration: inertia,
|
|
2256
|
+
transitionEasing: INERTIA_EASING
|
|
2257
|
+
},
|
|
2258
|
+
{
|
|
2259
|
+
isDragging: false,
|
|
2260
|
+
isRotating: true
|
|
2261
|
+
}
|
|
2262
|
+
);
|
|
2263
|
+
this.blockEvents(inertia);
|
|
2264
|
+
} else {
|
|
2265
|
+
const newControllerState = this.controllerState.rotateEnd();
|
|
2266
|
+
this.updateViewport(newControllerState, null, {
|
|
2267
|
+
isDragging: false,
|
|
2268
|
+
isRotating: false
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2271
|
+
return true;
|
|
2272
|
+
}
|
|
2273
|
+
// Default handler for the `pinchstart` event.
|
|
2274
|
+
_onPinchStart(event) {
|
|
2275
|
+
const pos = this.getCenter(event);
|
|
2276
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
2277
|
+
return false;
|
|
2278
|
+
}
|
|
2279
|
+
const newControllerState = this.controllerState.zoomStart({ pos }).rotateStart({ pos });
|
|
2280
|
+
pinchEventWorkaround._startPinchRotation = event.rotation;
|
|
2281
|
+
pinchEventWorkaround._lastPinchEvent = event;
|
|
2282
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
|
|
2283
|
+
return true;
|
|
2284
|
+
}
|
|
2285
|
+
// Default handler for the `pinchmove` and `pinchend` events.
|
|
2286
|
+
_onPinch(event) {
|
|
2287
|
+
if (!this.touchZoom && !this.touchRotate) {
|
|
2288
|
+
return false;
|
|
2289
|
+
}
|
|
2290
|
+
if (!this.isDragging()) {
|
|
2291
|
+
return false;
|
|
2292
|
+
}
|
|
2293
|
+
let newControllerState = this.controllerState;
|
|
2294
|
+
if (this.touchZoom) {
|
|
2295
|
+
const { scale } = event;
|
|
2296
|
+
const pos = this.getCenter(event);
|
|
2297
|
+
newControllerState = newControllerState.zoom({ pos, scale });
|
|
2298
|
+
}
|
|
2299
|
+
if (this.touchRotate) {
|
|
2300
|
+
const { rotation } = event;
|
|
2301
|
+
newControllerState = newControllerState.rotate({
|
|
2302
|
+
deltaAngleX: pinchEventWorkaround._startPinchRotation - rotation
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
2306
|
+
isDragging: true,
|
|
2307
|
+
isPanning: this.touchZoom,
|
|
2308
|
+
isZooming: this.touchZoom,
|
|
2309
|
+
isRotating: this.touchRotate
|
|
2310
|
+
});
|
|
2311
|
+
pinchEventWorkaround._lastPinchEvent = event;
|
|
2312
|
+
return true;
|
|
2313
|
+
}
|
|
2314
|
+
_onPinchEnd(event) {
|
|
2315
|
+
if (!this.isDragging()) {
|
|
2316
|
+
return false;
|
|
2317
|
+
}
|
|
2318
|
+
const { inertia } = this;
|
|
2319
|
+
const { _lastPinchEvent } = pinchEventWorkaround;
|
|
2320
|
+
if (this.touchZoom && inertia && _lastPinchEvent && event.scale !== _lastPinchEvent.scale) {
|
|
2321
|
+
const pos = this.getCenter(event);
|
|
2322
|
+
let newControllerState = this.controllerState.rotateEnd();
|
|
2323
|
+
const z = Math.log2(event.scale);
|
|
2324
|
+
const velocityZ = (z - Math.log2(_lastPinchEvent.scale)) / (event.deltaTime - _lastPinchEvent.deltaTime);
|
|
2325
|
+
const endScale = Math.pow(2, z + velocityZ * inertia / 2);
|
|
2326
|
+
newControllerState = newControllerState.zoom({ pos, scale: endScale }).zoomEnd();
|
|
2327
|
+
this.updateViewport(
|
|
2328
|
+
newControllerState,
|
|
2329
|
+
{
|
|
2330
|
+
...this._getTransitionProps({ around: pos }),
|
|
2331
|
+
transitionDuration: inertia,
|
|
2332
|
+
transitionEasing: INERTIA_EASING
|
|
2333
|
+
},
|
|
2334
|
+
{
|
|
2335
|
+
isDragging: false,
|
|
2336
|
+
isPanning: this.touchZoom,
|
|
2337
|
+
isZooming: this.touchZoom,
|
|
2338
|
+
isRotating: false
|
|
2339
|
+
}
|
|
2340
|
+
);
|
|
2341
|
+
this.blockEvents(inertia);
|
|
2342
|
+
} else {
|
|
2343
|
+
const newControllerState = this.controllerState.zoomEnd().rotateEnd();
|
|
2344
|
+
this.updateViewport(newControllerState, null, {
|
|
2345
|
+
isDragging: false,
|
|
2346
|
+
isPanning: false,
|
|
2347
|
+
isZooming: false,
|
|
2348
|
+
isRotating: false
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2351
|
+
pinchEventWorkaround._startPinchRotation = null;
|
|
2352
|
+
pinchEventWorkaround._lastPinchEvent = null;
|
|
2353
|
+
return true;
|
|
2354
|
+
}
|
|
2355
|
+
// Default handler for the `dblclick` event.
|
|
2356
|
+
_onDoubleClick(event) {
|
|
2357
|
+
if (!this.doubleClickZoom) {
|
|
2358
|
+
return false;
|
|
2359
|
+
}
|
|
2360
|
+
const pos = this.getCenter(event);
|
|
2361
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
2362
|
+
return false;
|
|
2363
|
+
}
|
|
2364
|
+
const isZoomOut = this.isFunctionKeyPressed(event);
|
|
2365
|
+
const newControllerState = this.controllerState.zoom({ pos, scale: isZoomOut ? 0.5 : 2 });
|
|
2366
|
+
this.updateViewport(newControllerState, this._getTransitionProps({ around: pos }), {
|
|
2367
|
+
isZooming: true,
|
|
2368
|
+
isPanning: true
|
|
2369
|
+
});
|
|
2370
|
+
this.blockEvents(100);
|
|
2371
|
+
return true;
|
|
2372
|
+
}
|
|
2373
|
+
// Default handler for the `keydown` event
|
|
2374
|
+
_onKeyDown(event) {
|
|
2375
|
+
if (!this.keyboard) {
|
|
2376
|
+
return false;
|
|
2377
|
+
}
|
|
2378
|
+
const funcKey = this.isFunctionKeyPressed(event);
|
|
2379
|
+
const { zoomSpeed, moveSpeed, rotateSpeedX, rotateSpeedY } = this.keyboard === true ? {} : this.keyboard;
|
|
2380
|
+
const { controllerState } = this;
|
|
2381
|
+
let newControllerState;
|
|
2382
|
+
const interactionState = {};
|
|
2383
|
+
switch (event.srcEvent.code) {
|
|
2384
|
+
case "Minus":
|
|
2385
|
+
newControllerState = funcKey ? controllerState.zoomOut(zoomSpeed).zoomOut(zoomSpeed) : controllerState.zoomOut(zoomSpeed);
|
|
2386
|
+
interactionState.isZooming = true;
|
|
2387
|
+
break;
|
|
2388
|
+
case "Equal":
|
|
2389
|
+
newControllerState = funcKey ? controllerState.zoomIn(zoomSpeed).zoomIn(zoomSpeed) : controllerState.zoomIn(zoomSpeed);
|
|
2390
|
+
interactionState.isZooming = true;
|
|
2391
|
+
break;
|
|
2392
|
+
case "ArrowLeft":
|
|
2393
|
+
if (funcKey) {
|
|
2394
|
+
newControllerState = controllerState.rotateLeft(rotateSpeedX);
|
|
2395
|
+
interactionState.isRotating = true;
|
|
2396
|
+
} else {
|
|
2397
|
+
newControllerState = controllerState.moveLeft(moveSpeed);
|
|
2398
|
+
interactionState.isPanning = true;
|
|
2399
|
+
}
|
|
2400
|
+
break;
|
|
2401
|
+
case "ArrowRight":
|
|
2402
|
+
if (funcKey) {
|
|
2403
|
+
newControllerState = controllerState.rotateRight(rotateSpeedX);
|
|
2404
|
+
interactionState.isRotating = true;
|
|
2405
|
+
} else {
|
|
2406
|
+
newControllerState = controllerState.moveRight(moveSpeed);
|
|
2407
|
+
interactionState.isPanning = true;
|
|
2408
|
+
}
|
|
2409
|
+
break;
|
|
2410
|
+
case "ArrowUp":
|
|
2411
|
+
if (funcKey) {
|
|
2412
|
+
newControllerState = controllerState.rotateUp(rotateSpeedY);
|
|
2413
|
+
interactionState.isRotating = true;
|
|
2414
|
+
} else {
|
|
2415
|
+
newControllerState = controllerState.moveUp(moveSpeed);
|
|
2416
|
+
interactionState.isPanning = true;
|
|
2417
|
+
}
|
|
2418
|
+
break;
|
|
2419
|
+
case "ArrowDown":
|
|
2420
|
+
if (funcKey) {
|
|
2421
|
+
newControllerState = controllerState.rotateDown(rotateSpeedY);
|
|
2422
|
+
interactionState.isRotating = true;
|
|
2423
|
+
} else {
|
|
2424
|
+
newControllerState = controllerState.moveDown(moveSpeed);
|
|
2425
|
+
interactionState.isPanning = true;
|
|
2426
|
+
}
|
|
2427
|
+
break;
|
|
2428
|
+
default:
|
|
2429
|
+
return false;
|
|
2430
|
+
}
|
|
2431
|
+
this.updateViewport(newControllerState, this._getTransitionProps(), interactionState);
|
|
2432
|
+
return true;
|
|
2433
|
+
}
|
|
2434
|
+
_getTransitionProps(opts) {
|
|
2435
|
+
const { transition } = this;
|
|
2436
|
+
if (!transition || !transition.transitionInterpolator) {
|
|
2437
|
+
return NO_TRANSITION_PROPS;
|
|
2438
|
+
}
|
|
2439
|
+
return opts ? {
|
|
2440
|
+
...transition,
|
|
2441
|
+
transitionInterpolator: new LinearInterpolator({
|
|
2442
|
+
...opts,
|
|
2443
|
+
...transition.transitionInterpolator.opts,
|
|
2444
|
+
makeViewport: this.controllerState.makeViewport
|
|
2445
|
+
})
|
|
2446
|
+
} : transition;
|
|
2447
|
+
}
|
|
2448
|
+
};
|
|
2449
|
+
|
|
2450
|
+
// ../core/src/controllers/view-state.ts
|
|
2451
|
+
var ViewState = class {
|
|
2452
|
+
constructor(props, state, makeViewport) {
|
|
2453
|
+
this.makeViewport = makeViewport;
|
|
2454
|
+
this._viewportProps = this.applyConstraints(props);
|
|
2455
|
+
this._state = state;
|
|
2456
|
+
}
|
|
2457
|
+
getViewportProps() {
|
|
2458
|
+
return this._viewportProps;
|
|
2459
|
+
}
|
|
2460
|
+
getState() {
|
|
2461
|
+
return this._state;
|
|
2462
|
+
}
|
|
2463
|
+
};
|
|
2464
|
+
|
|
2465
|
+
// ../core/src/controllers/map-controller.ts
|
|
2466
|
+
var import_web_mercator5 = require("@math.gl/web-mercator");
|
|
2467
|
+
var PITCH_MOUSE_THRESHOLD = 5;
|
|
2468
|
+
var PITCH_ACCEL = 1.2;
|
|
2469
|
+
var WEB_MERCATOR_TILE_SIZE = 512;
|
|
2470
|
+
var WEB_MERCATOR_MAX_BOUNDS = [
|
|
2471
|
+
[-Infinity, -90],
|
|
2472
|
+
[Infinity, 90]
|
|
2473
|
+
];
|
|
2474
|
+
function lngLatToWorld2([lng, lat]) {
|
|
2475
|
+
if (Math.abs(lat) > 90) {
|
|
2476
|
+
lat = Math.sign(lat) * 90;
|
|
2477
|
+
}
|
|
2478
|
+
if (Number.isFinite(lng)) {
|
|
2479
|
+
const [x, y2] = (0, import_web_mercator5.lngLatToWorld)([lng, lat]);
|
|
2480
|
+
return [x, (0, import_core9.clamp)(y2, 0, WEB_MERCATOR_TILE_SIZE)];
|
|
2481
|
+
}
|
|
2482
|
+
const [, y] = (0, import_web_mercator5.lngLatToWorld)([0, lat]);
|
|
2483
|
+
return [lng, (0, import_core9.clamp)(y, 0, WEB_MERCATOR_TILE_SIZE)];
|
|
2484
|
+
}
|
|
2485
|
+
var MapState = class extends ViewState {
|
|
2486
|
+
constructor(options) {
|
|
2487
|
+
const {
|
|
2488
|
+
/** Mapbox viewport properties */
|
|
2489
|
+
/** The width of the viewport */
|
|
2490
|
+
width,
|
|
2491
|
+
/** The height of the viewport */
|
|
2492
|
+
height,
|
|
2493
|
+
/** The latitude at the center of the viewport */
|
|
2494
|
+
latitude,
|
|
2495
|
+
/** The longitude at the center of the viewport */
|
|
2496
|
+
longitude,
|
|
2497
|
+
/** The tile zoom level of the map. */
|
|
2498
|
+
zoom,
|
|
2499
|
+
/** The bearing of the viewport in degrees */
|
|
2500
|
+
bearing = 0,
|
|
2501
|
+
/** The pitch of the viewport in degrees */
|
|
2502
|
+
pitch = 0,
|
|
2503
|
+
/**
|
|
2504
|
+
* Specify the altitude of the viewport camera
|
|
2505
|
+
* Unit: map heights, default 1.5
|
|
2506
|
+
* Non-public API, see https://github.com/mapbox/mapbox-gl-js/issues/1137
|
|
2507
|
+
*/
|
|
2508
|
+
altitude = 1.5,
|
|
2509
|
+
/** Viewport position */
|
|
2510
|
+
position = [0, 0, 0],
|
|
2511
|
+
/** Viewport constraints */
|
|
2512
|
+
maxZoom = 20,
|
|
2513
|
+
minZoom = 0,
|
|
2514
|
+
maxPitch = 60,
|
|
2515
|
+
minPitch = 0,
|
|
2516
|
+
/** Interaction states, required to calculate change during transform */
|
|
2517
|
+
/* The point on map being grabbed when the operation first started */
|
|
2518
|
+
startPanLngLat,
|
|
2519
|
+
/* Center of the zoom when the operation first started */
|
|
2520
|
+
startZoomLngLat,
|
|
2521
|
+
/* Pointer position when rotation started */
|
|
2522
|
+
startRotatePos,
|
|
2523
|
+
/* The lng/lat point at the rotation pivot (where rotation started) */
|
|
2524
|
+
startRotateLngLat,
|
|
2525
|
+
/** Bearing when current perspective rotate operation started */
|
|
2526
|
+
startBearing,
|
|
2527
|
+
/** Pitch when current perspective rotate operation started */
|
|
2528
|
+
startPitch,
|
|
2529
|
+
/** Zoom when current zoom operation started */
|
|
2530
|
+
startZoom,
|
|
2531
|
+
/** Normalize viewport props to fit map height into viewport */
|
|
2532
|
+
normalize = true
|
|
2533
|
+
} = options;
|
|
2534
|
+
assert(Number.isFinite(longitude));
|
|
2535
|
+
assert(Number.isFinite(latitude));
|
|
2536
|
+
assert(Number.isFinite(zoom));
|
|
2537
|
+
const maxBounds = options.maxBounds || (normalize ? WEB_MERCATOR_MAX_BOUNDS : null);
|
|
2538
|
+
super(
|
|
2539
|
+
{
|
|
2540
|
+
width,
|
|
2541
|
+
height,
|
|
2542
|
+
latitude,
|
|
2543
|
+
longitude,
|
|
2544
|
+
zoom,
|
|
2545
|
+
bearing,
|
|
2546
|
+
pitch,
|
|
2547
|
+
altitude,
|
|
2548
|
+
maxZoom,
|
|
2549
|
+
minZoom,
|
|
2550
|
+
maxPitch,
|
|
2551
|
+
minPitch,
|
|
2552
|
+
normalize,
|
|
2553
|
+
position,
|
|
2554
|
+
maxBounds
|
|
2555
|
+
},
|
|
2556
|
+
{
|
|
2557
|
+
startPanLngLat,
|
|
2558
|
+
startZoomLngLat,
|
|
2559
|
+
startRotatePos,
|
|
2560
|
+
startRotateLngLat,
|
|
2561
|
+
startBearing,
|
|
2562
|
+
startPitch,
|
|
2563
|
+
startZoom
|
|
2564
|
+
},
|
|
2565
|
+
options.makeViewport
|
|
2566
|
+
);
|
|
2567
|
+
this.getAltitude = options.getAltitude;
|
|
2568
|
+
}
|
|
2569
|
+
/**
|
|
2570
|
+
* Start panning
|
|
2571
|
+
* @param {[Number, Number]} pos - position on screen where the pointer grabs
|
|
2572
|
+
*/
|
|
2573
|
+
panStart({ pos }) {
|
|
2574
|
+
return this._getUpdatedState({
|
|
2575
|
+
startPanLngLat: this._unproject(pos)
|
|
2576
|
+
});
|
|
2577
|
+
}
|
|
2578
|
+
/**
|
|
2579
|
+
* Pan
|
|
2580
|
+
* @param {[Number, Number]} pos - position on screen where the pointer is
|
|
2581
|
+
* @param {[Number, Number], optional} startPos - where the pointer grabbed at
|
|
2582
|
+
* the start of the operation. Must be supplied of `panStart()` was not called
|
|
2583
|
+
*/
|
|
2584
|
+
pan({ pos, startPos }) {
|
|
2585
|
+
const startPanLngLat = this.getState().startPanLngLat || this._unproject(startPos);
|
|
2586
|
+
if (!startPanLngLat) {
|
|
2587
|
+
return this;
|
|
2588
|
+
}
|
|
2589
|
+
const viewport = this.makeViewport(this.getViewportProps());
|
|
2590
|
+
const newProps = viewport.panByPosition(startPanLngLat, pos);
|
|
2591
|
+
return this._getUpdatedState(newProps);
|
|
2592
|
+
}
|
|
2593
|
+
/**
|
|
2594
|
+
* End panning
|
|
2595
|
+
* Must call if `panStart()` was called
|
|
2596
|
+
*/
|
|
2597
|
+
panEnd() {
|
|
2598
|
+
return this._getUpdatedState({
|
|
2599
|
+
startPanLngLat: null
|
|
2600
|
+
});
|
|
2601
|
+
}
|
|
2602
|
+
/**
|
|
2603
|
+
* Start rotating
|
|
2604
|
+
* @param {[Number, Number]} pos - position on screen where the center is
|
|
2605
|
+
*/
|
|
2606
|
+
rotateStart({ pos }) {
|
|
2607
|
+
var _a;
|
|
2608
|
+
const altitude = (_a = this.getAltitude) == null ? void 0 : _a.call(this, pos);
|
|
2609
|
+
return this._getUpdatedState({
|
|
2610
|
+
startRotatePos: pos,
|
|
2611
|
+
startRotateLngLat: altitude !== void 0 ? this._unproject3D(pos, altitude) : void 0,
|
|
2612
|
+
startBearing: this.getViewportProps().bearing,
|
|
2613
|
+
startPitch: this.getViewportProps().pitch
|
|
2614
|
+
});
|
|
2615
|
+
}
|
|
2616
|
+
/**
|
|
2617
|
+
* Rotate
|
|
2618
|
+
* @param {[Number, Number]} pos - position on screen where the center is
|
|
2619
|
+
*/
|
|
2620
|
+
rotate({
|
|
2621
|
+
pos,
|
|
2622
|
+
deltaAngleX = 0,
|
|
2623
|
+
deltaAngleY = 0
|
|
2624
|
+
}) {
|
|
2625
|
+
const { startRotatePos, startRotateLngLat, startBearing, startPitch } = this.getState();
|
|
2626
|
+
if (!startRotatePos || startBearing === void 0 || startPitch === void 0) {
|
|
2627
|
+
return this;
|
|
2628
|
+
}
|
|
2629
|
+
let newRotation;
|
|
2630
|
+
if (pos) {
|
|
2631
|
+
newRotation = this._getNewRotation(pos, startRotatePos, startPitch, startBearing);
|
|
2632
|
+
} else {
|
|
2633
|
+
newRotation = {
|
|
2634
|
+
bearing: startBearing + deltaAngleX,
|
|
2635
|
+
pitch: startPitch + deltaAngleY
|
|
2636
|
+
};
|
|
2637
|
+
}
|
|
2638
|
+
if (startRotateLngLat) {
|
|
2639
|
+
const rotatedViewport = this.makeViewport({
|
|
2640
|
+
...this.getViewportProps(),
|
|
2641
|
+
...newRotation
|
|
2642
|
+
});
|
|
2643
|
+
const panMethod = "panByPosition3D" in rotatedViewport ? "panByPosition3D" : "panByPosition";
|
|
2644
|
+
return this._getUpdatedState({
|
|
2645
|
+
...newRotation,
|
|
2646
|
+
...rotatedViewport[panMethod](startRotateLngLat, startRotatePos)
|
|
2647
|
+
});
|
|
2648
|
+
}
|
|
2649
|
+
return this._getUpdatedState(newRotation);
|
|
2650
|
+
}
|
|
2651
|
+
/**
|
|
2652
|
+
* End rotating
|
|
2653
|
+
* Must call if `rotateStart()` was called
|
|
2654
|
+
*/
|
|
2655
|
+
rotateEnd() {
|
|
2656
|
+
return this._getUpdatedState({
|
|
2657
|
+
startRotatePos: null,
|
|
2658
|
+
startRotateLngLat: null,
|
|
2659
|
+
startBearing: null,
|
|
2660
|
+
startPitch: null
|
|
2661
|
+
});
|
|
2662
|
+
}
|
|
2663
|
+
/**
|
|
2664
|
+
* Start zooming
|
|
2665
|
+
* @param {[Number, Number]} pos - position on screen where the center is
|
|
2666
|
+
*/
|
|
2667
|
+
zoomStart({ pos }) {
|
|
2668
|
+
return this._getUpdatedState({
|
|
2669
|
+
startZoomLngLat: this._unproject(pos),
|
|
2670
|
+
startZoom: this.getViewportProps().zoom
|
|
2671
|
+
});
|
|
2672
|
+
}
|
|
2673
|
+
/**
|
|
2674
|
+
* Zoom
|
|
2675
|
+
* @param {[Number, Number]} pos - position on screen where the current center is
|
|
2676
|
+
* @param {[Number, Number]} startPos - the center position at
|
|
2677
|
+
* the start of the operation. Must be supplied of `zoomStart()` was not called
|
|
2678
|
+
* @param {Number} scale - a number between [0, 1] specifying the accumulated
|
|
2679
|
+
* relative scale.
|
|
2680
|
+
*/
|
|
2681
|
+
zoom({
|
|
2682
|
+
pos,
|
|
2683
|
+
startPos,
|
|
2684
|
+
scale
|
|
2685
|
+
}) {
|
|
2686
|
+
let { startZoom, startZoomLngLat } = this.getState();
|
|
2687
|
+
if (!startZoomLngLat) {
|
|
2688
|
+
startZoom = this.getViewportProps().zoom;
|
|
2689
|
+
startZoomLngLat = this._unproject(startPos) || this._unproject(pos);
|
|
2690
|
+
}
|
|
2691
|
+
if (!startZoomLngLat) {
|
|
2692
|
+
return this;
|
|
2693
|
+
}
|
|
2694
|
+
const zoom = this._constrainZoom(startZoom + Math.log2(scale));
|
|
2695
|
+
const zoomedViewport = this.makeViewport({ ...this.getViewportProps(), zoom });
|
|
2696
|
+
return this._getUpdatedState({
|
|
2697
|
+
zoom,
|
|
2698
|
+
...zoomedViewport.panByPosition(startZoomLngLat, pos)
|
|
2699
|
+
});
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* End zooming
|
|
2703
|
+
* Must call if `zoomStart()` was called
|
|
2704
|
+
*/
|
|
2705
|
+
zoomEnd() {
|
|
2706
|
+
return this._getUpdatedState({
|
|
2707
|
+
startZoomLngLat: null,
|
|
2708
|
+
startZoom: null
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
zoomIn(speed = 2) {
|
|
2712
|
+
return this._zoomFromCenter(speed);
|
|
2713
|
+
}
|
|
2714
|
+
zoomOut(speed = 2) {
|
|
2715
|
+
return this._zoomFromCenter(1 / speed);
|
|
2716
|
+
}
|
|
2717
|
+
moveLeft(speed = 100) {
|
|
2718
|
+
return this._panFromCenter([speed, 0]);
|
|
2719
|
+
}
|
|
2720
|
+
moveRight(speed = 100) {
|
|
2721
|
+
return this._panFromCenter([-speed, 0]);
|
|
2722
|
+
}
|
|
2723
|
+
moveUp(speed = 100) {
|
|
2724
|
+
return this._panFromCenter([0, speed]);
|
|
2725
|
+
}
|
|
2726
|
+
moveDown(speed = 100) {
|
|
2727
|
+
return this._panFromCenter([0, -speed]);
|
|
2728
|
+
}
|
|
2729
|
+
rotateLeft(speed = 15) {
|
|
2730
|
+
return this._getUpdatedState({
|
|
2731
|
+
bearing: this.getViewportProps().bearing - speed
|
|
2732
|
+
});
|
|
2733
|
+
}
|
|
2734
|
+
rotateRight(speed = 15) {
|
|
2735
|
+
return this._getUpdatedState({
|
|
2736
|
+
bearing: this.getViewportProps().bearing + speed
|
|
2737
|
+
});
|
|
2738
|
+
}
|
|
2739
|
+
rotateUp(speed = 10) {
|
|
2740
|
+
return this._getUpdatedState({
|
|
2741
|
+
pitch: this.getViewportProps().pitch + speed
|
|
2742
|
+
});
|
|
2743
|
+
}
|
|
2744
|
+
rotateDown(speed = 10) {
|
|
2745
|
+
return this._getUpdatedState({
|
|
2746
|
+
pitch: this.getViewportProps().pitch - speed
|
|
2747
|
+
});
|
|
2748
|
+
}
|
|
2749
|
+
shortestPathFrom(viewState) {
|
|
2750
|
+
const fromProps = viewState.getViewportProps();
|
|
2751
|
+
const props = { ...this.getViewportProps() };
|
|
2752
|
+
const { bearing, longitude } = props;
|
|
2753
|
+
if (Math.abs(bearing - fromProps.bearing) > 180) {
|
|
2754
|
+
props.bearing = bearing < 0 ? bearing + 360 : bearing - 360;
|
|
2755
|
+
}
|
|
2756
|
+
if (Math.abs(longitude - fromProps.longitude) > 180) {
|
|
2757
|
+
props.longitude = longitude < 0 ? longitude + 360 : longitude - 360;
|
|
2758
|
+
}
|
|
2759
|
+
return props;
|
|
2760
|
+
}
|
|
2761
|
+
// Apply any constraints (mathematical or defined by _viewportProps) to map state
|
|
2762
|
+
applyConstraints(props) {
|
|
2763
|
+
const { maxPitch, minPitch, pitch, longitude, bearing, normalize, maxBounds } = props;
|
|
2764
|
+
if (normalize) {
|
|
2765
|
+
if (longitude < -180 || longitude > 180) {
|
|
2766
|
+
props.longitude = mod(longitude + 180, 360) - 180;
|
|
2767
|
+
}
|
|
2768
|
+
if (bearing < -180 || bearing > 180) {
|
|
2769
|
+
props.bearing = mod(bearing + 180, 360) - 180;
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
props.pitch = (0, import_core9.clamp)(pitch, minPitch, maxPitch);
|
|
2773
|
+
props.zoom = this._constrainZoom(props.zoom, props);
|
|
2774
|
+
if (maxBounds) {
|
|
2775
|
+
const bl = lngLatToWorld2(maxBounds[0]);
|
|
2776
|
+
const tr = lngLatToWorld2(maxBounds[1]);
|
|
2777
|
+
const scale = 2 ** props.zoom;
|
|
2778
|
+
const halfWidth = props.width / 2 / scale;
|
|
2779
|
+
const halfHeight = props.height / 2 / scale;
|
|
2780
|
+
const [minLng, minLat] = (0, import_web_mercator5.worldToLngLat)([bl[0] + halfWidth, bl[1] + halfHeight]);
|
|
2781
|
+
const [maxLng, maxLat] = (0, import_web_mercator5.worldToLngLat)([tr[0] - halfWidth, tr[1] - halfHeight]);
|
|
2782
|
+
props.longitude = (0, import_core9.clamp)(props.longitude, minLng, maxLng);
|
|
2783
|
+
props.latitude = (0, import_core9.clamp)(props.latitude, minLat, maxLat);
|
|
2784
|
+
}
|
|
2785
|
+
return props;
|
|
2786
|
+
}
|
|
2787
|
+
/* Private methods */
|
|
2788
|
+
_constrainZoom(zoom, props) {
|
|
2789
|
+
props ||= this.getViewportProps();
|
|
2790
|
+
const { maxZoom, maxBounds } = props;
|
|
2791
|
+
const shouldApplyMaxBounds = maxBounds !== null && props.width > 0 && props.height > 0;
|
|
2792
|
+
let { minZoom } = props;
|
|
2793
|
+
if (shouldApplyMaxBounds) {
|
|
2794
|
+
const bl = lngLatToWorld2(maxBounds[0]);
|
|
2795
|
+
const tr = lngLatToWorld2(maxBounds[1]);
|
|
2796
|
+
const w = tr[0] - bl[0];
|
|
2797
|
+
const h = tr[1] - bl[1];
|
|
2798
|
+
if (Number.isFinite(w) && w > 0) {
|
|
2799
|
+
minZoom = Math.max(minZoom, Math.log2(props.width / w));
|
|
2800
|
+
}
|
|
2801
|
+
if (Number.isFinite(h) && h > 0) {
|
|
2802
|
+
minZoom = Math.max(minZoom, Math.log2(props.height / h));
|
|
2803
|
+
}
|
|
2804
|
+
if (minZoom > maxZoom)
|
|
2805
|
+
minZoom = maxZoom;
|
|
2806
|
+
}
|
|
2807
|
+
return (0, import_core9.clamp)(zoom, minZoom, maxZoom);
|
|
2808
|
+
}
|
|
2809
|
+
_zoomFromCenter(scale) {
|
|
2810
|
+
const { width, height } = this.getViewportProps();
|
|
2811
|
+
return this.zoom({
|
|
2812
|
+
pos: [width / 2, height / 2],
|
|
2813
|
+
scale
|
|
2814
|
+
});
|
|
2815
|
+
}
|
|
2816
|
+
_panFromCenter(offset) {
|
|
2817
|
+
const { width, height } = this.getViewportProps();
|
|
2818
|
+
return this.pan({
|
|
2819
|
+
startPos: [width / 2, height / 2],
|
|
2820
|
+
pos: [width / 2 + offset[0], height / 2 + offset[1]]
|
|
2821
|
+
});
|
|
2822
|
+
}
|
|
2823
|
+
_getUpdatedState(newProps) {
|
|
2824
|
+
return new this.constructor({
|
|
2825
|
+
makeViewport: this.makeViewport,
|
|
2826
|
+
...this.getViewportProps(),
|
|
2827
|
+
...this.getState(),
|
|
2828
|
+
...newProps
|
|
2829
|
+
});
|
|
2830
|
+
}
|
|
2831
|
+
_unproject(pos) {
|
|
2832
|
+
const viewport = this.makeViewport(this.getViewportProps());
|
|
2833
|
+
return pos && viewport.unproject(pos);
|
|
2834
|
+
}
|
|
2835
|
+
_unproject3D(pos, altitude) {
|
|
2836
|
+
const viewport = this.makeViewport(this.getViewportProps());
|
|
2837
|
+
return viewport.unproject(pos, { targetZ: altitude });
|
|
2838
|
+
}
|
|
2839
|
+
_getNewRotation(pos, startPos, startPitch, startBearing) {
|
|
2840
|
+
const deltaX = pos[0] - startPos[0];
|
|
2841
|
+
const deltaY = pos[1] - startPos[1];
|
|
2842
|
+
const centerY = pos[1];
|
|
2843
|
+
const startY = startPos[1];
|
|
2844
|
+
const { width, height } = this.getViewportProps();
|
|
2845
|
+
const deltaScaleX = deltaX / width;
|
|
2846
|
+
let deltaScaleY = 0;
|
|
2847
|
+
if (deltaY > 0) {
|
|
2848
|
+
if (Math.abs(height - startY) > PITCH_MOUSE_THRESHOLD) {
|
|
2849
|
+
deltaScaleY = deltaY / (startY - height) * PITCH_ACCEL;
|
|
2850
|
+
}
|
|
2851
|
+
} else if (deltaY < 0) {
|
|
2852
|
+
if (startY > PITCH_MOUSE_THRESHOLD) {
|
|
2853
|
+
deltaScaleY = 1 - centerY / startY;
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
deltaScaleY = (0, import_core9.clamp)(deltaScaleY, -1, 1);
|
|
2857
|
+
const { minPitch, maxPitch } = this.getViewportProps();
|
|
2858
|
+
const bearing = startBearing + 180 * deltaScaleX;
|
|
2859
|
+
let pitch = startPitch;
|
|
2860
|
+
if (deltaScaleY > 0) {
|
|
2861
|
+
pitch = startPitch + deltaScaleY * (maxPitch - startPitch);
|
|
2862
|
+
} else if (deltaScaleY < 0) {
|
|
2863
|
+
pitch = startPitch - deltaScaleY * (minPitch - startPitch);
|
|
2864
|
+
}
|
|
2865
|
+
return {
|
|
2866
|
+
pitch,
|
|
2867
|
+
bearing
|
|
2868
|
+
};
|
|
2869
|
+
}
|
|
2870
|
+
};
|
|
2871
|
+
var MapController = class extends Controller {
|
|
2872
|
+
constructor() {
|
|
2873
|
+
super(...arguments);
|
|
2874
|
+
this.ControllerState = MapState;
|
|
2875
|
+
this.transition = {
|
|
2876
|
+
transitionDuration: 300,
|
|
2877
|
+
transitionInterpolator: new LinearInterpolator({
|
|
2878
|
+
transitionProps: {
|
|
2879
|
+
compare: ["longitude", "latitude", "zoom", "bearing", "pitch", "position"],
|
|
2880
|
+
required: ["longitude", "latitude", "zoom"]
|
|
2881
|
+
}
|
|
2882
|
+
})
|
|
2883
|
+
};
|
|
2884
|
+
this.dragMode = "pan";
|
|
2885
|
+
/**
|
|
2886
|
+
* Rotation pivot behavior:
|
|
2887
|
+
* - 'center': Rotate around viewport center (default)
|
|
2888
|
+
* - '2d': Rotate around pointer position at ground level (z=0)
|
|
2889
|
+
* - '3d': Rotate around 3D picked point (requires pickPosition callback)
|
|
2890
|
+
*/
|
|
2891
|
+
this.rotationPivot = "center";
|
|
2892
|
+
/** Add altitude to rotateStart params based on rotationPivot mode */
|
|
2893
|
+
this._getAltitude = (pos) => {
|
|
2894
|
+
if (this.rotationPivot === "2d") {
|
|
2895
|
+
return 0;
|
|
2896
|
+
} else if (this.rotationPivot === "3d") {
|
|
2897
|
+
if (this.pickPosition) {
|
|
2898
|
+
const { x, y } = this.props;
|
|
2899
|
+
const pickResult = this.pickPosition(x + pos[0], y + pos[1]);
|
|
2900
|
+
if (pickResult && pickResult.coordinate && pickResult.coordinate.length >= 3) {
|
|
2901
|
+
return pickResult.coordinate[2];
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
return void 0;
|
|
2906
|
+
};
|
|
2907
|
+
}
|
|
2908
|
+
setProps(props) {
|
|
2909
|
+
if ("rotationPivot" in props) {
|
|
2910
|
+
this.rotationPivot = props.rotationPivot || "center";
|
|
2911
|
+
}
|
|
2912
|
+
props.getAltitude = this._getAltitude;
|
|
2913
|
+
props.position = props.position || [0, 0, 0];
|
|
2914
|
+
props.maxBounds = props.maxBounds || (props.normalize === false ? null : WEB_MERCATOR_MAX_BOUNDS);
|
|
2915
|
+
super.setProps(props);
|
|
2916
|
+
}
|
|
2917
|
+
updateViewport(newControllerState, extraProps = null, interactionState = {}) {
|
|
2918
|
+
const state = newControllerState.getState();
|
|
2919
|
+
if (interactionState.isDragging && state.startRotateLngLat) {
|
|
2920
|
+
interactionState = {
|
|
2921
|
+
...interactionState,
|
|
2922
|
+
rotationPivotPosition: state.startRotateLngLat
|
|
2923
|
+
};
|
|
2924
|
+
} else if (interactionState.isDragging === false) {
|
|
2925
|
+
interactionState = { ...interactionState, rotationPivotPosition: void 0 };
|
|
2926
|
+
}
|
|
2927
|
+
super.updateViewport(newControllerState, extraProps, interactionState);
|
|
2928
|
+
}
|
|
2929
|
+
};
|
|
2930
|
+
|
|
2931
|
+
// ../core/src/views/map-view.ts
|
|
2932
|
+
var MapView = class extends View {
|
|
2933
|
+
constructor(props = {}) {
|
|
2934
|
+
super(props);
|
|
2935
|
+
}
|
|
2936
|
+
getViewportType() {
|
|
2937
|
+
return WebMercatorViewport;
|
|
2938
|
+
}
|
|
2939
|
+
get ControllerType() {
|
|
2940
|
+
return MapController;
|
|
2941
|
+
}
|
|
2942
|
+
};
|
|
2943
|
+
MapView.displayName = "MapView";
|
|
2944
|
+
|
|
321
2945
|
// dist/deck-renderer.js
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
2946
|
+
var ARCGIS_WEB_MERCATOR_SCALE_AT_ZOOM_0 = 5916575505e-1;
|
|
2947
|
+
var DECK_GROUND_MPP_AT_ZOOM_0 = 78271.484;
|
|
2948
|
+
var METERS_PER_DEG_LAT = 111320;
|
|
2949
|
+
var ARCGIS_DIAGONAL_FOV_RADIANS = 55 * Math.PI / 180;
|
|
2950
|
+
var ALTITUDE_BLEND_START_TILT = 65;
|
|
2951
|
+
var ALTITUDE_BLEND_END_TILT = 80;
|
|
2952
|
+
function getDistanceMeters(a, b) {
|
|
2953
|
+
const midLatRad = (a.latitude + b.latitude) / 2 * Math.PI / 180;
|
|
2954
|
+
const dLatM = (a.latitude - b.latitude) * METERS_PER_DEG_LAT;
|
|
2955
|
+
const dLngM = (a.longitude - b.longitude) * METERS_PER_DEG_LAT * Math.cos(midLatRad);
|
|
2956
|
+
return Math.sqrt(dLatM * dLatM + dLngM * dLngM);
|
|
326
2957
|
}
|
|
327
|
-
function
|
|
2958
|
+
function getZoom(view, longitude, latitude, width, height) {
|
|
2959
|
+
const focalPoint = view.toMap({ x: width / 2, y: height / 2 });
|
|
2960
|
+
const focalPointRight = view.toMap({ x: width / 2 + 1, y: height / 2 });
|
|
2961
|
+
if (focalPoint && focalPointRight) {
|
|
2962
|
+
const horizontalMetersPerPixel = getDistanceMeters(focalPoint, focalPointRight);
|
|
2963
|
+
if (horizontalMetersPerPixel > 0) {
|
|
2964
|
+
const latitudeRad = latitude * Math.PI / 180;
|
|
2965
|
+
return Math.log2(DECK_GROUND_MPP_AT_ZOOM_0 * Math.cos(latitudeRad) / horizontalMetersPerPixel);
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
return Math.log2(ARCGIS_WEB_MERCATOR_SCALE_AT_ZOOM_0 / view.scale) - 1;
|
|
2969
|
+
}
|
|
2970
|
+
function smoothstep(edge0, edge1, value) {
|
|
2971
|
+
const t = Math.max(0, Math.min(1, (value - edge0) / (edge1 - edge0)));
|
|
2972
|
+
return t * t * (3 - 2 * t);
|
|
2973
|
+
}
|
|
2974
|
+
function getFovMatchedAltitude(width, height) {
|
|
2975
|
+
const aspect = width / height;
|
|
2976
|
+
const verticalTan = Math.tan(ARCGIS_DIAGONAL_FOV_RADIANS / 2) / Math.sqrt(1 + aspect * aspect);
|
|
2977
|
+
return 0.5 / verticalTan;
|
|
2978
|
+
}
|
|
2979
|
+
function getAltitude(tilt, slantAltitude, width, height) {
|
|
2980
|
+
const fovAltitude = getFovMatchedAltitude(width, height);
|
|
2981
|
+
const blend = smoothstep(ALTITUDE_BLEND_START_TILT, ALTITUDE_BLEND_END_TILT, tilt);
|
|
2982
|
+
return slantAltitude * (1 - blend) + fovAltitude * blend;
|
|
2983
|
+
}
|
|
2984
|
+
function getArcGISMatrixViewState(view, longitude, latitude, zoom, resolution, altitude) {
|
|
2985
|
+
return {
|
|
2986
|
+
views: new MapView({ id: "arcgis-scene" }),
|
|
2987
|
+
viewState: {
|
|
2988
|
+
"arcgis-scene": {
|
|
2989
|
+
id: "arcgis-scene",
|
|
2990
|
+
longitude,
|
|
2991
|
+
latitude,
|
|
2992
|
+
zoom,
|
|
2993
|
+
pitch: view.camera.tilt,
|
|
2994
|
+
bearing: view.camera.heading,
|
|
2995
|
+
altitude,
|
|
2996
|
+
position: [0, 0, 0],
|
|
2997
|
+
resolution
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
}
|
|
3002
|
+
function createDeckRenderer(DeckProps2, RenderNode2) {
|
|
328
3003
|
class DeckRenderer2 {
|
|
329
|
-
constructor(
|
|
3004
|
+
constructor(viewOrProps, props) {
|
|
330
3005
|
this.resources = null;
|
|
331
3006
|
this.cancelInitialization = null;
|
|
332
|
-
this.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (cancelled) {
|
|
341
|
-
finalizeResources(resources);
|
|
342
|
-
return;
|
|
3007
|
+
this.renderNode = null;
|
|
3008
|
+
if (viewOrProps && typeof viewOrProps === "object" && "view" in viewOrProps) {
|
|
3009
|
+
const { view, ...deckProps } = viewOrProps;
|
|
3010
|
+
this.view = view;
|
|
3011
|
+
this.deck = new DeckProps2(deckProps);
|
|
3012
|
+
} else {
|
|
3013
|
+
this.view = viewOrProps;
|
|
3014
|
+
this.deck = new DeckProps2(props);
|
|
343
3015
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
3016
|
+
let isInitializing = false;
|
|
3017
|
+
const self = this;
|
|
3018
|
+
const DeckRenderNode = RenderNode2.createSubclass({
|
|
3019
|
+
consumes: { required: ["composite-color"] },
|
|
3020
|
+
produces: "composite-color",
|
|
3021
|
+
initialize() {
|
|
3022
|
+
},
|
|
3023
|
+
render(inputs) {
|
|
3024
|
+
const renderNode = this;
|
|
3025
|
+
const passthrough = inputs.find((i) => i.name === "composite-color");
|
|
3026
|
+
if (!self.resources && !isInitializing) {
|
|
3027
|
+
const gl2 = renderNode.gl;
|
|
3028
|
+
if (gl2) {
|
|
3029
|
+
isInitializing = true;
|
|
3030
|
+
let cancelled = false;
|
|
3031
|
+
self.cancelInitialization = () => {
|
|
3032
|
+
cancelled = true;
|
|
3033
|
+
};
|
|
3034
|
+
initializeResources.call(self, gl2).then((resources) => {
|
|
3035
|
+
isInitializing = false;
|
|
3036
|
+
if (cancelled) {
|
|
3037
|
+
finalizeResources(resources);
|
|
3038
|
+
return;
|
|
3039
|
+
}
|
|
3040
|
+
self.deck.on("change", (deckProps) => resources.deck.setProps(deckProps));
|
|
3041
|
+
resources.deck.setProps(self.deck.toJSON());
|
|
3042
|
+
self.resources = resources;
|
|
3043
|
+
renderNode.requestRender();
|
|
3044
|
+
}).catch((err) => {
|
|
3045
|
+
isInitializing = false;
|
|
3046
|
+
console.error("DeckRenderer: failed to initialize resources", err);
|
|
3047
|
+
});
|
|
3048
|
+
}
|
|
3049
|
+
return passthrough;
|
|
3050
|
+
}
|
|
3051
|
+
if (!self.resources) {
|
|
3052
|
+
return passthrough;
|
|
3053
|
+
}
|
|
3054
|
+
const output = renderNode.bindRenderTarget();
|
|
3055
|
+
const gl = renderNode.gl;
|
|
3056
|
+
const dpr = window.devicePixelRatio || 1;
|
|
3057
|
+
const width = gl.drawingBufferWidth / dpr;
|
|
3058
|
+
const height = gl.drawingBufferHeight / dpr;
|
|
3059
|
+
const cameraPos = self.view.camera.position;
|
|
3060
|
+
const focalPoint = self.view.toMap({ x: width / 2, y: height / 2 });
|
|
3061
|
+
const latitude = focalPoint ? focalPoint.latitude : self.view.center.latitude;
|
|
3062
|
+
const longitude = focalPoint ? focalPoint.longitude : self.view.center.longitude;
|
|
3063
|
+
const midLatRad = (latitude + cameraPos.latitude) / 2 * Math.PI / 180;
|
|
3064
|
+
const dLatM = (cameraPos.latitude - latitude) * METERS_PER_DEG_LAT;
|
|
3065
|
+
const dLngM = (cameraPos.longitude - longitude) * METERS_PER_DEG_LAT * Math.cos(midLatRad);
|
|
3066
|
+
const horizM = Math.sqrt(dLatM * dLatM + dLngM * dLngM);
|
|
3067
|
+
const slantM = Math.sqrt(horizM * horizM + cameraPos.z * cameraPos.z);
|
|
3068
|
+
const zoom = getZoom(self.view, longitude, latitude, width, height);
|
|
3069
|
+
const viewportHeightM = height * self.view.resolution;
|
|
3070
|
+
const slantAltitude = slantM / viewportHeightM;
|
|
3071
|
+
const altitude = getAltitude(self.view.camera.tilt, slantAltitude, width, height);
|
|
3072
|
+
const arcgisMatrixView = getArcGISMatrixViewState(self.view, longitude, latitude, zoom, self.view.resolution, altitude);
|
|
3073
|
+
try {
|
|
3074
|
+
if (arcgisMatrixView) {
|
|
3075
|
+
render(self.resources, {
|
|
3076
|
+
width,
|
|
3077
|
+
height,
|
|
3078
|
+
latitude,
|
|
3079
|
+
longitude,
|
|
3080
|
+
altitude,
|
|
3081
|
+
zoom,
|
|
3082
|
+
bearing: self.view.camera.heading,
|
|
3083
|
+
pitch: self.view.camera.tilt,
|
|
3084
|
+
...arcgisMatrixView
|
|
3085
|
+
});
|
|
3086
|
+
} else {
|
|
3087
|
+
render(self.resources, {
|
|
3088
|
+
width,
|
|
3089
|
+
height,
|
|
3090
|
+
latitude,
|
|
3091
|
+
longitude,
|
|
3092
|
+
altitude,
|
|
3093
|
+
zoom,
|
|
3094
|
+
bearing: self.view.camera.heading,
|
|
3095
|
+
pitch: self.view.camera.tilt
|
|
3096
|
+
});
|
|
3097
|
+
}
|
|
3098
|
+
} catch (e) {
|
|
3099
|
+
console.error("DeckRenderer: render error", e);
|
|
3100
|
+
}
|
|
3101
|
+
return output;
|
|
3102
|
+
}
|
|
3103
|
+
});
|
|
3104
|
+
this.renderNode = new DeckRenderNode({ view: this.view });
|
|
3105
|
+
}
|
|
3106
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3107
|
+
async setup(_context) {
|
|
347
3108
|
}
|
|
348
3109
|
dispose() {
|
|
349
3110
|
var _a;
|
|
350
3111
|
(_a = this.cancelInitialization) == null ? void 0 : _a.call(this);
|
|
351
3112
|
if (this.resources) {
|
|
352
3113
|
finalizeResources(this.resources);
|
|
3114
|
+
this.resources = null;
|
|
353
3115
|
}
|
|
3116
|
+
this.renderNode = null;
|
|
354
3117
|
}
|
|
355
3118
|
redraw() {
|
|
356
|
-
|
|
3119
|
+
var _a;
|
|
3120
|
+
(_a = this.renderNode) == null ? void 0 : _a.requestRender();
|
|
357
3121
|
}
|
|
358
3122
|
render() {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
width,
|
|
362
|
-
height,
|
|
363
|
-
latitude: this.view.center.latitude,
|
|
364
|
-
longitude: this.view.center.longitude,
|
|
365
|
-
altitude: arcgisFOVToDeckAltitude(this.view.camera.fov, width / height),
|
|
366
|
-
zoom: this.view.zoom,
|
|
367
|
-
bearing: this.view.camera.heading,
|
|
368
|
-
pitch: this.view.camera.tilt
|
|
369
|
-
});
|
|
3123
|
+
var _a;
|
|
3124
|
+
(_a = this.renderNode) == null ? void 0 : _a.requestRender();
|
|
370
3125
|
}
|
|
371
3126
|
}
|
|
372
3127
|
return DeckRenderer2;
|
|
@@ -376,7 +3131,7 @@ function createDeckRenderer(DeckProps2, externalRenderers2) {
|
|
|
376
3131
|
var import_Accessor = __toESM(require("@arcgis/core/core/Accessor"), 1);
|
|
377
3132
|
var import_Layer = __toESM(require("@arcgis/core/layers/Layer"), 1);
|
|
378
3133
|
var import_BaseLayerViewGL2D = __toESM(require("@arcgis/core/views/2d/layers/BaseLayerViewGL2D"), 1);
|
|
379
|
-
var
|
|
3134
|
+
var import_RenderNode = __toESM(require("@arcgis/core/views/3d/webgl/RenderNode"), 1);
|
|
380
3135
|
|
|
381
3136
|
// dist/load-modules.js
|
|
382
3137
|
var import_esri_loader = require("esri-loader");
|
|
@@ -399,22 +3154,22 @@ async function loadArcGISModule(esri, loadScriptOptions) {
|
|
|
399
3154
|
const Layer3 = esri.layers.Layer;
|
|
400
3155
|
const Accessor3 = esri.core.Accessor;
|
|
401
3156
|
const BaseLayerViewGL2D3 = esri.views["2d"].layers.BaseLayerViewGL2D;
|
|
402
|
-
const
|
|
403
|
-
return initialize(Layer3, Accessor3, BaseLayerViewGL2D3,
|
|
3157
|
+
const RenderNode3 = esri.views["3d"].webgl.RenderNode;
|
|
3158
|
+
return initialize(Layer3, Accessor3, BaseLayerViewGL2D3, RenderNode3);
|
|
404
3159
|
}
|
|
405
|
-
const [Layer2, Accessor2, BaseLayerViewGL2D2,
|
|
3160
|
+
const [Layer2, Accessor2, BaseLayerViewGL2D2, RenderNode2] = await (0, import_esri_loader.loadModules)([
|
|
406
3161
|
"esri/layers/Layer",
|
|
407
3162
|
"esri/core/Accessor",
|
|
408
3163
|
"esri/views/2d/layers/BaseLayerViewGL2D",
|
|
409
|
-
"esri/views/3d/
|
|
3164
|
+
"esri/views/3d/webgl/RenderNode"
|
|
410
3165
|
], loadScriptOptions);
|
|
411
|
-
return initialize(Layer2, Accessor2, BaseLayerViewGL2D2,
|
|
3166
|
+
return initialize(Layer2, Accessor2, BaseLayerViewGL2D2, RenderNode2);
|
|
412
3167
|
}
|
|
413
|
-
function initialize(Layer2, Accessor2, BaseLayerViewGL2D2,
|
|
3168
|
+
function initialize(Layer2, Accessor2, BaseLayerViewGL2D2, RenderNode2) {
|
|
414
3169
|
const DeckProps2 = createDeckProps(Accessor2);
|
|
415
3170
|
const DeckLayerView2D2 = createDeckLayerView2D(BaseLayerViewGL2D2);
|
|
416
3171
|
const DeckLayer2 = createDeckLayer(DeckProps2, Layer2, DeckLayerView2D2);
|
|
417
|
-
const DeckRenderer2 = createDeckRenderer(DeckProps2,
|
|
3172
|
+
const DeckRenderer2 = createDeckRenderer(DeckProps2, RenderNode2);
|
|
418
3173
|
arcGIS = { DeckLayer: DeckLayer2, DeckRenderer: DeckRenderer2 };
|
|
419
3174
|
return arcGIS;
|
|
420
3175
|
}
|
|
@@ -423,5 +3178,5 @@ function initialize(Layer2, Accessor2, BaseLayerViewGL2D2, externalRenderers2) {
|
|
|
423
3178
|
var DeckProps = createDeckProps(import_Accessor.default);
|
|
424
3179
|
var DeckLayerView2D = createDeckLayerView2D(import_BaseLayerViewGL2D.default);
|
|
425
3180
|
var DeckLayer = createDeckLayer(DeckProps, import_Layer.default, DeckLayerView2D);
|
|
426
|
-
var DeckRenderer = createDeckRenderer(DeckProps,
|
|
3181
|
+
var DeckRenderer = createDeckRenderer(DeckProps, import_RenderNode.default);
|
|
427
3182
|
//# sourceMappingURL=index.cjs.map
|