@plait/core 0.0.48 → 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;
736
- }
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;
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;
744
835
  }
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,91 +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
- /**
808
- * viewZoom 转 zoom
809
- * @param viewZoom 视图上显示的 zoom 缩放级别 %
810
- * @returns zoom 真实的 zoom
811
- */
812
- const transformViewZoom = (viewZoom) => 2 - 100 / viewZoom;
813
- /**
814
- * zoom 转 viewZoom
815
- * @param zoom this.board.viewport.zoom
816
- * @returns 视图上显示的 zoom 缩放级别 %
817
- */
818
- const transformZoom = (zoom) => Number((100 / (2 - zoom)).toFixed(0));
819
- const updateCursorStatus = (board, cursor) => {
820
- if (cursor) {
821
- board.cursor = cursor;
822
- }
823
- };
824
-
825
- /**
826
- * Check whether to merge an operation into the previous operation.
827
- */
828
- const shouldMerge = (op, prev) => {
829
- if (op.type === 'set_viewport' && op.type === prev?.type) {
830
- return true;
831
- }
832
- return false;
833
- };
834
- /**
835
- * Check whether an operation needs to be saved to the history.
836
- */
837
- const shouldSave = (op, prev) => {
838
- if (op.type === 'set_selection' || op.type === 'set_viewport') {
839
- return false;
840
- }
841
- return true;
842
- };
843
- /**
844
- * Check whether an operation should clear the redos stack.
845
- */
846
- const shouldClear = (op) => {
847
- if (op.type === 'set_selection') {
848
- return false;
849
- }
850
- return true;
851
- };
852
- const PlaitHistoryBoard = {
853
- /**
854
- * Get the saving flag's current value.
855
- */
856
- isSaving(board) {
857
- return SAVING.get(board);
858
- },
859
- /**
860
- * Get the merge flag's current value.
861
- */
862
- isMerging(board) {
863
- return MERGING.get(board);
864
- },
865
- /**
866
- * Apply a series of changes inside a synchronous `fn`, without merging any of
867
- * the new operations into previous save point in the history.
868
- */
869
- withoutMerging(board, fn) {
870
- const prev = PlaitHistoryBoard.isMerging(board);
871
- MERGING.set(board, false);
872
- fn();
873
- MERGING.set(board, prev);
874
- },
875
- /**
876
- * Apply a series of changes inside a synchronous `fn`, without saving any of
877
- * their operations into the history.
878
- */
879
- withoutSaving(board, fn) {
880
- const prev = PlaitHistoryBoard.isSaving(board);
881
- SAVING.set(board, false);
882
- fn();
883
- SAVING.set(board, prev);
884
- }
885
- };
886
902
 
887
903
  function withHistory(board) {
888
904
  const { apply, keydown } = board;
@@ -1140,7 +1156,7 @@ class PlaitToolbarComponent {
1140
1156
  this.resetZoomHandel = new EventEmitter();
1141
1157
  }
1142
1158
  set viewZoom(zoom) {
1143
- this._viewZoom = Math.floor(zoom * 100);
1159
+ this._viewZoom = Number(((zoom ?? 1) * 100).toFixed(0));
1144
1160
  }
1145
1161
  get viewZoom() {
1146
1162
  return this._viewZoom;
@@ -1202,6 +1218,8 @@ class PlaitBoardComponent {
1202
1218
  this.destroy$ = new Subject();
1203
1219
  this.autoFitPadding = 8;
1204
1220
  this.isMoving = false;
1221
+ this.focusPoint = [];
1222
+ this.matrix = [];
1205
1223
  this.plaitValue = [];
1206
1224
  this.plaitPlugins = [];
1207
1225
  this.plaitChange = new EventEmitter();
@@ -1248,10 +1266,18 @@ class PlaitBoardComponent {
1248
1266
  if (this.board.operations.some(op => PlaitOperation.isSetViewportOperation(op))) {
1249
1267
  this.updateViewport();
1250
1268
  }
1269
+ if (this.board.operations.some(op => ['set_node', 'remove_node'].includes(op.type))) {
1270
+ this.calculateViewport();
1271
+ }
1251
1272
  this.plaitChange.emit(changeEvent);
1252
1273
  });
1253
1274
  this.hasInitialized = true;
1254
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
+ }
1255
1281
  ngOnChanges(changes) {
1256
1282
  if (this.hasInitialized) {
1257
1283
  const valueChange = changes['plaitValue'];
@@ -1391,6 +1417,39 @@ class PlaitBoardComponent {
1391
1417
  offsetYRatio: scrollTopRatio
1392
1418
  });
1393
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
+ }
1394
1453
  viewportChange() {
1395
1454
  const viewBox = getViewBox(this.board);
1396
1455
  const offsetXRatio = this.board.viewport.offsetXRatio;
@@ -1406,15 +1465,13 @@ class PlaitBoardComponent {
1406
1465
  if (width > 0 && height > 0) {
1407
1466
  this.renderer2.setAttribute(this.host, 'viewBox', box.join());
1408
1467
  }
1409
- const container = this.contentContainer.nativeElement;
1410
- container.scrollTo({
1411
- top: this.scrollTop,
1412
- left: this.scrollLeft
1413
- });
1468
+ this.focusPoint = [viewportBox.x, viewportBox.y];
1469
+ this.setMatrix();
1414
1470
  }
1415
1471
  updateViewport() {
1416
1472
  this.resizeViewport();
1417
1473
  this.viewportChange();
1474
+ this.updateScroll();
1418
1475
  }
1419
1476
  // 拖拽模式
1420
1477
  changeMoveMode(cursorStatus) {
@@ -1591,5 +1648,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1591
1648
  * Generated bundle index. Do not edit.
1592
1649
  */
1593
1650
 
1594
- 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, transformViewZoom, transformZoom, 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 };
1595
1652
  //# sourceMappingURL=plait-core.mjs.map