@plait/core 0.0.49 → 0.0.52

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.
@@ -15,6 +15,7 @@ var BaseCursorStatus;
15
15
  (function (BaseCursorStatus) {
16
16
  BaseCursorStatus["move"] = "move";
17
17
  BaseCursorStatus["select"] = "select";
18
+ BaseCursorStatus["drag"] = "drag";
18
19
  })(BaseCursorStatus || (BaseCursorStatus = {}));
19
20
 
20
21
  const Path = {
@@ -510,6 +511,33 @@ function withBoard(board) {
510
511
  return board;
511
512
  }
512
513
 
514
+ function transformPoints(board, points) {
515
+ const newPoints = points.map(point => {
516
+ return transformPoint(board, point);
517
+ });
518
+ return newPoints;
519
+ }
520
+ function transformPoint(board, point) {
521
+ const { width, height } = board.host.getBoundingClientRect();
522
+ const viewBox = board.host.viewBox.baseVal;
523
+ const x = (point[0] / width) * viewBox.width + viewBox.x;
524
+ const y = (point[1] / height) * viewBox.height + viewBox.y;
525
+ const newPoint = [x, y];
526
+ return newPoint;
527
+ }
528
+ function calculateZoom(zoom, minZoom = 0.2, maxZoom = 4) {
529
+ return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
530
+ }
531
+ function isNoSelectionElement(e) {
532
+ var _a;
533
+ return (_a = e.target) === null || _a === void 0 ? void 0 : _a.closest('.plait-board-attached');
534
+ }
535
+ const updateCursorStatus = (board, cursor) => {
536
+ if (cursor) {
537
+ board.cursor = cursor;
538
+ }
539
+ };
540
+
513
541
  const NS = 'http://www.w3.org/2000/svg';
514
542
  function toPoint(x, y, container) {
515
543
  const rect = container.getBoundingClientRect();
@@ -556,6 +584,68 @@ function toRectangleClient(points) {
556
584
  return rect;
557
585
  }
558
586
 
587
+ /**
588
+ * Check whether to merge an operation into the previous operation.
589
+ */
590
+ const shouldMerge = (op, prev) => {
591
+ if (op.type === 'set_viewport' && op.type === (prev === null || prev === void 0 ? void 0 : prev.type)) {
592
+ return true;
593
+ }
594
+ return false;
595
+ };
596
+ /**
597
+ * Check whether an operation needs to be saved to the history.
598
+ */
599
+ const shouldSave = (op, prev) => {
600
+ if (op.type === 'set_selection' || op.type === 'set_viewport') {
601
+ return false;
602
+ }
603
+ return true;
604
+ };
605
+ /**
606
+ * Check whether an operation should clear the redos stack.
607
+ */
608
+ const shouldClear = (op) => {
609
+ if (op.type === 'set_selection') {
610
+ return false;
611
+ }
612
+ return true;
613
+ };
614
+ const PlaitHistoryBoard = {
615
+ /**
616
+ * Get the saving flag's current value.
617
+ */
618
+ isSaving(board) {
619
+ return SAVING.get(board);
620
+ },
621
+ /**
622
+ * Get the merge flag's current value.
623
+ */
624
+ isMerging(board) {
625
+ return MERGING.get(board);
626
+ },
627
+ /**
628
+ * Apply a series of changes inside a synchronous `fn`, without merging any of
629
+ * the new operations into previous save point in the history.
630
+ */
631
+ withoutMerging(board, fn) {
632
+ const prev = PlaitHistoryBoard.isMerging(board);
633
+ MERGING.set(board, false);
634
+ fn();
635
+ MERGING.set(board, prev);
636
+ },
637
+ /**
638
+ * Apply a series of changes inside a synchronous `fn`, without saving any of
639
+ * their operations into the history.
640
+ */
641
+ withoutSaving(board, fn) {
642
+ const prev = PlaitHistoryBoard.isSaving(board);
643
+ SAVING.set(board, false);
644
+ fn();
645
+ SAVING.set(board, prev);
646
+ }
647
+ };
648
+
559
649
  /**
560
650
  * Hotkey mappings for each platform.
561
651
  */
@@ -704,32 +794,27 @@ function distanceBetweenPointAndPoint(x1, y1, x2, y2) {
704
794
  return Math.hypot(dx, dy);
705
795
  }
706
796
 
707
- function transformPoints(board, points) {
708
- const newPoints = points.map(point => {
709
- return transformPoint(board, point);
710
- });
711
- return newPoints;
797
+ function invert(oldMatrix, newMatrix) {
798
+ let n = newMatrix[0], r = newMatrix[1], a = newMatrix[2], i = newMatrix[3], o = newMatrix[4], c = newMatrix[5], l = newMatrix[6], s = newMatrix[7], u = newMatrix[8], d = u * o - c * s, h = -u * i + c * l, f = s * i - o * l, p = n * d + r * h + a * f;
799
+ return p
800
+ ? ((p = 1 / p),
801
+ (oldMatrix[0] = d * p),
802
+ (oldMatrix[1] = (-u * r + a * s) * p),
803
+ (oldMatrix[2] = (c * r - a * o) * p),
804
+ (oldMatrix[3] = h * p),
805
+ (oldMatrix[4] = (u * n - a * l) * p),
806
+ (oldMatrix[5] = (-c * n + a * i) * p),
807
+ (oldMatrix[6] = f * p),
808
+ (oldMatrix[7] = (-s * n + r * l) * p),
809
+ (oldMatrix[8] = (o * n - r * i) * p),
810
+ oldMatrix)
811
+ : null;
712
812
  }
713
- function transformPoint(board, point) {
714
- const { width, height } = board.host.getBoundingClientRect();
715
- const viewBox = board.host.viewBox.baseVal;
716
- const x = (point[0] / width) * viewBox.width + viewBox.x;
717
- const y = (point[1] / height) * viewBox.height + viewBox.y;
718
- const newPoint = [x, y];
719
- return newPoint;
720
- }
721
- function getViewBox(board) {
722
- const viewportBox = getViewportClientBox(board);
723
- const rootGroupBBox = calculateBBox(board);
724
- const padding = [viewportBox.height / 2, viewportBox.width / 2];
725
- const zoom = board.viewport.zoom;
726
- const minX = rootGroupBBox.left - padding[1] / zoom;
727
- const minY = rootGroupBBox.top - padding[0] / zoom;
728
- const viewportWidth = (rootGroupBBox.right - rootGroupBBox.left) * zoom + 2 * padding[1];
729
- const viewportHeight = (rootGroupBBox.bottom - rootGroupBBox.top) * zoom + 2 * padding[0];
730
- const width = viewportWidth / zoom;
731
- const height = viewportHeight / zoom;
732
- return { minX, minY, width, height, viewportWidth, viewportHeight };
813
+ function transformMat3(e, t, n) {
814
+ const r = t[0];
815
+ const a = t[1];
816
+ const i = t[2];
817
+ return (e[0] = r * n[0] + a * n[3] + i * n[6]), (e[1] = r * n[1] + a * n[4] + i * n[7]), (e[2] = r * n[2] + a * n[5] + i * n[8]), e;
733
818
  }
734
819
  function getViewportClientBox(board) {
735
820
  var _a;
@@ -739,9 +824,13 @@ function getViewportClientBox(board) {
739
824
  const containerRect = container === null || container === void 0 ? void 0 : container.getBoundingClientRect();
740
825
  const width = containerRect.width - scrollBarWidth;
741
826
  const height = containerRect.height - scrollBarWidth;
827
+ const x = containerRect.x || containerRect.left;
828
+ const y = containerRect.y || containerRect.top;
742
829
  return {
743
830
  width,
744
- height
831
+ height,
832
+ x,
833
+ y
745
834
  };
746
835
  }
747
836
  function calculateBBox(board) {
@@ -775,80 +864,40 @@ function calculateBBox(board) {
775
864
  // 在新的缩放比容器宽高下的内容盒子位置
776
865
  return box;
777
866
  }
778
- function calculateZoom(zoom, minZoom = 0.2, maxZoom = 4) {
779
- return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
780
- }
781
- function isNoSelectionElement(e) {
782
- var _a;
783
- return (_a = e.target) === null || _a === void 0 ? void 0 : _a.closest('.plait-board-attached');
867
+ function getViewBox(board) {
868
+ const viewportBox = getViewportClientBox(board);
869
+ const rootGroupBBox = calculateBBox(board);
870
+ const padding = [viewportBox.height / 2, viewportBox.width / 2];
871
+ const zoom = board.viewport.zoom;
872
+ const minX = rootGroupBBox.left - padding[1] / zoom;
873
+ const minY = rootGroupBBox.top - padding[0] / zoom;
874
+ const viewportWidth = (rootGroupBBox.right - rootGroupBBox.left) * zoom + 2 * padding[1];
875
+ const viewportHeight = (rootGroupBBox.bottom - rootGroupBBox.top) * zoom + 2 * padding[0];
876
+ const width = viewportWidth / zoom;
877
+ const height = viewportHeight / zoom;
878
+ return { minX, minY, width, height, viewportWidth, viewportHeight };
784
879
  }
785
- const updateCursorStatus = (board, cursor) => {
786
- if (cursor) {
787
- board.cursor = cursor;
880
+ function isOutExtent(board, node, gap) {
881
+ const result = { x: 0, y: 0 };
882
+ if (!node)
883
+ return result;
884
+ const boardComponent = PLAIT_BOARD_TO_COMPONENT.get(board);
885
+ const scrollBarWidth = board.options.hideScrollbar ? SCROLL_BAR_WIDTH : 0;
886
+ const canvasRect = boardComponent.contentContainer.nativeElement.getBoundingClientRect();
887
+ if (node.left < canvasRect.left + gap) {
888
+ result.x = canvasRect.left - node.left - gap;
788
889
  }
789
- };
790
-
791
- /**
792
- * Check whether to merge an operation into the previous operation.
793
- */
794
- const shouldMerge = (op, prev) => {
795
- if (op.type === 'set_viewport' && op.type === (prev === null || prev === void 0 ? void 0 : prev.type)) {
796
- return true;
890
+ else if (node.right > canvasRect.right - scrollBarWidth - gap) {
891
+ result.x = canvasRect.right - scrollBarWidth - gap - node.right - node.width;
797
892
  }
798
- return false;
799
- };
800
- /**
801
- * Check whether an operation needs to be saved to the history.
802
- */
803
- const shouldSave = (op, prev) => {
804
- if (op.type === 'set_selection' || op.type === 'set_viewport') {
805
- return false;
893
+ if (node.top < canvasRect.top + gap) {
894
+ result.y = canvasRect.top - node.top - gap;
806
895
  }
807
- return true;
808
- };
809
- /**
810
- * Check whether an operation should clear the redos stack.
811
- */
812
- const shouldClear = (op) => {
813
- if (op.type === 'set_selection') {
814
- return false;
896
+ else if (node.bottom > canvasRect.bottom - scrollBarWidth - gap) {
897
+ result.y = canvasRect.bottom - scrollBarWidth - gap - node.bottom - node.height;
815
898
  }
816
- return true;
817
- };
818
- const PlaitHistoryBoard = {
819
- /**
820
- * Get the saving flag's current value.
821
- */
822
- isSaving(board) {
823
- return SAVING.get(board);
824
- },
825
- /**
826
- * Get the merge flag's current value.
827
- */
828
- isMerging(board) {
829
- return MERGING.get(board);
830
- },
831
- /**
832
- * Apply a series of changes inside a synchronous `fn`, without merging any of
833
- * the new operations into previous save point in the history.
834
- */
835
- withoutMerging(board, fn) {
836
- const prev = PlaitHistoryBoard.isMerging(board);
837
- MERGING.set(board, false);
838
- fn();
839
- MERGING.set(board, prev);
840
- },
841
- /**
842
- * Apply a series of changes inside a synchronous `fn`, without saving any of
843
- * their operations into the history.
844
- */
845
- withoutSaving(board, fn) {
846
- const prev = PlaitHistoryBoard.isSaving(board);
847
- SAVING.set(board, false);
848
- fn();
849
- SAVING.set(board, prev);
850
- }
851
- };
899
+ return result;
900
+ }
852
901
 
853
902
  function withHistory(board) {
854
903
  const { apply, keydown } = board;
@@ -1168,6 +1217,8 @@ class PlaitBoardComponent {
1168
1217
  this.destroy$ = new Subject();
1169
1218
  this.autoFitPadding = 8;
1170
1219
  this.isMoving = false;
1220
+ this.focusPoint = [];
1221
+ this.matrix = [];
1171
1222
  this.plaitValue = [];
1172
1223
  this.plaitPlugins = [];
1173
1224
  this.plaitChange = new EventEmitter();
@@ -1215,10 +1266,18 @@ class PlaitBoardComponent {
1215
1266
  if (this.board.operations.some(op => PlaitOperation.isSetViewportOperation(op))) {
1216
1267
  this.updateViewport();
1217
1268
  }
1269
+ if (this.board.operations.some(op => ['set_node', 'remove_node'].includes(op.type))) {
1270
+ this.calculateViewport();
1271
+ }
1218
1272
  this.plaitChange.emit(changeEvent);
1219
1273
  });
1220
1274
  this.hasInitialized = true;
1221
1275
  }
1276
+ setMatrix() {
1277
+ const viewBox = getViewBox(this.board);
1278
+ const zoom = this.board.viewport.zoom;
1279
+ this.matrix = [zoom, 0, 0, 0, zoom, 0, -this.scrollLeft - zoom * viewBox.minX, -this.scrollTop - zoom * viewBox.minY, 1];
1280
+ }
1222
1281
  ngOnChanges(changes) {
1223
1282
  if (this.hasInitialized) {
1224
1283
  const valueChange = changes['plaitValue'];
@@ -1364,6 +1423,39 @@ class PlaitBoardComponent {
1364
1423
  offsetYRatio: scrollTopRatio
1365
1424
  });
1366
1425
  }
1426
+ updateScroll() {
1427
+ const container = this.contentContainer.nativeElement;
1428
+ container.scrollTo({
1429
+ top: this.scrollTop,
1430
+ left: this.scrollLeft
1431
+ });
1432
+ }
1433
+ calculateViewport() {
1434
+ const viewBox = getViewBox(this.board);
1435
+ const { minX, minY, viewportWidth } = viewBox;
1436
+ const viewportBox = getViewportClientBox(this.board);
1437
+ const nweHhBox = calculateBBox(this.board);
1438
+ let scrollLeft = this.scrollLeft;
1439
+ let scrollTop = this.scrollTop;
1440
+ const zoom = this.board.viewport.zoom;
1441
+ const matrix = this.matrix;
1442
+ const focusPoint = this.focusPoint;
1443
+ if (matrix) {
1444
+ const g = [focusPoint[0] - viewportBox.x, focusPoint[1] - viewportBox.y, 1];
1445
+ const b = invert([], matrix);
1446
+ const x = transformMat3([], [g[0], g[1], 1], b);
1447
+ const k = [zoom, 0, 0, 0, zoom, 0, -zoom * minX, -zoom * minY, 1];
1448
+ const c = transformMat3([], x, k);
1449
+ scrollLeft = c[0] - g[0];
1450
+ scrollTop = c[1] - g[1];
1451
+ }
1452
+ else {
1453
+ scrollLeft = (viewportWidth - viewportBox.width) / 2;
1454
+ scrollTop = viewportBox.height / 2 - nweHhBox.top;
1455
+ }
1456
+ this.setScroll(scrollLeft, scrollTop);
1457
+ this.updateViewport();
1458
+ }
1367
1459
  viewportChange() {
1368
1460
  const viewBox = getViewBox(this.board);
1369
1461
  const offsetXRatio = this.board.viewport.offsetXRatio;
@@ -1379,15 +1471,13 @@ class PlaitBoardComponent {
1379
1471
  if (width > 0 && height > 0) {
1380
1472
  this.renderer2.setAttribute(this.host, 'viewBox', box.join());
1381
1473
  }
1382
- const container = this.contentContainer.nativeElement;
1383
- container.scrollTo({
1384
- top: this.scrollTop,
1385
- left: this.scrollLeft
1386
- });
1474
+ this.focusPoint = [viewportBox.x, viewportBox.y];
1475
+ this.setMatrix();
1387
1476
  }
1388
1477
  updateViewport() {
1389
1478
  this.resizeViewport();
1390
1479
  this.viewportChange();
1480
+ this.updateScroll();
1391
1481
  }
1392
1482
  // 拖拽模式
1393
1483
  changeMoveMode(cursorStatus) {
@@ -1409,7 +1499,7 @@ class PlaitBoardComponent {
1409
1499
  zoom = 1;
1410
1500
  }
1411
1501
  this.setViewport({
1412
- zoom,
1502
+ zoom: calculateZoom(zoom),
1413
1503
  offsetXRatio: 0.5,
1414
1504
  offsetYRatio: 0.5
1415
1505
  });
@@ -1450,7 +1540,7 @@ class PlaitBoardComponent {
1450
1540
  PlaitBoardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: PlaitBoardComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1451
1541
  PlaitBoardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: PlaitBoardComponent, selector: "plait-board", inputs: { plaitValue: "plaitValue", plaitViewport: "plaitViewport", plaitPlugins: "plaitPlugins", plaitOptions: "plaitOptions" }, outputs: { plaitChange: "plaitChange", plaitBoardInitialized: "plaitBoardInitialized" }, host: { properties: { "class": "this.hostClass", "class.readonly": "this.readonly", "class.moving": "this.moving", "class.focused": "this.focused" } }, queries: [{ propertyName: "toolbarTemplateRef", first: true, predicate: ["plaitToolbar"], descendants: true }], viewQueries: [{ propertyName: "svg", first: true, predicate: ["svg"], descendants: true, static: true }, { propertyName: "contentContainer", first: true, predicate: ["container"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: `
1452
1542
  <div class="container" #container>
1453
- <svg #svg width="100%" height="100%" style="position: relative"></svg>
1543
+ <svg #svg width="100%" height="100%" style="position: relative;"></svg>
1454
1544
  <plait-element
1455
1545
  *ngFor="let item of board.children; let index = index; trackBy: trackBy"
1456
1546
  [index]="index"
@@ -1479,7 +1569,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1479
1569
  selector: 'plait-board',
1480
1570
  template: `
1481
1571
  <div class="container" #container>
1482
- <svg #svg width="100%" height="100%" style="position: relative"></svg>
1572
+ <svg #svg width="100%" height="100%" style="position: relative;"></svg>
1483
1573
  <plait-element
1484
1574
  *ngFor="let item of board.children; let index = index; trackBy: trackBy"
1485
1575
  [index]="index"
@@ -1562,5 +1652,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1562
1652
  * Generated bundle index. Do not edit.
1563
1653
  */
1564
1654
 
1565
- export { BOARD_TO_ON_CHANGE, BaseCursorStatus, CLIP_BOARD_FORMAT_KEY, FLUSHING, HOST_TO_ROUGH_SVG, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_IOS, IS_SAFARI, IS_TEXT_EDITABLE, MERGING, NS, PLAIT_BOARD_TO_COMPONENT, Path, PlaitBoardComponent, PlaitElementComponent, PlaitHistoryBoard, PlaitModule, PlaitNode, PlaitOperation, PlaitToolbarComponent, SAVING, SCROLL_BAR_WIDTH, Transforms, Viewport, calculateBBox, calculateZoom, createG, createSVG, createText, distanceBetweenPointAndPoint, distanceBetweenPointAndSegment, getViewBox, getViewportClientBox, hotkeys, idCreator, inverse, isNoSelectionElement, isNullOrUndefined, isSetViewportOperation, rotate, shouldClear, shouldMerge, shouldSave, toPoint, toRectangleClient, transformPoint, transformPoints, updateCursorStatus };
1655
+ export { BOARD_TO_ON_CHANGE, BaseCursorStatus, CLIP_BOARD_FORMAT_KEY, FLUSHING, HOST_TO_ROUGH_SVG, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_IOS, IS_SAFARI, IS_TEXT_EDITABLE, MERGING, NS, PLAIT_BOARD_TO_COMPONENT, Path, PlaitBoardComponent, PlaitElementComponent, PlaitHistoryBoard, PlaitModule, PlaitNode, PlaitOperation, PlaitToolbarComponent, SAVING, SCROLL_BAR_WIDTH, Transforms, Viewport, calculateBBox, calculateZoom, createG, createSVG, createText, distanceBetweenPointAndPoint, distanceBetweenPointAndSegment, getViewBox, getViewportClientBox, hotkeys, idCreator, inverse, invert, isNoSelectionElement, isNullOrUndefined, isOutExtent, isSetViewportOperation, rotate, shouldClear, shouldMerge, shouldSave, toPoint, toRectangleClient, transformMat3, transformPoint, transformPoints, updateCursorStatus };
1566
1656
  //# sourceMappingURL=plait-core.mjs.map