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