@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
  /**
@@ -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,40 @@ 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;
902
+ function isOutExtent(board, node, gap) {
903
+ const result = { x: 0, y: 0 };
904
+ if (!node)
905
+ return result;
906
+ const boardComponent = PLAIT_BOARD_TO_COMPONENT.get(board);
907
+ const scrollBarWidth = board.options.hideScrollbar ? SCROLL_BAR_WIDTH : 0;
908
+ const canvasRect = boardComponent.contentContainer.nativeElement.getBoundingClientRect();
909
+ if (node.left < canvasRect.left + gap) {
910
+ result.x = canvasRect.left - node.left - gap;
819
911
  }
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;
912
+ else if (node.right > canvasRect.right - scrollBarWidth - gap) {
913
+ result.x = canvasRect.right - scrollBarWidth - gap - node.right - node.width;
828
914
  }
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;
915
+ if (node.top < canvasRect.top + gap) {
916
+ result.y = canvasRect.top - node.top - gap;
837
917
  }
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);
918
+ else if (node.bottom > canvasRect.bottom - scrollBarWidth - gap) {
919
+ result.y = canvasRect.bottom - scrollBarWidth - gap - node.bottom - node.height;
872
920
  }
873
- };
921
+ return result;
922
+ }
874
923
 
875
924
  function withHistory(board) {
876
925
  const { apply, keydown } = board;
@@ -1190,6 +1239,8 @@ class PlaitBoardComponent {
1190
1239
  this.destroy$ = new Subject();
1191
1240
  this.autoFitPadding = 8;
1192
1241
  this.isMoving = false;
1242
+ this.focusPoint = [];
1243
+ this.matrix = [];
1193
1244
  this.plaitValue = [];
1194
1245
  this.plaitPlugins = [];
1195
1246
  this.plaitChange = new EventEmitter();
@@ -1236,10 +1287,18 @@ class PlaitBoardComponent {
1236
1287
  if (this.board.operations.some(op => PlaitOperation.isSetViewportOperation(op))) {
1237
1288
  this.updateViewport();
1238
1289
  }
1290
+ if (this.board.operations.some(op => ['set_node', 'remove_node'].includes(op.type))) {
1291
+ this.calculateViewport();
1292
+ }
1239
1293
  this.plaitChange.emit(changeEvent);
1240
1294
  });
1241
1295
  this.hasInitialized = true;
1242
1296
  }
1297
+ setMatrix() {
1298
+ const viewBox = getViewBox(this.board);
1299
+ const zoom = this.board.viewport.zoom;
1300
+ this.matrix = [zoom, 0, 0, 0, zoom, 0, -this.scrollLeft - zoom * viewBox.minX, -this.scrollTop - zoom * viewBox.minY, 1];
1301
+ }
1243
1302
  ngOnChanges(changes) {
1244
1303
  if (this.hasInitialized) {
1245
1304
  const valueChange = changes['plaitValue'];
@@ -1379,6 +1438,39 @@ class PlaitBoardComponent {
1379
1438
  offsetYRatio: scrollTopRatio
1380
1439
  });
1381
1440
  }
1441
+ updateScroll() {
1442
+ const container = this.contentContainer.nativeElement;
1443
+ container.scrollTo({
1444
+ top: this.scrollTop,
1445
+ left: this.scrollLeft
1446
+ });
1447
+ }
1448
+ calculateViewport() {
1449
+ const viewBox = getViewBox(this.board);
1450
+ const { minX, minY, viewportWidth } = viewBox;
1451
+ const viewportBox = getViewportClientBox(this.board);
1452
+ const nweHhBox = calculateBBox(this.board);
1453
+ let scrollLeft = this.scrollLeft;
1454
+ let scrollTop = this.scrollTop;
1455
+ const zoom = this.board.viewport.zoom;
1456
+ const matrix = this.matrix;
1457
+ const focusPoint = this.focusPoint;
1458
+ if (matrix) {
1459
+ const g = [focusPoint[0] - viewportBox.x, focusPoint[1] - viewportBox.y, 1];
1460
+ const b = invert([], matrix);
1461
+ const x = transformMat3([], [g[0], g[1], 1], b);
1462
+ const k = [zoom, 0, 0, 0, zoom, 0, -zoom * minX, -zoom * minY, 1];
1463
+ const c = transformMat3([], x, k);
1464
+ scrollLeft = c[0] - g[0];
1465
+ scrollTop = c[1] - g[1];
1466
+ }
1467
+ else {
1468
+ scrollLeft = (viewportWidth - viewportBox.width) / 2;
1469
+ scrollTop = viewportBox.height / 2 - nweHhBox.top;
1470
+ }
1471
+ this.setScroll(scrollLeft, scrollTop);
1472
+ this.updateViewport();
1473
+ }
1382
1474
  viewportChange() {
1383
1475
  const viewBox = getViewBox(this.board);
1384
1476
  const offsetXRatio = this.board.viewport.offsetXRatio;
@@ -1394,15 +1486,13 @@ class PlaitBoardComponent {
1394
1486
  if (width > 0 && height > 0) {
1395
1487
  this.renderer2.setAttribute(this.host, 'viewBox', box.join());
1396
1488
  }
1397
- const container = this.contentContainer.nativeElement;
1398
- container.scrollTo({
1399
- top: this.scrollTop,
1400
- left: this.scrollLeft
1401
- });
1489
+ this.focusPoint = [viewportBox.x, viewportBox.y];
1490
+ this.setMatrix();
1402
1491
  }
1403
1492
  updateViewport() {
1404
1493
  this.resizeViewport();
1405
1494
  this.viewportChange();
1495
+ this.updateScroll();
1406
1496
  }
1407
1497
  // 拖拽模式
1408
1498
  changeMoveMode(cursorStatus) {
@@ -1424,7 +1514,7 @@ class PlaitBoardComponent {
1424
1514
  zoom = 1;
1425
1515
  }
1426
1516
  this.setViewport({
1427
- zoom,
1517
+ zoom: calculateZoom(zoom),
1428
1518
  offsetXRatio: 0.5,
1429
1519
  offsetYRatio: 0.5
1430
1520
  });
@@ -1467,7 +1557,7 @@ class PlaitBoardComponent {
1467
1557
  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 });
1468
1558
  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: `
1469
1559
  <div class="container" #container>
1470
- <svg #svg width="100%" height="100%" style="position: relative"></svg>
1560
+ <svg #svg width="100%" height="100%" style="position: relative;"></svg>
1471
1561
  <plait-element
1472
1562
  *ngFor="let item of board.children; let index = index; trackBy: trackBy"
1473
1563
  [index]="index"
@@ -1496,7 +1586,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1496
1586
  selector: 'plait-board',
1497
1587
  template: `
1498
1588
  <div class="container" #container>
1499
- <svg #svg width="100%" height="100%" style="position: relative"></svg>
1589
+ <svg #svg width="100%" height="100%" style="position: relative;"></svg>
1500
1590
  <plait-element
1501
1591
  *ngFor="let item of board.children; let index = index; trackBy: trackBy"
1502
1592
  [index]="index"
@@ -1579,5 +1669,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1579
1669
  * Generated bundle index. Do not edit.
1580
1670
  */
1581
1671
 
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 };
1672
+ 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 };
1583
1673
  //# sourceMappingURL=plait-core.mjs.map