@plait/core 0.0.49 → 0.0.50

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
  /**
@@ -534,6 +535,32 @@ function withBoard(board) {
534
535
  return board;
535
536
  }
536
537
 
538
+ function transformPoints(board, points) {
539
+ const newPoints = points.map(point => {
540
+ return transformPoint(board, point);
541
+ });
542
+ return newPoints;
543
+ }
544
+ function transformPoint(board, point) {
545
+ const { width, height } = board.host.getBoundingClientRect();
546
+ const viewBox = board.host.viewBox.baseVal;
547
+ const x = (point[0] / width) * viewBox.width + viewBox.x;
548
+ const y = (point[1] / height) * viewBox.height + viewBox.y;
549
+ const newPoint = [x, y];
550
+ return newPoint;
551
+ }
552
+ function calculateZoom(zoom, minZoom = 0.2, maxZoom = 4) {
553
+ return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
554
+ }
555
+ function isNoSelectionElement(e) {
556
+ return e.target?.closest('.plait-board-attached');
557
+ }
558
+ const updateCursorStatus = (board, cursor) => {
559
+ if (cursor) {
560
+ board.cursor = cursor;
561
+ }
562
+ };
563
+
537
564
  const NS = 'http://www.w3.org/2000/svg';
538
565
  function toPoint(x, y, container) {
539
566
  const rect = container.getBoundingClientRect();
@@ -580,6 +607,68 @@ function toRectangleClient(points) {
580
607
  return rect;
581
608
  }
582
609
 
610
+ /**
611
+ * Check whether to merge an operation into the previous operation.
612
+ */
613
+ const shouldMerge = (op, prev) => {
614
+ if (op.type === 'set_viewport' && op.type === prev?.type) {
615
+ return true;
616
+ }
617
+ return false;
618
+ };
619
+ /**
620
+ * Check whether an operation needs to be saved to the history.
621
+ */
622
+ const shouldSave = (op, prev) => {
623
+ if (op.type === 'set_selection' || op.type === 'set_viewport') {
624
+ return false;
625
+ }
626
+ return true;
627
+ };
628
+ /**
629
+ * Check whether an operation should clear the redos stack.
630
+ */
631
+ const shouldClear = (op) => {
632
+ if (op.type === 'set_selection') {
633
+ return false;
634
+ }
635
+ return true;
636
+ };
637
+ const PlaitHistoryBoard = {
638
+ /**
639
+ * Get the saving flag's current value.
640
+ */
641
+ isSaving(board) {
642
+ return SAVING.get(board);
643
+ },
644
+ /**
645
+ * Get the merge flag's current value.
646
+ */
647
+ isMerging(board) {
648
+ return MERGING.get(board);
649
+ },
650
+ /**
651
+ * Apply a series of changes inside a synchronous `fn`, without merging any of
652
+ * the new operations into previous save point in the history.
653
+ */
654
+ withoutMerging(board, fn) {
655
+ const prev = PlaitHistoryBoard.isMerging(board);
656
+ MERGING.set(board, false);
657
+ fn();
658
+ MERGING.set(board, prev);
659
+ },
660
+ /**
661
+ * Apply a series of changes inside a synchronous `fn`, without saving any of
662
+ * their operations into the history.
663
+ */
664
+ withoutSaving(board, fn) {
665
+ const prev = PlaitHistoryBoard.isSaving(board);
666
+ SAVING.set(board, false);
667
+ fn();
668
+ SAVING.set(board, prev);
669
+ }
670
+ };
671
+
583
672
  /**
584
673
  * Hotkey mappings for each platform.
585
674
  */
@@ -728,32 +817,27 @@ function distanceBetweenPointAndPoint(x1, y1, x2, y2) {
728
817
  return Math.hypot(dx, dy);
729
818
  }
730
819
 
731
- function transformPoints(board, points) {
732
- const newPoints = points.map(point => {
733
- return transformPoint(board, point);
734
- });
735
- return newPoints;
820
+ function invert(oldMatrix, newMatrix) {
821
+ 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;
822
+ return p
823
+ ? ((p = 1 / p),
824
+ (oldMatrix[0] = d * p),
825
+ (oldMatrix[1] = (-u * r + a * s) * p),
826
+ (oldMatrix[2] = (c * r - a * o) * p),
827
+ (oldMatrix[3] = h * p),
828
+ (oldMatrix[4] = (u * n - a * l) * p),
829
+ (oldMatrix[5] = (-c * n + a * i) * p),
830
+ (oldMatrix[6] = f * p),
831
+ (oldMatrix[7] = (-s * n + r * l) * p),
832
+ (oldMatrix[8] = (o * n - r * i) * p),
833
+ oldMatrix)
834
+ : null;
736
835
  }
737
- function transformPoint(board, point) {
738
- const { width, height } = board.host.getBoundingClientRect();
739
- const viewBox = board.host.viewBox.baseVal;
740
- const x = (point[0] / width) * viewBox.width + viewBox.x;
741
- const y = (point[1] / height) * viewBox.height + viewBox.y;
742
- const newPoint = [x, y];
743
- return newPoint;
744
- }
745
- function getViewBox(board) {
746
- const viewportBox = getViewportClientBox(board);
747
- const rootGroupBBox = calculateBBox(board);
748
- const padding = [viewportBox.height / 2, viewportBox.width / 2];
749
- const zoom = board.viewport.zoom;
750
- const minX = rootGroupBBox.left - padding[1] / zoom;
751
- const minY = rootGroupBBox.top - padding[0] / zoom;
752
- const viewportWidth = (rootGroupBBox.right - rootGroupBBox.left) * zoom + 2 * padding[1];
753
- const viewportHeight = (rootGroupBBox.bottom - rootGroupBBox.top) * zoom + 2 * padding[0];
754
- const width = viewportWidth / zoom;
755
- const height = viewportHeight / zoom;
756
- return { minX, minY, width, height, viewportWidth, viewportHeight };
836
+ function transformMat3(e, t, n) {
837
+ const r = t[0];
838
+ const a = t[1];
839
+ const i = t[2];
840
+ 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;
757
841
  }
758
842
  function getViewportClientBox(board) {
759
843
  const hideScrollbar = board.options.hideScrollbar;
@@ -762,9 +846,13 @@ function getViewportClientBox(board) {
762
846
  const containerRect = container?.getBoundingClientRect();
763
847
  const width = containerRect.width - scrollBarWidth;
764
848
  const height = containerRect.height - scrollBarWidth;
849
+ const x = containerRect.x || containerRect.left;
850
+ const y = containerRect.y || containerRect.top;
765
851
  return {
766
852
  width,
767
- height
853
+ height,
854
+ x,
855
+ y
768
856
  };
769
857
  }
770
858
  function calculateBBox(board) {
@@ -798,79 +886,19 @@ function calculateBBox(board) {
798
886
  // 在新的缩放比容器宽高下的内容盒子位置
799
887
  return box;
800
888
  }
801
- function calculateZoom(zoom, minZoom = 0.2, maxZoom = 4) {
802
- return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
803
- }
804
- function isNoSelectionElement(e) {
805
- return e.target?.closest('.plait-board-attached');
889
+ function getViewBox(board) {
890
+ const viewportBox = getViewportClientBox(board);
891
+ const rootGroupBBox = calculateBBox(board);
892
+ const padding = [viewportBox.height / 2, viewportBox.width / 2];
893
+ const zoom = board.viewport.zoom;
894
+ const minX = rootGroupBBox.left - padding[1] / zoom;
895
+ const minY = rootGroupBBox.top - padding[0] / zoom;
896
+ const viewportWidth = (rootGroupBBox.right - rootGroupBBox.left) * zoom + 2 * padding[1];
897
+ const viewportHeight = (rootGroupBBox.bottom - rootGroupBBox.top) * zoom + 2 * padding[0];
898
+ const width = viewportWidth / zoom;
899
+ const height = viewportHeight / zoom;
900
+ return { minX, minY, width, height, viewportWidth, viewportHeight };
806
901
  }
807
- const updateCursorStatus = (board, cursor) => {
808
- if (cursor) {
809
- board.cursor = cursor;
810
- }
811
- };
812
-
813
- /**
814
- * Check whether to merge an operation into the previous operation.
815
- */
816
- const shouldMerge = (op, prev) => {
817
- if (op.type === 'set_viewport' && op.type === prev?.type) {
818
- return true;
819
- }
820
- return false;
821
- };
822
- /**
823
- * Check whether an operation needs to be saved to the history.
824
- */
825
- const shouldSave = (op, prev) => {
826
- if (op.type === 'set_selection' || op.type === 'set_viewport') {
827
- return false;
828
- }
829
- return true;
830
- };
831
- /**
832
- * Check whether an operation should clear the redos stack.
833
- */
834
- const shouldClear = (op) => {
835
- if (op.type === 'set_selection') {
836
- return false;
837
- }
838
- return true;
839
- };
840
- const PlaitHistoryBoard = {
841
- /**
842
- * Get the saving flag's current value.
843
- */
844
- isSaving(board) {
845
- return SAVING.get(board);
846
- },
847
- /**
848
- * Get the merge flag's current value.
849
- */
850
- isMerging(board) {
851
- return MERGING.get(board);
852
- },
853
- /**
854
- * Apply a series of changes inside a synchronous `fn`, without merging any of
855
- * the new operations into previous save point in the history.
856
- */
857
- withoutMerging(board, fn) {
858
- const prev = PlaitHistoryBoard.isMerging(board);
859
- MERGING.set(board, false);
860
- fn();
861
- MERGING.set(board, prev);
862
- },
863
- /**
864
- * Apply a series of changes inside a synchronous `fn`, without saving any of
865
- * their operations into the history.
866
- */
867
- withoutSaving(board, fn) {
868
- const prev = PlaitHistoryBoard.isSaving(board);
869
- SAVING.set(board, false);
870
- fn();
871
- SAVING.set(board, prev);
872
- }
873
- };
874
902
 
875
903
  function withHistory(board) {
876
904
  const { apply, keydown } = board;
@@ -1190,6 +1218,8 @@ class PlaitBoardComponent {
1190
1218
  this.destroy$ = new Subject();
1191
1219
  this.autoFitPadding = 8;
1192
1220
  this.isMoving = false;
1221
+ this.focusPoint = [];
1222
+ this.matrix = [];
1193
1223
  this.plaitValue = [];
1194
1224
  this.plaitPlugins = [];
1195
1225
  this.plaitChange = new EventEmitter();
@@ -1236,10 +1266,18 @@ class PlaitBoardComponent {
1236
1266
  if (this.board.operations.some(op => PlaitOperation.isSetViewportOperation(op))) {
1237
1267
  this.updateViewport();
1238
1268
  }
1269
+ if (this.board.operations.some(op => ['set_node', 'remove_node'].includes(op.type))) {
1270
+ this.calculateViewport();
1271
+ }
1239
1272
  this.plaitChange.emit(changeEvent);
1240
1273
  });
1241
1274
  this.hasInitialized = true;
1242
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
+ }
1243
1281
  ngOnChanges(changes) {
1244
1282
  if (this.hasInitialized) {
1245
1283
  const valueChange = changes['plaitValue'];
@@ -1379,6 +1417,39 @@ class PlaitBoardComponent {
1379
1417
  offsetYRatio: scrollTopRatio
1380
1418
  });
1381
1419
  }
1420
+ updateScroll() {
1421
+ const container = this.contentContainer.nativeElement;
1422
+ container.scrollTo({
1423
+ top: this.scrollTop,
1424
+ left: this.scrollLeft
1425
+ });
1426
+ }
1427
+ calculateViewport() {
1428
+ const viewBox = getViewBox(this.board);
1429
+ const { minX, minY, viewportWidth } = viewBox;
1430
+ const viewportBox = getViewportClientBox(this.board);
1431
+ const nweHhBox = calculateBBox(this.board);
1432
+ let scrollLeft = this.scrollLeft;
1433
+ let scrollTop = this.scrollTop;
1434
+ const zoom = this.board.viewport.zoom;
1435
+ const matrix = this.matrix;
1436
+ const focusPoint = this.focusPoint;
1437
+ if (matrix) {
1438
+ const g = [focusPoint[0] - viewportBox.x, focusPoint[1] - viewportBox.y, 1];
1439
+ const b = invert([], matrix);
1440
+ const x = transformMat3([], [g[0], g[1], 1], b);
1441
+ const k = [zoom, 0, 0, 0, zoom, 0, -zoom * minX, -zoom * minY, 1];
1442
+ const c = transformMat3([], x, k);
1443
+ scrollLeft = c[0] - g[0];
1444
+ scrollTop = c[1] - g[1];
1445
+ }
1446
+ else {
1447
+ scrollLeft = (viewportWidth - viewportBox.width) / 2;
1448
+ scrollTop = viewportBox.height / 2 - nweHhBox.top;
1449
+ }
1450
+ this.setScroll(scrollLeft, scrollTop);
1451
+ this.updateViewport();
1452
+ }
1382
1453
  viewportChange() {
1383
1454
  const viewBox = getViewBox(this.board);
1384
1455
  const offsetXRatio = this.board.viewport.offsetXRatio;
@@ -1394,15 +1465,13 @@ class PlaitBoardComponent {
1394
1465
  if (width > 0 && height > 0) {
1395
1466
  this.renderer2.setAttribute(this.host, 'viewBox', box.join());
1396
1467
  }
1397
- const container = this.contentContainer.nativeElement;
1398
- container.scrollTo({
1399
- top: this.scrollTop,
1400
- left: this.scrollLeft
1401
- });
1468
+ this.focusPoint = [viewportBox.x, viewportBox.y];
1469
+ this.setMatrix();
1402
1470
  }
1403
1471
  updateViewport() {
1404
1472
  this.resizeViewport();
1405
1473
  this.viewportChange();
1474
+ this.updateScroll();
1406
1475
  }
1407
1476
  // 拖拽模式
1408
1477
  changeMoveMode(cursorStatus) {
@@ -1579,5 +1648,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1579
1648
  * Generated bundle index. Do not edit.
1580
1649
  */
1581
1650
 
1582
- 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 };
1651
+ 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, isSetViewportOperation, rotate, shouldClear, shouldMerge, shouldSave, toPoint, toRectangleClient, transformMat3, transformPoint, transformPoints, updateCursorStatus };
1583
1652
  //# sourceMappingURL=plait-core.mjs.map