@plait/draw 0.76.0 → 0.77.0
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/constants/default.d.ts +4 -0
- package/constants/index.d.ts +1 -0
- package/esm2022/constants/default.mjs +6 -1
- package/esm2022/constants/index.mjs +2 -1
- package/esm2022/geometry.component.mjs +2 -3
- package/esm2022/image.component.mjs +2 -4
- package/esm2022/plugins/with-arrow-line-text.mjs +20 -8
- package/esm2022/plugins/with-draw-resize.mjs +23 -18
- package/esm2022/plugins/with-geometry-create.mjs +7 -7
- package/esm2022/plugins/with-table-resize.mjs +11 -7
- package/esm2022/plugins/with-table.mjs +8 -5
- package/esm2022/table.component.mjs +2 -3
- package/esm2022/utils/common.mjs +6 -3
- package/esm2022/utils/geometry.mjs +5 -62
- package/esm2022/utils/table-selected.mjs +1 -5
- package/esm2022/utils/table.mjs +3 -3
- package/esm2022/utils/uml.mjs +7 -5
- package/fesm2022/plait-draw.mjs +1380 -1413
- package/fesm2022/plait-draw.mjs.map +1 -1
- package/package.json +1 -1
- package/plugins/with-arrow-line-text.d.ts +1 -0
- package/plugins/with-draw-resize.d.ts +1 -0
- package/utils/common.d.ts +1 -0
- package/utils/geometry.d.ts +18 -19
- package/utils/table-selected.d.ts +0 -1
package/fesm2022/plait-draw.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ACTIVE_STROKE_WIDTH, DEFAULT_COLOR, ThemeColorMode, PlaitElement, RectangleClient, getSelectedElements, idCreator,
|
|
2
|
-
import { DEFAULT_FILL, Alignment,
|
|
3
|
-
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
1
|
+
import { ACTIVE_STROKE_WIDTH, DEFAULT_COLOR, ThemeColorMode, PlaitElement, RectangleClient, getSelectedElements, idCreator, createDebugGenerator, Point, createG, arrowPoints, createPath, distanceBetweenPointAndPoint, drawLinearPath, rotate, catmullRomFitting, PlaitBoard, setStrokeLinecap, findElements, createMask, createRect, setPathStrokeLinecap, getNearestPointBetweenPointAndArc, distanceBetweenPointAndSegments, HIT_DISTANCE_BUFFER, isPointInPolygon, isLineHitRectangle, rotatePointsByAngle, rotateAntiPointsByElement, getEllipseArcCenter, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType, depthFirstRecursion, getIsRecursionFunc, SNAPPING_STROKE_WIDTH, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, getI18nValue, toActiveRectangleFromViewBoxRectangle, getElementById, rotatePointsByElement, PlaitNode, hasValidAngle, toViewBoxPoint, toHostPoint, Direction, rotatePoints, getRectangleByElements, getSelectionAngle, rotatedDataPoints, isAxisChangedByAngle, isSelectionMoving, drawRectangle, getRectangleByAngle, getSnapRectangles, getTripleAxis, getMinPointDelta, SNAP_TOLERANCE, drawPointSnapLines, drawSolidLines, getNearestPointBetweenPointAndSegments, isPointInEllipse, getNearestPointBetweenPointAndEllipse, getEllipseTangentSlope, getVectorFromPointAndSlope, drawRoundRectangle, isPointInRoundRectangle, getCrossingPointsBetweenEllipseAndSegment, drawLine, getNearestPointBetweenPointAndDiscreteSegments, getNearestPointBetweenPointAndSegment, Path, RgbaToHEX, SELECTION_RECTANGLE_CLASS_NAME, toActivePointFromViewBoxPoint, getHitElementByPoint, WritableClipboardOperationType, WritableClipboardType, addOrCreateClipboardContext, setAngleForG, CursorClass, toActivePoint, temporaryDisableSelection, toScreenPointFromActivePoint, PRESS_AND_MOVE_BUFFER, isMainPointer, throttleRAF, getAngleBetweenPoints, normalizeAngle, degreesToRadians, rotateElements, MERGING, ROTATE_HANDLE_CLASS_NAME, isSelectedElement, isDragging } from '@plait/core';
|
|
2
|
+
import { DEFAULT_FILL, Alignment, getMemorizedLatest, memorizeLatest, WithTextPluginKey, TextManage, StrokeStyle, removeDuplicatePoints, generateElbowLineRoute, simplifyOrthogonalPoints, getExtendPoint, getUnitVectorByPointAndPoint, Generator, getPointByVectorComponent, getStrokeLineDash, getPointOnPolyline, buildText, getCrossingPointsBetweenPointAndSegment, isPointOnSegment, getFirstTextEditor, sortElementsByArea, isFilled, getTextEditorsByElement, RESIZE_HANDLE_DIAMETER, measureElement, DEFAULT_FONT_FAMILY, getFirstTextManage, isSourceAndTargetIntersect, getPoints, DEFAULT_ROUTE_MARGIN, normalizeShapePoints, resetPointsAfterResize, getDirectionByVector, getRectangleResizeHandleRefs, getRotatedResizeCursorClassByAngle, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, isCornerHandle, getIndexByResizeHandle, withResize, getSymmetricHandleIndex, getResizeHandlePointByIndex, drawHandle, getDirectionFactorByDirectionComponent, buildClipboardData as buildClipboardData$1, insertClipboardData as insertClipboardData$1, getDirectionByPointOfRectangle, getDirectionFactor, rotateVector, getOppositeDirection, rotateVectorAnti90, getSourceAndTargetOuterRectangle, getNextPoint, PRIMARY_COLOR, CommonElementFlavour, createActiveGenerator, hasResizeHandle, ActiveGenerator, drawPrimaryHandle, drawFillPrimaryHandle, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, getElementsText, acceptImageTypes, getElementOfFocusedImage, buildImage, isResizingByCondition, getRatioByPoint, getTextManages, ImageGenerator, ResizeHandle, addRotating, removeRotating, drawRotateHandle } from '@plait/common';
|
|
4
3
|
import { TEXT_DEFAULT_HEIGHT, DEFAULT_FONT_SIZE, AlignEditor } from '@plait/text-plugins';
|
|
4
|
+
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
5
5
|
import { Editor, Node } from 'slate';
|
|
6
6
|
import { isKeyHotkey } from 'is-hotkey';
|
|
7
7
|
|
|
@@ -114,6 +114,11 @@ const PlaitTableElement = {
|
|
|
114
114
|
};
|
|
115
115
|
|
|
116
116
|
const WithDrawPluginKey = 'plait-draw-plugin-key';
|
|
117
|
+
var DrawI18nKey;
|
|
118
|
+
(function (DrawI18nKey) {
|
|
119
|
+
DrawI18nKey["lineText"] = "line-text";
|
|
120
|
+
DrawI18nKey["geometryText"] = "geometry-text";
|
|
121
|
+
})(DrawI18nKey || (DrawI18nKey = {}));
|
|
117
122
|
|
|
118
123
|
const ShapeDefaultSpace = {
|
|
119
124
|
rectangleAndText: 4
|
|
@@ -461,6 +466,18 @@ const DefaultSwimlanePropertyMap = {
|
|
|
461
466
|
|
|
462
467
|
const MIN_TEXT_WIDTH = 5;
|
|
463
468
|
|
|
469
|
+
const DefaultLineStyle = {
|
|
470
|
+
strokeWidth: 2,
|
|
471
|
+
strokeColor: '#000'
|
|
472
|
+
};
|
|
473
|
+
const LINE_TEXT_SPACE = 4;
|
|
474
|
+
const LINE_AUTO_COMPLETE_DIAMETER = 6;
|
|
475
|
+
const LINE_AUTO_COMPLETE_OPACITY = 0.6;
|
|
476
|
+
const LINE_AUTO_COMPLETE_HOVERED_OPACITY = 0.8;
|
|
477
|
+
const LINE_AUTO_COMPLETE_HOVERED_DIAMETER = 10;
|
|
478
|
+
const LINE_ALIGN_TOLERANCE = 3;
|
|
479
|
+
const LINE_TEXT = '文本';
|
|
480
|
+
|
|
464
481
|
const getElementShape = (value) => {
|
|
465
482
|
if (PlaitDrawElement.isImage(value)) {
|
|
466
483
|
return BasicShapes.rectangle;
|
|
@@ -471,6 +488,97 @@ const getElementShape = (value) => {
|
|
|
471
488
|
return value.shape;
|
|
472
489
|
};
|
|
473
490
|
|
|
491
|
+
const SHAPE_MAX_LENGTH = 6;
|
|
492
|
+
const memorizedShape = new WeakMap();
|
|
493
|
+
const getMemorizeKey = (element) => {
|
|
494
|
+
let key = '';
|
|
495
|
+
switch (true) {
|
|
496
|
+
case PlaitDrawElement.isText(element): {
|
|
497
|
+
key = MemorizeKey.text;
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
case PlaitDrawElement.isBasicShape(element): {
|
|
501
|
+
key = MemorizeKey.basicShape;
|
|
502
|
+
break;
|
|
503
|
+
}
|
|
504
|
+
case PlaitDrawElement.isFlowchart(element): {
|
|
505
|
+
key = MemorizeKey.flowchart;
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
case PlaitDrawElement.isArrowLine(element): {
|
|
509
|
+
key = MemorizeKey.arrowLine;
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
case PlaitDrawElement.isUML(element): {
|
|
513
|
+
key = MemorizeKey.UML;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return key;
|
|
517
|
+
};
|
|
518
|
+
const getLineMemorizedLatest = () => {
|
|
519
|
+
const properties = getMemorizedLatest(MemorizeKey.arrowLine);
|
|
520
|
+
return { ...properties } || {};
|
|
521
|
+
};
|
|
522
|
+
const getMemorizedLatestByPointer = (pointer) => {
|
|
523
|
+
let memorizeKey = '';
|
|
524
|
+
if (PlaitDrawElement.isBasicShape({ shape: pointer })) {
|
|
525
|
+
memorizeKey = pointer === BasicShapes.text ? MemorizeKey.text : MemorizeKey.basicShape;
|
|
526
|
+
}
|
|
527
|
+
else if (PlaitDrawElement.isUML({ shape: pointer })) {
|
|
528
|
+
memorizeKey = MemorizeKey.UML;
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
memorizeKey = MemorizeKey.flowchart;
|
|
532
|
+
}
|
|
533
|
+
const properties = { ...getMemorizedLatest(memorizeKey) } || {};
|
|
534
|
+
const textProperties = { ...properties.text } || {};
|
|
535
|
+
delete properties.text;
|
|
536
|
+
return { textProperties, geometryProperties: properties };
|
|
537
|
+
};
|
|
538
|
+
const memorizeLatestText = (element, operations) => {
|
|
539
|
+
const memorizeKey = getMemorizeKey(element);
|
|
540
|
+
let textMemory = getMemorizedLatest(memorizeKey)?.text || {};
|
|
541
|
+
const setNodeOperation = operations.find(operation => operation.type === 'set_node');
|
|
542
|
+
if (setNodeOperation) {
|
|
543
|
+
const { properties, newProperties } = setNodeOperation;
|
|
544
|
+
for (const key in newProperties) {
|
|
545
|
+
const value = newProperties[key];
|
|
546
|
+
if (value == null) {
|
|
547
|
+
delete textMemory[key];
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
textMemory[key] = value;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
for (const key in properties) {
|
|
554
|
+
if (!newProperties.hasOwnProperty(key)) {
|
|
555
|
+
delete textMemory[key];
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
memorizeLatest(memorizeKey, 'text', textMemory);
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
const memorizeLatestShape = (board, shape) => {
|
|
562
|
+
const shapes = memorizedShape.has(board) ? memorizedShape.get(board) : [];
|
|
563
|
+
const shapeIndex = shapes.indexOf(shape);
|
|
564
|
+
if (shape === BasicShapes.text || shapeIndex === 0) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (shapeIndex !== -1) {
|
|
568
|
+
shapes.splice(shapeIndex, 1);
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
if (shapes.length === SHAPE_MAX_LENGTH) {
|
|
572
|
+
shapes.pop();
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
shapes.unshift(shape);
|
|
576
|
+
memorizedShape.set(board, shapes);
|
|
577
|
+
};
|
|
578
|
+
const getMemorizedLatestShape = (board) => {
|
|
579
|
+
return memorizedShape.get(board);
|
|
580
|
+
};
|
|
581
|
+
|
|
474
582
|
// TODO: 是否可以完全基于位置定位 TextManager,实现 line 和 多文本 geometry 统一
|
|
475
583
|
// 一个元素有多个文本时,单纯通过位置无法获取 TextManage,因此这里单独通过 Map 保存关键字 key 和 TextManage 的对应关系
|
|
476
584
|
// 1. 单文本元素 key 就是元素的 id
|
|
@@ -602,10 +710,6 @@ const isSingleSelectTable = (board) => {
|
|
|
602
710
|
const selectedElements = getSelectedElements(board);
|
|
603
711
|
return selectedElements && selectedElements.length === 1 && PlaitDrawElement.isElementByTable(selectedElements[0]);
|
|
604
712
|
};
|
|
605
|
-
const isSingleSelectElementByTable = (board) => {
|
|
606
|
-
const selectedElements = getSelectedElements(board);
|
|
607
|
-
return selectedElements && selectedElements.length === 1 && PlaitDrawElement.isElementByTable(selectedElements[0]);
|
|
608
|
-
};
|
|
609
713
|
const getSelectedTableElements = (board, elements) => {
|
|
610
714
|
const selectedElements = elements?.length ? elements : getSelectedElements(board);
|
|
611
715
|
return selectedElements.filter(value => PlaitDrawElement.isElementByTable(value));
|
|
@@ -774,7 +878,7 @@ const createCell = (rowId, columnId, text = null) => {
|
|
|
774
878
|
return cell;
|
|
775
879
|
};
|
|
776
880
|
const getSelectedTableCellsEditor = (board) => {
|
|
777
|
-
if (
|
|
881
|
+
if (isSingleSelectTable(board)) {
|
|
778
882
|
const elements = getSelectedTableElements(board);
|
|
779
883
|
const selectedCells = getSelectedCells(elements[0]);
|
|
780
884
|
const selectedCellsEditor = selectedCells?.map(cell => {
|
|
@@ -788,1458 +892,1358 @@ const getSelectedTableCellsEditor = (board) => {
|
|
|
788
892
|
return undefined;
|
|
789
893
|
};
|
|
790
894
|
|
|
791
|
-
const
|
|
792
|
-
const
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
switch (true) {
|
|
796
|
-
case PlaitDrawElement.isText(element): {
|
|
797
|
-
key = MemorizeKey.text;
|
|
798
|
-
break;
|
|
799
|
-
}
|
|
800
|
-
case PlaitDrawElement.isBasicShape(element): {
|
|
801
|
-
key = MemorizeKey.basicShape;
|
|
802
|
-
break;
|
|
803
|
-
}
|
|
804
|
-
case PlaitDrawElement.isFlowchart(element): {
|
|
805
|
-
key = MemorizeKey.flowchart;
|
|
806
|
-
break;
|
|
807
|
-
}
|
|
808
|
-
case PlaitDrawElement.isArrowLine(element): {
|
|
809
|
-
key = MemorizeKey.arrowLine;
|
|
810
|
-
break;
|
|
811
|
-
}
|
|
812
|
-
case PlaitDrawElement.isUML(element): {
|
|
813
|
-
key = MemorizeKey.UML;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
return key;
|
|
895
|
+
const getStrokeColorByElement = (board, element) => {
|
|
896
|
+
const defaultColor = getDrawDefaultStrokeColor(board.theme.themeColorMode);
|
|
897
|
+
const strokeColor = element.strokeColor || defaultColor;
|
|
898
|
+
return strokeColor;
|
|
817
899
|
};
|
|
818
|
-
const
|
|
819
|
-
const
|
|
820
|
-
|
|
900
|
+
const getFillByElement = (board, element) => {
|
|
901
|
+
const defaultFill = PlaitDrawElement.isFlowchart(element) && isClosedDrawElement(element)
|
|
902
|
+
? getFlowchartDefaultFill(board.theme.themeColorMode)
|
|
903
|
+
: DefaultDrawStyle.fill;
|
|
904
|
+
const fill = element.fill || defaultFill;
|
|
905
|
+
return fill;
|
|
821
906
|
};
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
907
|
+
const getStrokeStyleByElement = (board, element) => {
|
|
908
|
+
return element.strokeStyle || StrokeStyle.solid;
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
const debugKey$4 = 'debug:plait:line-mirror';
|
|
912
|
+
const debugGenerator$4 = createDebugGenerator(debugKey$4);
|
|
913
|
+
const alignPoints = (basePoint, movingPoint) => {
|
|
914
|
+
const newPoint = [...movingPoint];
|
|
915
|
+
if (Point.isVertical(newPoint, basePoint, LINE_ALIGN_TOLERANCE)) {
|
|
916
|
+
newPoint[0] = basePoint[0];
|
|
829
917
|
}
|
|
830
|
-
|
|
831
|
-
|
|
918
|
+
if (Point.isHorizontal(newPoint, basePoint, LINE_ALIGN_TOLERANCE)) {
|
|
919
|
+
newPoint[1] = basePoint[1];
|
|
832
920
|
}
|
|
833
|
-
|
|
834
|
-
const textProperties = { ...properties.text } || {};
|
|
835
|
-
delete properties.text;
|
|
836
|
-
return { textProperties, geometryProperties: properties };
|
|
921
|
+
return newPoint;
|
|
837
922
|
};
|
|
838
|
-
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
}
|
|
853
|
-
for (const key in properties) {
|
|
854
|
-
if (!newProperties.hasOwnProperty(key)) {
|
|
855
|
-
delete textMemory[key];
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
memorizeLatest(memorizeKey, 'text', textMemory);
|
|
923
|
+
function getResizedPreviousAndNextPoint(nextRenderPoints, sourcePoint, targetPoint, handleIndex) {
|
|
924
|
+
const referencePoint = {
|
|
925
|
+
previous: null,
|
|
926
|
+
next: null
|
|
927
|
+
};
|
|
928
|
+
const startPoint = nextRenderPoints[handleIndex];
|
|
929
|
+
const endPoint = nextRenderPoints[handleIndex + 1];
|
|
930
|
+
const isHorizontal = Point.isHorizontal(startPoint, endPoint);
|
|
931
|
+
const isVertical = Point.isVertical(startPoint, endPoint);
|
|
932
|
+
const previousPoint = nextRenderPoints[handleIndex - 1] ?? nextRenderPoints[0];
|
|
933
|
+
const beforePreviousPoint = nextRenderPoints[handleIndex - 2] ?? sourcePoint;
|
|
934
|
+
if ((isHorizontal && Point.isHorizontal(beforePreviousPoint, previousPoint)) ||
|
|
935
|
+
(isVertical && Point.isVertical(beforePreviousPoint, previousPoint))) {
|
|
936
|
+
referencePoint.previous = previousPoint;
|
|
859
937
|
}
|
|
860
|
-
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
if (shape === BasicShapes.text || shapeIndex === 0) {
|
|
865
|
-
return;
|
|
938
|
+
const nextPoint = nextRenderPoints[handleIndex + 2] ?? nextRenderPoints[nextRenderPoints.length - 1];
|
|
939
|
+
const afterNextPoint = nextRenderPoints[handleIndex + 3] ?? targetPoint;
|
|
940
|
+
if ((isHorizontal && Point.isHorizontal(nextPoint, afterNextPoint)) || (isVertical && Point.isVertical(nextPoint, afterNextPoint))) {
|
|
941
|
+
referencePoint.next = nextPoint;
|
|
866
942
|
}
|
|
867
|
-
|
|
868
|
-
|
|
943
|
+
return referencePoint;
|
|
944
|
+
}
|
|
945
|
+
function alignElbowSegment(startKeyPoint, endKeyPoint, resizeState, resizedPreviousAndNextPoint) {
|
|
946
|
+
let newStartPoint = startKeyPoint;
|
|
947
|
+
let newEndPoint = endKeyPoint;
|
|
948
|
+
if (Point.isHorizontal(startKeyPoint, endKeyPoint)) {
|
|
949
|
+
const offsetY = Point.getOffsetY(resizeState.startPoint, resizeState.endPoint);
|
|
950
|
+
let pointY = startKeyPoint[1] + offsetY;
|
|
951
|
+
if (resizedPreviousAndNextPoint.previous && Math.abs(resizedPreviousAndNextPoint.previous[1] - pointY) < LINE_ALIGN_TOLERANCE) {
|
|
952
|
+
pointY = resizedPreviousAndNextPoint.previous[1];
|
|
953
|
+
}
|
|
954
|
+
else if (resizedPreviousAndNextPoint.next && Math.abs(resizedPreviousAndNextPoint.next[1] - pointY) < LINE_ALIGN_TOLERANCE) {
|
|
955
|
+
pointY = resizedPreviousAndNextPoint.next[1];
|
|
956
|
+
}
|
|
957
|
+
newStartPoint = [startKeyPoint[0], pointY];
|
|
958
|
+
newEndPoint = [endKeyPoint[0], pointY];
|
|
869
959
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
960
|
+
if (Point.isVertical(startKeyPoint, endKeyPoint)) {
|
|
961
|
+
const offsetX = Point.getOffsetX(resizeState.startPoint, resizeState.endPoint);
|
|
962
|
+
let pointX = startKeyPoint[0] + offsetX;
|
|
963
|
+
if (resizedPreviousAndNextPoint.previous && Math.abs(resizedPreviousAndNextPoint.previous[0] - pointX) < LINE_ALIGN_TOLERANCE) {
|
|
964
|
+
pointX = resizedPreviousAndNextPoint.previous[0];
|
|
965
|
+
}
|
|
966
|
+
else if (resizedPreviousAndNextPoint.next && Math.abs(resizedPreviousAndNextPoint.next[0] - pointX) < LINE_ALIGN_TOLERANCE) {
|
|
967
|
+
pointX = resizedPreviousAndNextPoint.next[0];
|
|
873
968
|
}
|
|
969
|
+
newStartPoint = [pointX, startKeyPoint[1]];
|
|
970
|
+
newEndPoint = [pointX, endKeyPoint[1]];
|
|
874
971
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
const texts = element.texts;
|
|
884
|
-
if (!texts.length)
|
|
885
|
-
return -1;
|
|
886
|
-
const points = getArrowLinePoints(board, element);
|
|
887
|
-
return texts.findIndex(text => {
|
|
888
|
-
const center = getPointOnPolyline(points, text.position);
|
|
889
|
-
const rectangle = {
|
|
890
|
-
x: center[0] - text.width / 2,
|
|
891
|
-
y: center[1] - text.height / 2,
|
|
892
|
-
width: text.width,
|
|
893
|
-
height: text.height
|
|
894
|
-
};
|
|
895
|
-
return RectangleClient.isHit(rectangle, RectangleClient.getRectangleByPoints([point, point]));
|
|
896
|
-
});
|
|
897
|
-
};
|
|
898
|
-
|
|
899
|
-
const isMultipleTextShape = (shape) => {
|
|
900
|
-
return GEOMETRY_WITH_MULTIPLE_TEXT.includes(shape);
|
|
901
|
-
};
|
|
902
|
-
const isMultipleTextGeometry = (geometry) => {
|
|
903
|
-
return PlaitDrawElement.isGeometry(geometry) && isMultipleTextShape(geometry.shape);
|
|
904
|
-
};
|
|
905
|
-
const getMultipleTextGeometryTextKeys = (shape) => {
|
|
906
|
-
return MultipleTextGeometryTextKeys[shape];
|
|
907
|
-
};
|
|
908
|
-
const createMultipleTextGeometryElement = (shape, points, options = {}) => {
|
|
909
|
-
const id = idCreator();
|
|
910
|
-
const drawShapeTexts = buildDefaultTextsByShape(shape);
|
|
911
|
-
return {
|
|
912
|
-
id,
|
|
913
|
-
type: 'geometry',
|
|
914
|
-
shape,
|
|
915
|
-
angle: 0,
|
|
916
|
-
opacity: 1,
|
|
917
|
-
texts: drawShapeTexts,
|
|
918
|
-
points,
|
|
919
|
-
...options
|
|
920
|
-
};
|
|
921
|
-
};
|
|
922
|
-
const buildDefaultTextsByShape = (shape) => {
|
|
923
|
-
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
924
|
-
const textProperties = { ...memorizedLatest.textProperties };
|
|
925
|
-
const alignment = textProperties?.align;
|
|
926
|
-
const textHeight = textProperties?.textHeight || DefaultTextProperty.height;
|
|
927
|
-
delete textProperties?.align;
|
|
928
|
-
delete textProperties?.textHeight;
|
|
929
|
-
const defaultTexts = getDefaultGeometryProperty(shape)?.texts || [];
|
|
930
|
-
const textKeys = getMultipleTextGeometryTextKeys(shape);
|
|
931
|
-
return (textKeys || []).map((textKey) => {
|
|
932
|
-
const text = defaultTexts?.find((item) => item?.key === textKey);
|
|
972
|
+
return [newStartPoint, newEndPoint];
|
|
973
|
+
}
|
|
974
|
+
function getIndexAndDeleteCountByKeyPoint(board, element, dataPoints, nextRenderPoints, handleIndex) {
|
|
975
|
+
let index = null;
|
|
976
|
+
let deleteCount = null;
|
|
977
|
+
const startKeyPoint = nextRenderPoints[handleIndex];
|
|
978
|
+
const endKeyPoint = nextRenderPoints[handleIndex + 1];
|
|
979
|
+
if (!startKeyPoint || !endKeyPoint) {
|
|
933
980
|
return {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
textHeight: textHeight
|
|
981
|
+
index,
|
|
982
|
+
deleteCount
|
|
937
983
|
};
|
|
938
|
-
});
|
|
939
|
-
};
|
|
940
|
-
const getHitMultipleGeometryText = (element, point) => {
|
|
941
|
-
const engine = getEngine(element.shape);
|
|
942
|
-
const rectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
943
|
-
let hitText;
|
|
944
|
-
if (engine.getTextRectangle) {
|
|
945
|
-
hitText = element.texts.find(text => {
|
|
946
|
-
const textRectangle = engine.getTextRectangle(element, { id: text.id });
|
|
947
|
-
return RectangleClient.isHit(rectangle, textRectangle);
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
|
-
return hitText;
|
|
951
|
-
};
|
|
952
|
-
|
|
953
|
-
const DefaultLineStyle = {
|
|
954
|
-
strokeWidth: 2,
|
|
955
|
-
strokeColor: '#000'
|
|
956
|
-
};
|
|
957
|
-
const LINE_TEXT_SPACE = 4;
|
|
958
|
-
const LINE_AUTO_COMPLETE_DIAMETER = 6;
|
|
959
|
-
const LINE_AUTO_COMPLETE_OPACITY = 0.6;
|
|
960
|
-
const LINE_AUTO_COMPLETE_HOVERED_OPACITY = 0.8;
|
|
961
|
-
const LINE_AUTO_COMPLETE_HOVERED_DIAMETER = 10;
|
|
962
|
-
const LINE_ALIGN_TOLERANCE = 3;
|
|
963
|
-
const LINE_TEXT = '文本';
|
|
964
|
-
|
|
965
|
-
class VectorLineShapeGenerator extends Generator {
|
|
966
|
-
canDraw(element) {
|
|
967
|
-
return true;
|
|
968
984
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
985
|
+
const midDataPoints = dataPoints.slice(1, -1);
|
|
986
|
+
const startIndex = midDataPoints.findIndex(item => Point.isEquals(item, startKeyPoint));
|
|
987
|
+
const endIndex = midDataPoints.findIndex(item => Point.isEquals(item, endKeyPoint));
|
|
988
|
+
if (Math.max(startIndex, endIndex) > -1) {
|
|
989
|
+
if (startIndex > -1 && endIndex > -1) {
|
|
990
|
+
return {
|
|
991
|
+
index: startIndex,
|
|
992
|
+
deleteCount: 2
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
if (startIndex > -1 && endIndex === -1) {
|
|
996
|
+
const isReplace = startIndex < midDataPoints.length - 1 &&
|
|
997
|
+
Point.isAlign([midDataPoints[startIndex], midDataPoints[startIndex + 1], startKeyPoint, endKeyPoint]);
|
|
998
|
+
if (isReplace) {
|
|
999
|
+
return {
|
|
1000
|
+
index: startIndex,
|
|
1001
|
+
deleteCount: 2
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
return {
|
|
1005
|
+
index: startIndex,
|
|
1006
|
+
deleteCount: 1
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
if (startIndex === -1 && endIndex > -1) {
|
|
1010
|
+
const isReplace = endIndex > 0 && Point.isAlign([midDataPoints[endIndex], midDataPoints[endIndex - 1], startKeyPoint, endKeyPoint]);
|
|
1011
|
+
if (isReplace) {
|
|
1012
|
+
return {
|
|
1013
|
+
index: endIndex - 1,
|
|
1014
|
+
deleteCount: 2
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
return {
|
|
1018
|
+
index: endIndex,
|
|
1019
|
+
deleteCount: 1
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
973
1022
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
const
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1023
|
+
else {
|
|
1024
|
+
for (let i = 0; i < midDataPoints.length - 1; i++) {
|
|
1025
|
+
const currentPoint = midDataPoints[i];
|
|
1026
|
+
const nextPoint = midDataPoints[i + 1];
|
|
1027
|
+
if (Point.isAlign([currentPoint, nextPoint, startKeyPoint, endKeyPoint])) {
|
|
1028
|
+
index = i;
|
|
1029
|
+
deleteCount = 2;
|
|
1030
|
+
break;
|
|
1031
|
+
}
|
|
1032
|
+
if (Point.isAlign([currentPoint, nextPoint, startKeyPoint])) {
|
|
1033
|
+
index = Math.min(i + 1, midDataPoints.length - 1);
|
|
1034
|
+
deleteCount = 1;
|
|
1035
|
+
break;
|
|
1036
|
+
}
|
|
1037
|
+
if (Point.isAlign([currentPoint, nextPoint, endKeyPoint])) {
|
|
1038
|
+
index = Math.max(i - 1, 0);
|
|
1039
|
+
deleteCount = 1;
|
|
1040
|
+
break;
|
|
1041
|
+
}
|
|
980
1042
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1043
|
+
}
|
|
1044
|
+
if (index === null) {
|
|
1045
|
+
deleteCount = 0;
|
|
1046
|
+
if (midDataPoints.length > 0) {
|
|
1047
|
+
const handleRefPair = getArrowLineHandleRefPair(board, element);
|
|
1048
|
+
const params = getElbowLineRouteOptions(board, element, handleRefPair);
|
|
1049
|
+
const keyPoints = removeDuplicatePoints(generateElbowLineRoute(params, board));
|
|
1050
|
+
const nextKeyPoints = simplifyOrthogonalPoints(keyPoints.slice(1, keyPoints.length - 1));
|
|
1051
|
+
const nextDataPoints = [nextRenderPoints[0], ...midDataPoints, nextRenderPoints[nextRenderPoints.length - 1]];
|
|
1052
|
+
const mirrorDataPoints = getMirrorDataPoints(board, nextDataPoints, nextKeyPoints, params);
|
|
1053
|
+
for (let i = handleIndex - 1; i >= 0; i--) {
|
|
1054
|
+
const previousIndex = mirrorDataPoints.slice(1, -1).findIndex(item => Point.isEquals(item, nextRenderPoints[i]));
|
|
1055
|
+
if (previousIndex > -1) {
|
|
1056
|
+
index = previousIndex + 1;
|
|
1057
|
+
break;
|
|
1058
|
+
}
|
|
984
1059
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1060
|
+
if (index === null) {
|
|
1061
|
+
index = 0;
|
|
1062
|
+
// When renderPoints is a straight line and dataPoints are not on the line,
|
|
1063
|
+
// the default 'deleteCount' is set to midDataPoints.length.
|
|
1064
|
+
if (Point.isAlign(nextRenderPoints)) {
|
|
1065
|
+
deleteCount = midDataPoints.length;
|
|
1066
|
+
}
|
|
989
1067
|
}
|
|
990
1068
|
}
|
|
991
|
-
|
|
992
|
-
|
|
1069
|
+
else {
|
|
1070
|
+
index = 0;
|
|
1071
|
+
}
|
|
993
1072
|
}
|
|
994
|
-
};
|
|
995
|
-
const createVectorLineElement = (shape, points, options) => {
|
|
996
1073
|
return {
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
shape,
|
|
1000
|
-
opacity: 1,
|
|
1001
|
-
points,
|
|
1002
|
-
...options
|
|
1074
|
+
index,
|
|
1075
|
+
deleteCount
|
|
1003
1076
|
};
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
const temporaryLineElement = createVectorLineElement(lineShape, [...points, movingPoint], {
|
|
1009
|
-
strokeWidth: DefaultLineStyle.strokeWidth,
|
|
1010
|
-
...memorizedLatest
|
|
1011
|
-
});
|
|
1012
|
-
const otherPoint = points[points.length - 1];
|
|
1013
|
-
temporaryLineElement.points[temporaryLineElement.points.length - 1] = alignPoints(otherPoint, movingPoint);
|
|
1014
|
-
lineGenerator.processDrawing(temporaryLineElement, lineShapeG);
|
|
1015
|
-
PlaitBoard.getElementTopHost(board).append(lineShapeG);
|
|
1016
|
-
return temporaryLineElement;
|
|
1017
|
-
};
|
|
1018
|
-
const drawVectorLine = (board, element) => {
|
|
1019
|
-
const strokeWidth = getStrokeWidthByElement(element);
|
|
1020
|
-
const strokeColor = getStrokeColorByElement(board, element);
|
|
1021
|
-
const strokeStyle = getStrokeStyleByElement(board, element);
|
|
1022
|
-
const strokeLineDash = getStrokeLineDash(strokeStyle, strokeWidth);
|
|
1023
|
-
const fill = getFillByElement(board, element);
|
|
1024
|
-
const options = { stroke: strokeColor, strokeWidth, strokeLineDash, fill };
|
|
1025
|
-
const lineG = createG();
|
|
1026
|
-
let points = getVectorLinePoints(board, element);
|
|
1027
|
-
const line = drawLinearPath(points, options);
|
|
1028
|
-
const id = idCreator();
|
|
1029
|
-
line.setAttribute('mask', `url(#${id})`);
|
|
1030
|
-
if (element.strokeStyle === StrokeStyle.dotted) {
|
|
1031
|
-
setStrokeLinecap(line, 'round');
|
|
1032
|
-
}
|
|
1033
|
-
lineG.appendChild(line);
|
|
1034
|
-
return lineG;
|
|
1035
|
-
};
|
|
1036
|
-
|
|
1037
|
-
const getCenterPointsOnPolygon$1 = (points) => {
|
|
1038
|
-
const centerPoints = [];
|
|
1039
|
-
for (let i = 0; i < points.length; i++) {
|
|
1040
|
-
let j = i == points.length - 1 ? 0 : i + 1;
|
|
1041
|
-
centerPoints.push([(points[i][0] + points[j][0]) / 2, (points[i][1] + points[j][1]) / 2]);
|
|
1042
|
-
}
|
|
1043
|
-
return centerPoints;
|
|
1044
|
-
};
|
|
1045
|
-
const getCrossingPointBetweenPointAndPolygon = (corners, point) => {
|
|
1046
|
-
const result = [];
|
|
1047
|
-
for (let index = 1; index <= corners.length; index++) {
|
|
1048
|
-
let start = corners[index - 1];
|
|
1049
|
-
let end = index === corners.length ? corners[0] : corners[index];
|
|
1050
|
-
const crossingPoint = getCrossingPointsBetweenPointAndSegment(point, start, end);
|
|
1051
|
-
result.push(...crossingPoint);
|
|
1077
|
+
}
|
|
1078
|
+
function getMirrorDataPoints(board, nextDataPoints, nextKeyPoints, params) {
|
|
1079
|
+
for (let index = 1; index < nextDataPoints.length - 2; index++) {
|
|
1080
|
+
adjustByCustomPointStartIndex(board, index, nextDataPoints, nextKeyPoints, params);
|
|
1052
1081
|
}
|
|
1053
|
-
return
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1082
|
+
return nextDataPoints;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* adjust based parallel segment
|
|
1086
|
+
*/
|
|
1087
|
+
const adjustByCustomPointStartIndex = (board, customPointStartIndex, nextDataPoints, nextKeyPoints, params) => {
|
|
1088
|
+
const beforePoint = nextDataPoints[customPointStartIndex - 1];
|
|
1089
|
+
const startPoint = nextDataPoints[customPointStartIndex];
|
|
1090
|
+
const endPoint = nextDataPoints[customPointStartIndex + 1];
|
|
1091
|
+
const afterPoint = nextDataPoints[customPointStartIndex + 2];
|
|
1092
|
+
const beforeSegment = [beforePoint, startPoint];
|
|
1093
|
+
const afterSegment = [endPoint, afterPoint];
|
|
1094
|
+
const isStraightWithBefore = Point.isAlign(beforeSegment);
|
|
1095
|
+
const isStraightWithAfter = Point.isAlign(afterSegment);
|
|
1096
|
+
let isAdjustStart = false;
|
|
1097
|
+
let isAdjustEnd = false;
|
|
1098
|
+
if (!isStraightWithBefore || !isStraightWithAfter) {
|
|
1099
|
+
const midKeyPointsWithBefore = getMidKeyPoints(nextKeyPoints, beforeSegment[0], beforeSegment[1]);
|
|
1100
|
+
const midKeyPointsWithAfter = getMidKeyPoints(nextKeyPoints, afterSegment[0], afterSegment[1]);
|
|
1101
|
+
const hasMidKeyPoints = midKeyPointsWithBefore.length > 0 && midKeyPointsWithAfter.length > 0;
|
|
1102
|
+
isAdjustStart = !isStraightWithBefore && !hasMidKeyPoints;
|
|
1103
|
+
isAdjustEnd = !isStraightWithAfter && !hasMidKeyPoints;
|
|
1062
1104
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
ry: yRadius * 1.2,
|
|
1076
|
-
xAxisRotation: 0,
|
|
1077
|
-
largeArcFlag: 1,
|
|
1078
|
-
sweepFlag: 1,
|
|
1079
|
-
endX: rectangle.x + divisionWidth * 2,
|
|
1080
|
-
endY: rectangle.y + divisionHeight / 2
|
|
1081
|
-
},
|
|
1082
|
-
{
|
|
1083
|
-
rx: xRadius,
|
|
1084
|
-
ry: yRadius,
|
|
1085
|
-
xAxisRotation: 0,
|
|
1086
|
-
largeArcFlag: 1,
|
|
1087
|
-
sweepFlag: 1,
|
|
1088
|
-
endX: rectangle.x + divisionWidth * 4.2,
|
|
1089
|
-
endY: rectangle.y + divisionHeight / 2.2
|
|
1090
|
-
},
|
|
1091
|
-
{
|
|
1092
|
-
rx: xRadius,
|
|
1093
|
-
ry: yRadius,
|
|
1094
|
-
xAxisRotation: 0,
|
|
1095
|
-
largeArcFlag: 1,
|
|
1096
|
-
sweepFlag: 1,
|
|
1097
|
-
endX: rectangle.x + divisionWidth * 5.8,
|
|
1098
|
-
endY: rectangle.y + divisionHeight
|
|
1099
|
-
},
|
|
1100
|
-
{
|
|
1101
|
-
rx: xRadius,
|
|
1102
|
-
ry: yRadius * 1.3,
|
|
1103
|
-
xAxisRotation: 0,
|
|
1104
|
-
largeArcFlag: 1,
|
|
1105
|
-
sweepFlag: 1,
|
|
1106
|
-
endX: rectangle.x + divisionWidth * 6,
|
|
1107
|
-
endY: rectangle.y + divisionHeight * 2.2
|
|
1108
|
-
},
|
|
1109
|
-
{
|
|
1110
|
-
rx: xRadius,
|
|
1111
|
-
ry: yRadius * 1.2,
|
|
1112
|
-
xAxisRotation: 0,
|
|
1113
|
-
largeArcFlag: 1,
|
|
1114
|
-
sweepFlag: 1,
|
|
1115
|
-
endX: rectangle.x + divisionWidth * 5,
|
|
1116
|
-
endY: rectangle.y + divisionHeight * 2.8
|
|
1117
|
-
},
|
|
1118
|
-
{
|
|
1119
|
-
rx: xRadius,
|
|
1120
|
-
ry: yRadius / 1.2,
|
|
1121
|
-
xAxisRotation: 0,
|
|
1122
|
-
largeArcFlag: 1,
|
|
1123
|
-
sweepFlag: 1,
|
|
1124
|
-
endX: rectangle.x + divisionWidth * 2.8,
|
|
1125
|
-
endY: rectangle.y + divisionHeight * 2.8
|
|
1126
|
-
},
|
|
1127
|
-
{
|
|
1128
|
-
rx: xRadius,
|
|
1129
|
-
ry: yRadius,
|
|
1130
|
-
xAxisRotation: 0,
|
|
1131
|
-
largeArcFlag: 1,
|
|
1132
|
-
sweepFlag: 1,
|
|
1133
|
-
endX: rectangle.x + divisionWidth,
|
|
1134
|
-
endY: rectangle.y + divisionHeight * 2.2
|
|
1135
|
-
},
|
|
1136
|
-
{
|
|
1137
|
-
rx: xRadius,
|
|
1138
|
-
ry: yRadius * 1.42,
|
|
1139
|
-
xAxisRotation: 0,
|
|
1140
|
-
largeArcFlag: 1,
|
|
1141
|
-
sweepFlag: 1,
|
|
1142
|
-
endX: rectangle.x + divisionWidth,
|
|
1143
|
-
endY: rectangle.y + divisionHeight
|
|
1105
|
+
if (isAdjustStart || isAdjustEnd) {
|
|
1106
|
+
const parallelSegment = [startPoint, endPoint];
|
|
1107
|
+
const parallelSegments = findOrthogonalParallelSegments(parallelSegment, nextKeyPoints);
|
|
1108
|
+
const mirrorSegments = findMirrorSegments(board, parallelSegment, parallelSegments, params.sourceRectangle, params.targetRectangle);
|
|
1109
|
+
if (mirrorSegments.length === 1) {
|
|
1110
|
+
const mirrorSegment = mirrorSegments[0];
|
|
1111
|
+
if (isAdjustStart) {
|
|
1112
|
+
nextDataPoints.splice(customPointStartIndex, 1, mirrorSegment[0]);
|
|
1113
|
+
}
|
|
1114
|
+
if (isAdjustEnd) {
|
|
1115
|
+
nextDataPoints.splice(customPointStartIndex + 1, 1, mirrorSegment[1]);
|
|
1116
|
+
}
|
|
1144
1117
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
const svgElement = rs.path(pathData, { ...options, fillStyle: 'solid' });
|
|
1158
|
-
setPathStrokeLinecap(svgElement, 'round');
|
|
1159
|
-
return svgElement;
|
|
1160
|
-
},
|
|
1161
|
-
isInsidePoint(rectangle, point) {
|
|
1162
|
-
const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
1163
|
-
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
1164
|
-
},
|
|
1165
|
-
getCornerPoints(rectangle) {
|
|
1166
|
-
return RectangleClient.getCornerPoints(rectangle);
|
|
1167
|
-
},
|
|
1168
|
-
getNearestPoint(rectangle, point) {
|
|
1169
|
-
const { startPoint, arcCommands } = generateCloudPath(rectangle);
|
|
1170
|
-
let minDistance = Infinity;
|
|
1171
|
-
let nearestPoint = point;
|
|
1172
|
-
let currentStart = startPoint;
|
|
1173
|
-
for (const arcCommand of arcCommands) {
|
|
1174
|
-
const arcNearestPoint = getNearestPointBetweenPointAndArc(point, currentStart, arcCommand);
|
|
1175
|
-
const distance = distanceBetweenPointAndPoint(point[0], point[1], arcNearestPoint[0], arcNearestPoint[1]);
|
|
1176
|
-
if (distance < minDistance) {
|
|
1177
|
-
minDistance = distance;
|
|
1178
|
-
nearestPoint = arcNearestPoint;
|
|
1118
|
+
else {
|
|
1119
|
+
const isHorizontal = Point.isHorizontal(startPoint, endPoint);
|
|
1120
|
+
const adjustIndex = isHorizontal ? 0 : 1;
|
|
1121
|
+
if (isAdjustStart) {
|
|
1122
|
+
const newStartPoint = [startPoint[0], startPoint[1]];
|
|
1123
|
+
newStartPoint[adjustIndex] = beforePoint[adjustIndex];
|
|
1124
|
+
nextDataPoints.splice(customPointStartIndex, 1, newStartPoint);
|
|
1125
|
+
}
|
|
1126
|
+
if (isAdjustEnd) {
|
|
1127
|
+
const newEndPoint = [endPoint[0], endPoint[1]];
|
|
1128
|
+
newEndPoint[adjustIndex] = afterPoint[adjustIndex];
|
|
1129
|
+
nextDataPoints.splice(customPointStartIndex + 1, 1, newEndPoint);
|
|
1179
1130
|
}
|
|
1180
|
-
currentStart = [arcCommand.endX, arcCommand.endY];
|
|
1181
1131
|
}
|
|
1182
|
-
return nearestPoint;
|
|
1183
|
-
},
|
|
1184
|
-
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
1185
|
-
const corners = CloudEngine.getCornerPoints(rectangle);
|
|
1186
|
-
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
1187
|
-
return getPolygonEdgeByConnectionPoint(corners, point);
|
|
1188
|
-
},
|
|
1189
|
-
getConnectorPoints(rectangle) {
|
|
1190
|
-
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
1191
|
-
},
|
|
1192
|
-
getTextRectangle(element) {
|
|
1193
|
-
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
1194
|
-
const strokeWidth = getStrokeWidthByElement(element);
|
|
1195
|
-
const height = element.textHeight;
|
|
1196
|
-
const originWidth = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
1197
|
-
const width = originWidth / 1.5;
|
|
1198
|
-
return {
|
|
1199
|
-
height,
|
|
1200
|
-
width: width > 0 ? width : 0,
|
|
1201
|
-
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + originWidth / 6,
|
|
1202
|
-
y: elementRectangle.y + elementRectangle.height / 6 + ((elementRectangle.height * 4) / 6 - height) / 2
|
|
1203
|
-
};
|
|
1204
1132
|
}
|
|
1205
1133
|
};
|
|
1206
|
-
|
|
1207
|
-
const
|
|
1208
|
-
|
|
1209
|
-
if (geometry.textHeight && geometry.textHeight > client.height) {
|
|
1134
|
+
function isUpdatedHandleIndex(board, element, dataPoints, nextRenderPoints, handleIndex) {
|
|
1135
|
+
const { deleteCount } = getIndexAndDeleteCountByKeyPoint(board, element, dataPoints, nextRenderPoints, handleIndex);
|
|
1136
|
+
if (deleteCount !== null && deleteCount > 1) {
|
|
1210
1137
|
return true;
|
|
1211
1138
|
}
|
|
1212
1139
|
return false;
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
}
|
|
1226
|
-
const isHitVectorLine = (board, element, point) => {
|
|
1227
|
-
const points = getVectorLinePoints(board, element);
|
|
1228
|
-
if (isClosedPoints(element.points)) {
|
|
1229
|
-
return isPointInPolygon(point, points) || isHitPolyLine(points, point);
|
|
1230
|
-
}
|
|
1231
|
-
else {
|
|
1232
|
-
return isHitPolyLine(points, point);
|
|
1233
|
-
}
|
|
1234
|
-
};
|
|
1235
|
-
const isRectangleHitElementText = (element, rectangle) => {
|
|
1236
|
-
const engine = getEngine(element.shape);
|
|
1237
|
-
if (isMultipleTextGeometry(element)) {
|
|
1238
|
-
const texts = element.texts;
|
|
1239
|
-
return texts.some((item) => {
|
|
1240
|
-
const textClient = engine.getTextRectangle(element, { id: item.id });
|
|
1241
|
-
return isRectangleHitRotatedPoints(rectangle, RectangleClient.getCornerPoints(textClient), element.angle);
|
|
1242
|
-
});
|
|
1140
|
+
}
|
|
1141
|
+
function getMidKeyPoints(simplifiedNextKeyPoints, startPoint, endPoint) {
|
|
1142
|
+
let midElbowPoints = [];
|
|
1143
|
+
let startPointIndex = -1;
|
|
1144
|
+
let endPointIndex = -1;
|
|
1145
|
+
for (let i = 0; i < simplifiedNextKeyPoints.length; i++) {
|
|
1146
|
+
if (Point.isAlign([simplifiedNextKeyPoints[i], startPoint])) {
|
|
1147
|
+
startPointIndex = i;
|
|
1148
|
+
}
|
|
1149
|
+
if (startPointIndex > -1 && Point.isAlign([simplifiedNextKeyPoints[i], endPoint])) {
|
|
1150
|
+
endPointIndex = i;
|
|
1151
|
+
break;
|
|
1152
|
+
}
|
|
1243
1153
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
return isRectangleHitRotatedPoints(rectangle, RectangleClient.getCornerPoints(textClient), element.angle);
|
|
1154
|
+
if (startPointIndex > -1 && endPointIndex > -1) {
|
|
1155
|
+
midElbowPoints = simplifiedNextKeyPoints.slice(startPointIndex, endPointIndex + 1);
|
|
1247
1156
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1157
|
+
return midElbowPoints;
|
|
1158
|
+
}
|
|
1159
|
+
function findOrthogonalParallelSegments(segment, keyPoints) {
|
|
1160
|
+
const isHorizontalSegment = Point.isHorizontal(segment[0], segment[1]);
|
|
1161
|
+
const parallelSegments = [];
|
|
1162
|
+
for (let i = 0; i < keyPoints.length - 1; i++) {
|
|
1163
|
+
const current = keyPoints[i];
|
|
1164
|
+
const next = keyPoints[i + 1];
|
|
1165
|
+
const isHorizontal = Point.isHorizontal(current, next, 0.1);
|
|
1166
|
+
if (isHorizontalSegment && isHorizontal) {
|
|
1167
|
+
parallelSegments.push([current, next]);
|
|
1168
|
+
}
|
|
1169
|
+
if (!isHorizontalSegment && !isHorizontal) {
|
|
1170
|
+
parallelSegments.push([current, next]);
|
|
1171
|
+
}
|
|
1257
1172
|
}
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1173
|
+
return parallelSegments;
|
|
1174
|
+
}
|
|
1175
|
+
function findMirrorSegments(board, segment, parallelSegments, sourceRectangle, targetRectangle) {
|
|
1176
|
+
debugGenerator$4.isDebug() && debugGenerator$4.clear();
|
|
1177
|
+
const mirrorSegments = [];
|
|
1178
|
+
for (let index = 0; index < parallelSegments.length; index++) {
|
|
1179
|
+
const parallelPath = parallelSegments[index];
|
|
1180
|
+
const startPoint = [segment[0][0], segment[0][1]];
|
|
1181
|
+
const endPoint = [segment[1][0], segment[1][1]];
|
|
1182
|
+
const isHorizontal = Point.isHorizontal(startPoint, endPoint);
|
|
1183
|
+
const adjustDataIndex = isHorizontal ? 0 : 1;
|
|
1184
|
+
startPoint[adjustDataIndex] = parallelPath[0][adjustDataIndex];
|
|
1185
|
+
endPoint[adjustDataIndex] = parallelPath[1][adjustDataIndex];
|
|
1186
|
+
const fakeRectangle = RectangleClient.getRectangleByPoints([startPoint, endPoint, ...parallelPath]);
|
|
1187
|
+
const isValid = !RectangleClient.isHit(fakeRectangle, sourceRectangle) && !RectangleClient.isHit(fakeRectangle, targetRectangle);
|
|
1188
|
+
if (isValid) {
|
|
1189
|
+
mirrorSegments.push([startPoint, endPoint]);
|
|
1190
|
+
debugGenerator$4.isDebug() && debugGenerator$4.drawPolygon(board, RectangleClient.getCornerPoints(fakeRectangle));
|
|
1191
|
+
}
|
|
1261
1192
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1193
|
+
return mirrorSegments;
|
|
1194
|
+
}
|
|
1195
|
+
const hasIllegalElbowPoint = (midDataPoints) => {
|
|
1196
|
+
if (midDataPoints.length === 1) {
|
|
1265
1197
|
return true;
|
|
1266
1198
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
const
|
|
1274
|
-
if (
|
|
1275
|
-
return
|
|
1199
|
+
return midDataPoints.some((item, index) => {
|
|
1200
|
+
const beforePoint = midDataPoints[index - 1];
|
|
1201
|
+
const afterPoint = midDataPoints[index + 1];
|
|
1202
|
+
const beforeSegment = beforePoint && [beforePoint, item];
|
|
1203
|
+
const afterSegment = afterPoint && [item, afterPoint];
|
|
1204
|
+
const isStraightWithBefore = beforeSegment && Point.isAlign(beforeSegment);
|
|
1205
|
+
const isStraightWithAfter = afterSegment && Point.isAlign(afterSegment);
|
|
1206
|
+
if (index === 0) {
|
|
1207
|
+
return !isStraightWithAfter;
|
|
1276
1208
|
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
return
|
|
1281
|
-
}
|
|
1282
|
-
if (PlaitDrawElement.isArrowLine(element)) {
|
|
1283
|
-
const points = getArrowLinePoints(board, element);
|
|
1284
|
-
return isLineHitRectangle(points, rangeRectangle);
|
|
1285
|
-
}
|
|
1286
|
-
if (PlaitDrawElement.isVectorLine(element)) {
|
|
1287
|
-
const points = getVectorLinePoints(board, element);
|
|
1288
|
-
return isLineHitRectangle(points, rangeRectangle);
|
|
1289
|
-
}
|
|
1290
|
-
return null;
|
|
1291
|
-
};
|
|
1292
|
-
const isRectangleHitRotatedElement = (board, rectangle, element) => {
|
|
1293
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1294
|
-
return isRectangleHitRotatedPoints(rectangle, RectangleClient.getCornerPoints(client), element.angle);
|
|
1295
|
-
};
|
|
1296
|
-
const isRectangleHitRotatedPoints = (rectangle, points, angle) => {
|
|
1297
|
-
let rotatedPoints = rotatePointsByAngle(points, angle) || points;
|
|
1298
|
-
return isLineHitRectangle(rotatedPoints, rectangle);
|
|
1209
|
+
if (index === midDataPoints.length - 1) {
|
|
1210
|
+
return !isStraightWithBefore;
|
|
1211
|
+
}
|
|
1212
|
+
return !isStraightWithBefore && !isStraightWithAfter;
|
|
1213
|
+
});
|
|
1299
1214
|
};
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
const newElements = elements.slice(0, endIndex);
|
|
1307
|
-
const element = getFirstTextOrLineElement(newElements);
|
|
1308
|
-
if (element) {
|
|
1309
|
-
return element;
|
|
1215
|
+
|
|
1216
|
+
const ARROW_LENGTH = 20;
|
|
1217
|
+
const drawArrowLineArrow = (element, points, options) => {
|
|
1218
|
+
const arrowG = createG();
|
|
1219
|
+
if (PlaitArrowLine.isSourceMark(element, ArrowLineMarkerType.none) && PlaitArrowLine.isTargetMark(element, ArrowLineMarkerType.none)) {
|
|
1220
|
+
return null;
|
|
1310
1221
|
}
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
let filledElement = null;
|
|
1316
|
-
for (let i = 0; i < elements.length; i++) {
|
|
1317
|
-
const element = elements[i];
|
|
1318
|
-
if (isClosedCustomGeometry(board, element) || isClosedDrawElement(element)) {
|
|
1319
|
-
const fill = getFillByElement(board, element);
|
|
1320
|
-
if (isFilled(fill)) {
|
|
1321
|
-
filledElement = element;
|
|
1322
|
-
break;
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1222
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1223
|
+
const offset = (strokeWidth * strokeWidth) / 3;
|
|
1224
|
+
if (points.length === 1) {
|
|
1225
|
+
points = [points[0], [points[0][0] + 0.1, points[0][1]]];
|
|
1325
1226
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
const
|
|
1329
|
-
|
|
1330
|
-
};
|
|
1331
|
-
const getFirstTextOrLineElement = (elements) => {
|
|
1332
|
-
const texts = elements.filter((item) => PlaitDrawElement.isText(item));
|
|
1333
|
-
if (texts.length) {
|
|
1334
|
-
return texts[0];
|
|
1227
|
+
if (!PlaitArrowLine.isSourceMark(element, ArrowLineMarkerType.none)) {
|
|
1228
|
+
const source = getExtendPoint(points[0], points[1], ARROW_LENGTH + offset);
|
|
1229
|
+
const sourceArrow = getArrow(element, { marker: element.source.marker, source, target: points[0], isSource: true }, options);
|
|
1230
|
+
sourceArrow && arrowG.appendChild(sourceArrow);
|
|
1335
1231
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1232
|
+
if (!PlaitArrowLine.isTargetMark(element, ArrowLineMarkerType.none)) {
|
|
1233
|
+
const source = getExtendPoint(points[points.length - 1], points[points.length - 2], ARROW_LENGTH + offset);
|
|
1234
|
+
const arrow = getArrow(element, { marker: element.target.marker, source, target: points[points.length - 1], isSource: false }, options);
|
|
1235
|
+
arrow && arrowG.appendChild(arrow);
|
|
1339
1236
|
}
|
|
1340
|
-
return
|
|
1237
|
+
return arrowG;
|
|
1341
1238
|
};
|
|
1342
|
-
const
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
if (debugGenerator$4.isDebug() && shapes.includes(element.shape)) {
|
|
1350
|
-
debugGenerator$4.clear();
|
|
1351
|
-
const { startPoint, arcCommands } = generateCloudPath(rectangle);
|
|
1352
|
-
const points = [startPoint, ...arcCommands.map((arc) => [arc.endX, arc.endY])];
|
|
1353
|
-
debugGenerator$4.drawCircles(board, points, 5, false);
|
|
1354
|
-
let minDistance = Infinity;
|
|
1355
|
-
let nearestPoint = point;
|
|
1356
|
-
let currentStart = startPoint;
|
|
1357
|
-
for (const arc of arcCommands) {
|
|
1358
|
-
const arcNearestPoint = getNearestPointBetweenPointAndArc(point, currentStart, arc);
|
|
1359
|
-
const distance = distanceBetweenPointAndPoint(point[0], point[1], arcNearestPoint[0], arcNearestPoint[1]);
|
|
1360
|
-
const { center } = getEllipseArcCenter(currentStart, arc);
|
|
1361
|
-
debugGenerator$4.drawCircles(board, [center], 8, false, { fill: 'yellow' });
|
|
1362
|
-
if (distance < minDistance) {
|
|
1363
|
-
minDistance = distance;
|
|
1364
|
-
nearestPoint = arcNearestPoint;
|
|
1365
|
-
}
|
|
1366
|
-
currentStart = [arc.endX, arc.endY];
|
|
1367
|
-
}
|
|
1368
|
-
debugGenerator$4.drawCircles(board, [point], 12, false, { fill: 'black', stroke: 'black' });
|
|
1369
|
-
debugGenerator$4.drawCircles(board, [nearestPoint], 12, false, { fill: 'green', stroke: 'green' });
|
|
1239
|
+
const getArrow = (element, arrowOptions, options) => {
|
|
1240
|
+
const { marker, target, source, isSource } = arrowOptions;
|
|
1241
|
+
let targetArrow;
|
|
1242
|
+
switch (marker) {
|
|
1243
|
+
case ArrowLineMarkerType.openTriangle: {
|
|
1244
|
+
targetArrow = drawOpenTriangle(element, source, target, options);
|
|
1245
|
+
break;
|
|
1370
1246
|
}
|
|
1371
|
-
|
|
1372
|
-
|
|
1247
|
+
case ArrowLineMarkerType.solidTriangle: {
|
|
1248
|
+
targetArrow = drawSolidTriangle(source, target, options);
|
|
1249
|
+
break;
|
|
1373
1250
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
return RectangleClient.isPointInRectangle(textClient, point);
|
|
1251
|
+
case ArrowLineMarkerType.arrow: {
|
|
1252
|
+
targetArrow = drawArrow(element, source, target, options);
|
|
1253
|
+
break;
|
|
1378
1254
|
}
|
|
1379
|
-
|
|
1380
|
-
|
|
1255
|
+
case ArrowLineMarkerType.sharpArrow: {
|
|
1256
|
+
targetArrow = drawSharpArrow(source, target, options);
|
|
1257
|
+
break;
|
|
1381
1258
|
}
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
if (PlaitDrawElement.isImage(element)) {
|
|
1386
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1387
|
-
return RectangleClient.isPointInRectangle(client, point);
|
|
1388
|
-
}
|
|
1389
|
-
if (PlaitDrawElement.isArrowLine(element)) {
|
|
1390
|
-
return isHitArrowLine(board, element, point);
|
|
1391
|
-
}
|
|
1392
|
-
if (PlaitDrawElement.isVectorLine(element)) {
|
|
1393
|
-
return isHitVectorLine(board, element, point);
|
|
1394
|
-
}
|
|
1395
|
-
return null;
|
|
1396
|
-
};
|
|
1397
|
-
const isHitEdgeOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
1398
|
-
const nearestPoint = getNearestPoint(element, point);
|
|
1399
|
-
const distance = distanceBetweenPointAndPoint(nearestPoint[0], nearestPoint[1], point[0], point[1]);
|
|
1400
|
-
return distance <= hitDistanceBuffer;
|
|
1401
|
-
};
|
|
1402
|
-
const isInsideOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
1403
|
-
const client = RectangleClient.inflate(RectangleClient.getRectangleByPoints(element.points), hitDistanceBuffer);
|
|
1404
|
-
return getEngine(getElementShape(element)).isInsidePoint(client, point);
|
|
1405
|
-
};
|
|
1406
|
-
const isHitElementInside = (board, element, point) => {
|
|
1407
|
-
const rectangle = board.getRectangle(element);
|
|
1408
|
-
point = rotateAntiPointsByElement(board, point, element) || point;
|
|
1409
|
-
if (PlaitDrawElement.isGeometry(element) && !PlaitDrawElement.isGeometryByTable(element)) {
|
|
1410
|
-
const engine = getEngine(getElementShape(element));
|
|
1411
|
-
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
1412
|
-
if (isHitInside) {
|
|
1413
|
-
return isHitInside;
|
|
1259
|
+
case ArrowLineMarkerType.oneSideUp: {
|
|
1260
|
+
targetArrow = drawOneSideArrow(source, target, isSource ? 'down' : 'up', options);
|
|
1261
|
+
break;
|
|
1414
1262
|
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1263
|
+
case ArrowLineMarkerType.oneSideDown: {
|
|
1264
|
+
targetArrow = drawOneSideArrow(source, target, isSource ? 'up' : 'down', options);
|
|
1265
|
+
break;
|
|
1266
|
+
}
|
|
1267
|
+
case ArrowLineMarkerType.hollowTriangle: {
|
|
1268
|
+
targetArrow = drawHollowTriangleArrow(source, target, options);
|
|
1269
|
+
break;
|
|
1270
|
+
}
|
|
1271
|
+
case ArrowLineMarkerType.singleSlash: {
|
|
1272
|
+
targetArrow = drawSingleSlash(source, target, isSource, options);
|
|
1273
|
+
break;
|
|
1420
1274
|
}
|
|
1421
1275
|
}
|
|
1422
|
-
|
|
1423
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1424
|
-
return RectangleClient.isPointInRectangle(client, point);
|
|
1425
|
-
}
|
|
1426
|
-
if (PlaitDrawElement.isArrowLine(element)) {
|
|
1427
|
-
return isHitArrowLine(board, element, point);
|
|
1428
|
-
}
|
|
1429
|
-
if (PlaitDrawElement.isVectorLine(element)) {
|
|
1430
|
-
return isHitVectorLine(board, element, point);
|
|
1431
|
-
}
|
|
1432
|
-
return null;
|
|
1276
|
+
return targetArrow;
|
|
1433
1277
|
};
|
|
1434
|
-
|
|
1435
|
-
const
|
|
1436
|
-
const
|
|
1437
|
-
const
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1278
|
+
const drawSharpArrow = (source, target, options) => {
|
|
1279
|
+
const startPoint = target;
|
|
1280
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 20);
|
|
1281
|
+
const g = createG();
|
|
1282
|
+
const path = createPath();
|
|
1283
|
+
let polylinePath = `M${pointRight[0]},${pointRight[1]}A25,25,20,0,1,${pointLeft[0]},${pointLeft[1]}L${startPoint[0]},${startPoint[1]}Z`;
|
|
1284
|
+
path.setAttribute('d', polylinePath);
|
|
1285
|
+
path.setAttribute('stroke', `${options?.stroke}`);
|
|
1286
|
+
path.setAttribute('stroke-width', `${options?.strokeWidth}`);
|
|
1287
|
+
path.setAttribute('fill', `${options?.stroke}`);
|
|
1288
|
+
g.appendChild(path);
|
|
1289
|
+
return g;
|
|
1446
1290
|
};
|
|
1447
|
-
const
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
const
|
|
1452
|
-
|
|
1291
|
+
const drawArrow = (element, source, target, options) => {
|
|
1292
|
+
const unitVector = getUnitVectorByPointAndPoint(source, target);
|
|
1293
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1294
|
+
const endPoint = [target[0] + (strokeWidth * unitVector[0]) / 2, target[1] + (strokeWidth * unitVector[1]) / 2];
|
|
1295
|
+
const distance = distanceBetweenPointAndPoint(...source, ...endPoint);
|
|
1296
|
+
const middlePoint = [
|
|
1297
|
+
endPoint[0] - (((distance * 3) / 5 + strokeWidth) / 2) * unitVector[0],
|
|
1298
|
+
endPoint[1] - (((distance * 3) / 5 + strokeWidth) / 2) * unitVector[1]
|
|
1299
|
+
];
|
|
1300
|
+
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 30);
|
|
1301
|
+
const arrowG = drawLinearPath([pointLeft, endPoint, pointRight, middlePoint], { ...options, fill: options.stroke }, true);
|
|
1302
|
+
const path = arrowG.querySelector('path');
|
|
1303
|
+
path.setAttribute('stroke-linejoin', 'round');
|
|
1304
|
+
return arrowG;
|
|
1453
1305
|
};
|
|
1454
|
-
const
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
addSelectedElement(board, element);
|
|
1459
|
-
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
1306
|
+
const drawSolidTriangle = (source, target, options) => {
|
|
1307
|
+
const endPoint = target;
|
|
1308
|
+
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 30);
|
|
1309
|
+
return drawLinearPath([pointLeft, endPoint, pointRight], { ...options, fill: options.stroke }, true);
|
|
1460
1310
|
};
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1311
|
+
const drawOpenTriangle = (element, source, target, options) => {
|
|
1312
|
+
const unitVector = getUnitVectorByPointAndPoint(source, target);
|
|
1313
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1314
|
+
const endPoint = [target[0] + (strokeWidth * unitVector[0]) / 2, target[1] + (strokeWidth * unitVector[1]) / 2];
|
|
1315
|
+
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 40);
|
|
1316
|
+
return drawLinearPath([pointLeft, endPoint, pointRight], options);
|
|
1317
|
+
};
|
|
1318
|
+
const drawOneSideArrow = (source, target, side, options) => {
|
|
1319
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 40);
|
|
1320
|
+
return drawLinearPath([side === 'up' ? pointRight : pointLeft, target], options);
|
|
1321
|
+
};
|
|
1322
|
+
const drawSingleSlash = (source, target, isSource, options) => {
|
|
1323
|
+
const length = distanceBetweenPointAndPoint(...source, ...target);
|
|
1324
|
+
const middlePoint = getExtendPoint(target, source, length / 2);
|
|
1325
|
+
const angle = isSource ? 120 : 60;
|
|
1326
|
+
const start = rotate(...source, ...middlePoint, (angle * Math.PI) / 180);
|
|
1327
|
+
const end = rotate(...target, ...middlePoint, (angle * Math.PI) / 180);
|
|
1328
|
+
return drawLinearPath([start, end], options);
|
|
1329
|
+
};
|
|
1330
|
+
const drawHollowTriangleArrow = (source, target, options) => {
|
|
1331
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 30);
|
|
1332
|
+
return drawLinearPath([pointLeft, pointRight, target], { ...options, fill: 'white' }, true);
|
|
1333
|
+
};
|
|
1334
|
+
|
|
1335
|
+
class ArrowLineShapeGenerator extends Generator {
|
|
1336
|
+
canDraw(element) {
|
|
1463
1337
|
return true;
|
|
1464
1338
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
return isGeometryIncludeText(element);
|
|
1470
|
-
}
|
|
1471
|
-
if (PlaitDrawElement.isArrowLine(element)) {
|
|
1472
|
-
const editors = getTextEditorsByElement(element);
|
|
1473
|
-
return editors.length > 0;
|
|
1474
|
-
}
|
|
1475
|
-
if (PlaitDrawElement.isElementByTable(element)) {
|
|
1476
|
-
return element.cells.some((cell) => isCellIncludeText(cell));
|
|
1339
|
+
draw(element) {
|
|
1340
|
+
let lineG;
|
|
1341
|
+
lineG = drawArrowLine(this.board, element);
|
|
1342
|
+
return lineG;
|
|
1477
1343
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
const
|
|
1481
|
-
return
|
|
1482
|
-
|
|
1483
|
-
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
const createArrowLineElement = (shape, points, source, target, texts, options) => {
|
|
1347
|
+
return {
|
|
1348
|
+
id: idCreator(),
|
|
1349
|
+
type: 'arrow-line',
|
|
1350
|
+
shape,
|
|
1351
|
+
source,
|
|
1352
|
+
texts: texts ? texts : [],
|
|
1353
|
+
target,
|
|
1354
|
+
opacity: 1,
|
|
1355
|
+
points,
|
|
1356
|
+
...options
|
|
1357
|
+
};
|
|
1484
1358
|
};
|
|
1485
|
-
const
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
return
|
|
1359
|
+
const getArrowLinePoints = (board, element) => {
|
|
1360
|
+
switch (element.shape) {
|
|
1361
|
+
case ArrowLineShape.elbow: {
|
|
1362
|
+
return getElbowPoints(board, element);
|
|
1489
1363
|
}
|
|
1490
|
-
|
|
1491
|
-
return
|
|
1364
|
+
case ArrowLineShape.curve: {
|
|
1365
|
+
return getCurvePoints(board, element);
|
|
1492
1366
|
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1367
|
+
default: {
|
|
1368
|
+
const points = PlaitArrowLine.getPoints(board, element);
|
|
1369
|
+
const handleRefPair = getArrowLineHandleRefPair(board, element);
|
|
1370
|
+
points[0] = handleRefPair.source.point;
|
|
1371
|
+
points[points.length - 1] = handleRefPair.target.point;
|
|
1372
|
+
return points;
|
|
1495
1373
|
}
|
|
1496
|
-
return true;
|
|
1497
1374
|
}
|
|
1498
|
-
return false;
|
|
1499
1375
|
};
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1376
|
+
const getCurvePoints = (board, element) => {
|
|
1377
|
+
if (element.points.length === 2) {
|
|
1378
|
+
const handleRefPair = getArrowLineHandleRefPair(board, element);
|
|
1379
|
+
const { source, target } = handleRefPair;
|
|
1380
|
+
const sourceBoundElement = handleRefPair.source.boundElement;
|
|
1381
|
+
const targetBoundElement = handleRefPair.target.boundElement;
|
|
1382
|
+
let curvePoints = [source.point];
|
|
1383
|
+
const sumDistance = distanceBetweenPointAndPoint(...source.point, ...target.point);
|
|
1384
|
+
const offset = 12 + sumDistance / 3;
|
|
1385
|
+
if (sourceBoundElement) {
|
|
1386
|
+
curvePoints.push(getPointByVectorComponent(source.point, source.vector, offset));
|
|
1509
1387
|
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
};
|
|
1513
|
-
const getSnappingRef = (board, hitElement, point) => {
|
|
1514
|
-
const rotatedPoint = rotateAntiPointsByElement(board, point, hitElement) || point;
|
|
1515
|
-
const connectorPoint = getHitConnectorPoint(rotatedPoint, hitElement);
|
|
1516
|
-
const edgePoint = getNearestPoint(hitElement, rotatedPoint);
|
|
1517
|
-
const isHitEdge = isHitEdgeOfShape(board, hitElement, rotatedPoint, LINE_SNAPPING_BUFFER);
|
|
1518
|
-
return { isHitEdge, isHitConnector: !!connectorPoint, connectorPoint, edgePoint };
|
|
1519
|
-
};
|
|
1520
|
-
const getHitShape = (board, point, offset = LINE_HIT_GEOMETRY_BUFFER) => {
|
|
1521
|
-
let hitShape = null;
|
|
1522
|
-
traverseDrawShapes(board, (element) => {
|
|
1523
|
-
if (hitShape === null && isInsideOfShape(board, element, rotateAntiPointsByElement(board, point, element) || point, offset * 2)) {
|
|
1524
|
-
hitShape = element;
|
|
1388
|
+
if (targetBoundElement) {
|
|
1389
|
+
curvePoints.push(getPointByVectorComponent(target.point, target.vector, offset));
|
|
1525
1390
|
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
const
|
|
1530
|
-
|
|
1531
|
-
if (!PlaitBoard.isBoard(node) && PlaitDrawElement.isShapeElement(node)) {
|
|
1532
|
-
callback(node);
|
|
1391
|
+
const isSingleBound = (sourceBoundElement && !targetBoundElement) || (!sourceBoundElement && targetBoundElement);
|
|
1392
|
+
if (isSingleBound) {
|
|
1393
|
+
curvePoints.push(target.point);
|
|
1394
|
+
const points = Q2C(curvePoints);
|
|
1395
|
+
return pointsOnBezierCurves(points);
|
|
1533
1396
|
}
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
const g = createG();
|
|
1541
|
-
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
1542
|
-
const activeRectangle = RectangleClient.inflate(rectangle, SNAPPING_STROKE_WIDTH);
|
|
1543
|
-
const shape = getElementShape(element);
|
|
1544
|
-
let drawOptions;
|
|
1545
|
-
if (PlaitDrawElement.isElementByTable(element)) {
|
|
1546
|
-
drawOptions = { element };
|
|
1547
|
-
}
|
|
1548
|
-
const strokeG = drawShape(board, activeRectangle, shape, {
|
|
1549
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
1550
|
-
strokeWidth: SNAPPING_STROKE_WIDTH
|
|
1551
|
-
}, drawOptions);
|
|
1552
|
-
g.appendChild(strokeG);
|
|
1553
|
-
if (roughOptions.hasMask) {
|
|
1554
|
-
const maskG = drawShape(board, activeRectangle, shape, {
|
|
1555
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
1556
|
-
strokeWidth: 0,
|
|
1557
|
-
fill: isClosedDrawElement(element) ? SELECTION_FILL_COLOR : DefaultDrawStyle.fill,
|
|
1558
|
-
fillStyle: 'solid'
|
|
1559
|
-
}, drawOptions);
|
|
1560
|
-
g.appendChild(maskG);
|
|
1397
|
+
if (!sourceBoundElement && !targetBoundElement) {
|
|
1398
|
+
curvePoints.push(getPointByVectorComponent(source.point, source.vector, offset));
|
|
1399
|
+
curvePoints.push(getPointByVectorComponent(target.point, target.vector, offset));
|
|
1400
|
+
}
|
|
1401
|
+
curvePoints.push(target.point);
|
|
1402
|
+
return pointsOnBezierCurves(curvePoints);
|
|
1561
1403
|
}
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
1568
|
-
fill: '#FFF',
|
|
1569
|
-
fillStyle: 'solid'
|
|
1570
|
-
});
|
|
1571
|
-
g.appendChild(circleG);
|
|
1572
|
-
});
|
|
1404
|
+
else {
|
|
1405
|
+
let dataPoints = PlaitArrowLine.getPoints(board, element);
|
|
1406
|
+
dataPoints = removeDuplicatePoints(dataPoints);
|
|
1407
|
+
const points = catmullRomFitting(dataPoints);
|
|
1408
|
+
return pointsOnBezierCurves(points);
|
|
1573
1409
|
}
|
|
1574
|
-
return g;
|
|
1575
1410
|
};
|
|
1576
|
-
const
|
|
1577
|
-
|
|
1578
|
-
|
|
1411
|
+
const drawArrowLine = (board, element) => {
|
|
1412
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1413
|
+
const strokeColor = getStrokeColorByElement(board, element);
|
|
1414
|
+
const strokeStyle = getStrokeStyleByElement(board, element);
|
|
1415
|
+
const strokeLineDash = getStrokeLineDash(strokeStyle, strokeWidth);
|
|
1416
|
+
const options = { stroke: strokeColor, strokeWidth, strokeLineDash };
|
|
1417
|
+
const lineG = createG();
|
|
1418
|
+
let points = getArrowLinePoints(board, element);
|
|
1419
|
+
let line;
|
|
1420
|
+
if (element.shape === ArrowLineShape.curve) {
|
|
1421
|
+
line = PlaitBoard.getRoughSVG(board).curve(points, options);
|
|
1579
1422
|
}
|
|
1580
1423
|
else {
|
|
1581
|
-
|
|
1424
|
+
line = drawLinearPath(points, options);
|
|
1582
1425
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
if (
|
|
1586
|
-
|
|
1587
|
-
return drawShapeText?.text.align || Alignment.center;
|
|
1588
|
-
}
|
|
1589
|
-
if (isSingleTextGeometry(element)) {
|
|
1590
|
-
return element.text?.align || Alignment.center;
|
|
1426
|
+
const id = idCreator();
|
|
1427
|
+
line.setAttribute('mask', `url(#${id})`);
|
|
1428
|
+
if (element.strokeStyle === StrokeStyle.dotted) {
|
|
1429
|
+
setStrokeLinecap(line, 'round');
|
|
1591
1430
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1431
|
+
lineG.appendChild(line);
|
|
1432
|
+
const { mask, maskTargetFillRect } = drawArrowLineMask(board, element, id);
|
|
1433
|
+
lineG.appendChild(mask);
|
|
1434
|
+
line.appendChild(maskTargetFillRect);
|
|
1435
|
+
const arrow = drawArrowLineArrow(element, points, { stroke: strokeColor, strokeWidth });
|
|
1436
|
+
arrow && lineG.appendChild(arrow);
|
|
1437
|
+
return lineG;
|
|
1438
|
+
};
|
|
1439
|
+
const getHitConnection = (board, point, hitElement) => {
|
|
1440
|
+
let rectangle = RectangleClient.getRectangleByPoints(hitElement.points);
|
|
1441
|
+
const ref = getSnappingRef(board, hitElement, point);
|
|
1442
|
+
const connectionPoint = ref.connectorPoint || ref.edgePoint;
|
|
1443
|
+
return [(connectionPoint[0] - rectangle.x) / rectangle.width, (connectionPoint[1] - rectangle.y) / rectangle.height];
|
|
1444
|
+
};
|
|
1445
|
+
const getHitConnectorPoint = (point, hitElement) => {
|
|
1446
|
+
const rectangle = RectangleClient.getRectangleByPoints(hitElement.points);
|
|
1447
|
+
const shape = getElementShape(hitElement);
|
|
1448
|
+
const connectorPoints = getEngine(shape).getConnectorPoints(rectangle);
|
|
1449
|
+
return connectorPoints.find((connectorPoint) => {
|
|
1450
|
+
return distanceBetweenPointAndPoint(...connectorPoint, ...point) <= LINE_SNAPPING_CONNECTOR_BUFFER;
|
|
1451
|
+
});
|
|
1452
|
+
};
|
|
1453
|
+
const getArrowLineTextRectangle = (board, element, index) => {
|
|
1454
|
+
const text = element.texts[index];
|
|
1455
|
+
const elbowPoints = getArrowLinePoints(board, element);
|
|
1456
|
+
const point = getPointOnPolyline(elbowPoints, text.position);
|
|
1457
|
+
return {
|
|
1458
|
+
x: point[0] - text.width / 2,
|
|
1459
|
+
y: point[1] - text.height / 2,
|
|
1460
|
+
width: text.width,
|
|
1461
|
+
height: text.height
|
|
1462
|
+
};
|
|
1463
|
+
};
|
|
1464
|
+
const getArrowLines = (board) => {
|
|
1465
|
+
return findElements(board, {
|
|
1466
|
+
match: (element) => PlaitDrawElement.isArrowLine(element),
|
|
1467
|
+
recursion: (element) => PlaitDrawElement.isDrawElement(element)
|
|
1468
|
+
});
|
|
1469
|
+
};
|
|
1470
|
+
// quadratic Bezier to cubic Bezier
|
|
1471
|
+
const Q2C = (points) => {
|
|
1472
|
+
const result = [];
|
|
1473
|
+
const numSegments = points.length / 3;
|
|
1474
|
+
for (let i = 0; i < numSegments; i++) {
|
|
1475
|
+
const start = points[i];
|
|
1476
|
+
const qControl = points[i + 1];
|
|
1477
|
+
const end = points[i + 2];
|
|
1478
|
+
const startDistance = distanceBetweenPointAndPoint(...start, ...qControl);
|
|
1479
|
+
const endDistance = distanceBetweenPointAndPoint(...end, ...qControl);
|
|
1480
|
+
const cControl1 = getExtendPoint(start, qControl, (startDistance * 2) / 3);
|
|
1481
|
+
const cControl2 = getExtendPoint(end, qControl, (endDistance * 2) / 3);
|
|
1482
|
+
result.push(start, cControl1, cControl2, end);
|
|
1595
1483
|
}
|
|
1596
|
-
return
|
|
1484
|
+
return result;
|
|
1597
1485
|
};
|
|
1598
|
-
const
|
|
1599
|
-
const
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1486
|
+
const handleArrowLineCreating = (board, lineShape, sourcePoint, movingPoint, sourceElement, lineShapeG) => {
|
|
1487
|
+
const hitElement = getSnappingShape(board, movingPoint);
|
|
1488
|
+
const targetConnection = hitElement ? getHitConnection(board, movingPoint, hitElement) : undefined;
|
|
1489
|
+
const sourceConnection = sourceElement ? getHitConnection(board, sourcePoint, sourceElement) : undefined;
|
|
1490
|
+
const targetBoundId = hitElement ? hitElement.id : undefined;
|
|
1491
|
+
const lineGenerator = new ArrowLineShapeGenerator(board);
|
|
1492
|
+
const memorizedLatest = getLineMemorizedLatest();
|
|
1493
|
+
let sourceMarker, targetMarker;
|
|
1494
|
+
sourceMarker = memorizedLatest.source;
|
|
1495
|
+
targetMarker = memorizedLatest.target;
|
|
1496
|
+
sourceMarker && delete memorizedLatest.source;
|
|
1497
|
+
targetMarker && delete memorizedLatest.target;
|
|
1498
|
+
const temporaryLineElement = createArrowLineElement(lineShape, [sourcePoint, movingPoint], { marker: sourceMarker || ArrowLineMarkerType.none, connection: sourceConnection, boundId: sourceElement?.id }, { marker: targetMarker || ArrowLineMarkerType.arrow, connection: targetConnection, boundId: targetBoundId }, [], {
|
|
1499
|
+
strokeWidth: DefaultLineStyle.strokeWidth,
|
|
1500
|
+
...memorizedLatest
|
|
1501
|
+
});
|
|
1502
|
+
const linePoints = getArrowLinePoints(board, temporaryLineElement);
|
|
1503
|
+
const otherPoint = linePoints[0];
|
|
1504
|
+
temporaryLineElement.points[1] = alignPoints(otherPoint, movingPoint);
|
|
1505
|
+
lineGenerator.processDrawing(temporaryLineElement, lineShapeG);
|
|
1506
|
+
PlaitBoard.getElementTopHost(board).append(lineShapeG);
|
|
1507
|
+
return temporaryLineElement;
|
|
1602
1508
|
};
|
|
1509
|
+
function drawArrowLineMask(board, element, id) {
|
|
1510
|
+
const mask = createMask();
|
|
1511
|
+
mask.setAttribute('id', id);
|
|
1512
|
+
const points = getArrowLinePoints(board, element);
|
|
1513
|
+
let rectangle = RectangleClient.getRectangleByPoints(points);
|
|
1514
|
+
rectangle = RectangleClient.getOutlineRectangle(rectangle, -30);
|
|
1515
|
+
const maskFillRect = createRect(rectangle, {
|
|
1516
|
+
fill: 'white'
|
|
1517
|
+
});
|
|
1518
|
+
mask.appendChild(maskFillRect);
|
|
1519
|
+
const texts = element.texts;
|
|
1520
|
+
texts.forEach((text, index) => {
|
|
1521
|
+
let textRectangle = getArrowLineTextRectangle(board, element, index);
|
|
1522
|
+
textRectangle = RectangleClient.inflate(textRectangle, LINE_TEXT_SPACE * 2);
|
|
1523
|
+
const rect = createRect(textRectangle, {
|
|
1524
|
+
fill: 'black'
|
|
1525
|
+
});
|
|
1526
|
+
mask.appendChild(rect);
|
|
1527
|
+
});
|
|
1528
|
+
// open line
|
|
1529
|
+
const maskTargetFillRect = createRect(rectangle);
|
|
1530
|
+
maskTargetFillRect.setAttribute('opacity', '0');
|
|
1531
|
+
maskTargetFillRect.setAttribute('fill', 'none');
|
|
1532
|
+
return { mask, maskTargetFillRect };
|
|
1533
|
+
}
|
|
1603
1534
|
|
|
1604
|
-
const
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
|
|
1535
|
+
const getHitArrowLineTextIndex = (board, element, point) => {
|
|
1536
|
+
const texts = element.texts;
|
|
1537
|
+
if (!texts.length)
|
|
1538
|
+
return -1;
|
|
1539
|
+
const points = getArrowLinePoints(board, element);
|
|
1540
|
+
return texts.findIndex(text => {
|
|
1541
|
+
const center = getPointOnPolyline(points, text.position);
|
|
1542
|
+
const rectangle = {
|
|
1543
|
+
x: center[0] - text.width / 2,
|
|
1544
|
+
y: center[1] - text.height / 2,
|
|
1545
|
+
width: text.width,
|
|
1546
|
+
height: text.height
|
|
1547
|
+
};
|
|
1548
|
+
return RectangleClient.isHit(rectangle, RectangleClient.getRectangleByPoints([point, point]));
|
|
1549
|
+
});
|
|
1608
1550
|
};
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
: DefaultDrawStyle.fill;
|
|
1613
|
-
const fill = element.fill || defaultFill;
|
|
1614
|
-
return fill;
|
|
1551
|
+
|
|
1552
|
+
const isMultipleTextShape = (shape) => {
|
|
1553
|
+
return GEOMETRY_WITH_MULTIPLE_TEXT.includes(shape);
|
|
1615
1554
|
};
|
|
1616
|
-
const
|
|
1617
|
-
return
|
|
1555
|
+
const isMultipleTextGeometry = (geometry) => {
|
|
1556
|
+
return PlaitDrawElement.isGeometry(geometry) && isMultipleTextShape(geometry.shape);
|
|
1618
1557
|
};
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
const debugGenerator$3 = createDebugGenerator(debugKey$3);
|
|
1622
|
-
const alignPoints = (basePoint, movingPoint) => {
|
|
1623
|
-
const newPoint = [...movingPoint];
|
|
1624
|
-
if (Point.isVertical(newPoint, basePoint, LINE_ALIGN_TOLERANCE)) {
|
|
1625
|
-
newPoint[0] = basePoint[0];
|
|
1626
|
-
}
|
|
1627
|
-
if (Point.isHorizontal(newPoint, basePoint, LINE_ALIGN_TOLERANCE)) {
|
|
1628
|
-
newPoint[1] = basePoint[1];
|
|
1629
|
-
}
|
|
1630
|
-
return newPoint;
|
|
1558
|
+
const getMultipleTextGeometryTextKeys = (shape) => {
|
|
1559
|
+
return MultipleTextGeometryTextKeys[shape];
|
|
1631
1560
|
};
|
|
1632
|
-
|
|
1633
|
-
const
|
|
1634
|
-
|
|
1635
|
-
|
|
1561
|
+
const createMultipleTextGeometryElement = (shape, points, options = {}) => {
|
|
1562
|
+
const id = idCreator();
|
|
1563
|
+
const drawShapeTexts = buildDefaultTextsByShape(shape);
|
|
1564
|
+
return {
|
|
1565
|
+
id,
|
|
1566
|
+
type: 'geometry',
|
|
1567
|
+
shape,
|
|
1568
|
+
angle: 0,
|
|
1569
|
+
opacity: 1,
|
|
1570
|
+
texts: drawShapeTexts,
|
|
1571
|
+
points,
|
|
1572
|
+
...options
|
|
1636
1573
|
};
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
const
|
|
1640
|
-
const
|
|
1641
|
-
const
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1574
|
+
};
|
|
1575
|
+
const buildDefaultTextsByShape = (shape) => {
|
|
1576
|
+
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
1577
|
+
const textProperties = { ...memorizedLatest.textProperties };
|
|
1578
|
+
const alignment = textProperties?.align;
|
|
1579
|
+
const textHeight = textProperties?.textHeight || DefaultTextProperty.height;
|
|
1580
|
+
delete textProperties?.align;
|
|
1581
|
+
delete textProperties?.textHeight;
|
|
1582
|
+
const defaultTexts = getDefaultGeometryProperty(shape)?.texts || [];
|
|
1583
|
+
const textKeys = getMultipleTextGeometryTextKeys(shape);
|
|
1584
|
+
return (textKeys || []).map((textKey) => {
|
|
1585
|
+
const text = defaultTexts?.find((item) => item?.key === textKey);
|
|
1586
|
+
return {
|
|
1587
|
+
id: textKey,
|
|
1588
|
+
text: buildText(text?.text || '', alignment || text?.align || Alignment.center, textProperties),
|
|
1589
|
+
textHeight: textHeight
|
|
1590
|
+
};
|
|
1591
|
+
});
|
|
1592
|
+
};
|
|
1593
|
+
const getHitMultipleGeometryText = (element, point) => {
|
|
1594
|
+
const engine = getEngine(element.shape);
|
|
1595
|
+
const rectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
1596
|
+
let hitText;
|
|
1597
|
+
if (engine.getTextRectangle) {
|
|
1598
|
+
hitText = element.texts.find(text => {
|
|
1599
|
+
const textRectangle = engine.getTextRectangle(element, { id: text.id });
|
|
1600
|
+
return RectangleClient.isHit(rectangle, textRectangle);
|
|
1601
|
+
});
|
|
1646
1602
|
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1603
|
+
return hitText;
|
|
1604
|
+
};
|
|
1605
|
+
|
|
1606
|
+
class VectorLineShapeGenerator extends Generator {
|
|
1607
|
+
canDraw(element) {
|
|
1608
|
+
return true;
|
|
1609
|
+
}
|
|
1610
|
+
draw(element) {
|
|
1611
|
+
let lineG;
|
|
1612
|
+
lineG = drawVectorLine(this.board, element);
|
|
1613
|
+
return lineG;
|
|
1651
1614
|
}
|
|
1652
|
-
return referencePoint;
|
|
1653
1615
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
let pointY = startKeyPoint[1] + offsetY;
|
|
1660
|
-
if (resizedPreviousAndNextPoint.previous && Math.abs(resizedPreviousAndNextPoint.previous[1] - pointY) < LINE_ALIGN_TOLERANCE) {
|
|
1661
|
-
pointY = resizedPreviousAndNextPoint.previous[1];
|
|
1616
|
+
|
|
1617
|
+
const getVectorLinePoints = (board, element) => {
|
|
1618
|
+
switch (element.shape) {
|
|
1619
|
+
case VectorLineShape.straight: {
|
|
1620
|
+
return element.points;
|
|
1662
1621
|
}
|
|
1663
|
-
|
|
1664
|
-
|
|
1622
|
+
case VectorLineShape.curve: {
|
|
1623
|
+
if (element.points.length === 2) {
|
|
1624
|
+
return pointsOnBezierCurves(element.points);
|
|
1625
|
+
}
|
|
1626
|
+
else {
|
|
1627
|
+
let dataPoints = element.points;
|
|
1628
|
+
const points = catmullRomFitting(dataPoints);
|
|
1629
|
+
return pointsOnBezierCurves(points);
|
|
1630
|
+
}
|
|
1665
1631
|
}
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
}
|
|
1669
|
-
if (Point.isVertical(startKeyPoint, endKeyPoint)) {
|
|
1670
|
-
const offsetX = Point.getOffsetX(resizeState.startPoint, resizeState.endPoint);
|
|
1671
|
-
let pointX = startKeyPoint[0] + offsetX;
|
|
1672
|
-
if (resizedPreviousAndNextPoint.previous && Math.abs(resizedPreviousAndNextPoint.previous[0] - pointX) < LINE_ALIGN_TOLERANCE) {
|
|
1673
|
-
pointX = resizedPreviousAndNextPoint.previous[0];
|
|
1674
|
-
}
|
|
1675
|
-
else if (resizedPreviousAndNextPoint.next && Math.abs(resizedPreviousAndNextPoint.next[0] - pointX) < LINE_ALIGN_TOLERANCE) {
|
|
1676
|
-
pointX = resizedPreviousAndNextPoint.next[0];
|
|
1677
|
-
}
|
|
1678
|
-
newStartPoint = [pointX, startKeyPoint[1]];
|
|
1679
|
-
newEndPoint = [pointX, endKeyPoint[1]];
|
|
1632
|
+
default:
|
|
1633
|
+
return null;
|
|
1680
1634
|
}
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1635
|
+
};
|
|
1636
|
+
const createVectorLineElement = (shape, points, options) => {
|
|
1637
|
+
return {
|
|
1638
|
+
id: idCreator(),
|
|
1639
|
+
type: 'vector-line',
|
|
1640
|
+
shape,
|
|
1641
|
+
opacity: 1,
|
|
1642
|
+
points,
|
|
1643
|
+
...options
|
|
1644
|
+
};
|
|
1645
|
+
};
|
|
1646
|
+
const vectorLineCreating = (board, lineShape, points, movingPoint, lineShapeG) => {
|
|
1647
|
+
const lineGenerator = new VectorLineShapeGenerator(board);
|
|
1648
|
+
const memorizedLatest = getLineMemorizedLatest();
|
|
1649
|
+
const temporaryLineElement = createVectorLineElement(lineShape, [...points, movingPoint], {
|
|
1650
|
+
strokeWidth: DefaultLineStyle.strokeWidth,
|
|
1651
|
+
...memorizedLatest
|
|
1652
|
+
});
|
|
1653
|
+
const otherPoint = points[points.length - 1];
|
|
1654
|
+
temporaryLineElement.points[temporaryLineElement.points.length - 1] = alignPoints(otherPoint, movingPoint);
|
|
1655
|
+
lineGenerator.processDrawing(temporaryLineElement, lineShapeG);
|
|
1656
|
+
PlaitBoard.getElementTopHost(board).append(lineShapeG);
|
|
1657
|
+
return temporaryLineElement;
|
|
1658
|
+
};
|
|
1659
|
+
const drawVectorLine = (board, element) => {
|
|
1660
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1661
|
+
const strokeColor = getStrokeColorByElement(board, element);
|
|
1662
|
+
const strokeStyle = getStrokeStyleByElement(board, element);
|
|
1663
|
+
const strokeLineDash = getStrokeLineDash(strokeStyle, strokeWidth);
|
|
1664
|
+
const fill = getFillByElement(board, element);
|
|
1665
|
+
const options = { stroke: strokeColor, strokeWidth, strokeLineDash, fill };
|
|
1666
|
+
const lineG = createG();
|
|
1667
|
+
let points = getVectorLinePoints(board, element);
|
|
1668
|
+
const line = drawLinearPath(points, options);
|
|
1669
|
+
const id = idCreator();
|
|
1670
|
+
line.setAttribute('mask', `url(#${id})`);
|
|
1671
|
+
if (element.strokeStyle === StrokeStyle.dotted) {
|
|
1672
|
+
setStrokeLinecap(line, 'round');
|
|
1693
1673
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
}
|
|
1704
|
-
if (startIndex > -1 && endIndex === -1) {
|
|
1705
|
-
const isReplace = startIndex < midDataPoints.length - 1 &&
|
|
1706
|
-
Point.isAlign([midDataPoints[startIndex], midDataPoints[startIndex + 1], startKeyPoint, endKeyPoint]);
|
|
1707
|
-
if (isReplace) {
|
|
1708
|
-
return {
|
|
1709
|
-
index: startIndex,
|
|
1710
|
-
deleteCount: 2
|
|
1711
|
-
};
|
|
1712
|
-
}
|
|
1713
|
-
return {
|
|
1714
|
-
index: startIndex,
|
|
1715
|
-
deleteCount: 1
|
|
1716
|
-
};
|
|
1717
|
-
}
|
|
1718
|
-
if (startIndex === -1 && endIndex > -1) {
|
|
1719
|
-
const isReplace = endIndex > 0 && Point.isAlign([midDataPoints[endIndex], midDataPoints[endIndex - 1], startKeyPoint, endKeyPoint]);
|
|
1720
|
-
if (isReplace) {
|
|
1721
|
-
return {
|
|
1722
|
-
index: endIndex - 1,
|
|
1723
|
-
deleteCount: 2
|
|
1724
|
-
};
|
|
1725
|
-
}
|
|
1726
|
-
return {
|
|
1727
|
-
index: endIndex,
|
|
1728
|
-
deleteCount: 1
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1674
|
+
lineG.appendChild(line);
|
|
1675
|
+
return lineG;
|
|
1676
|
+
};
|
|
1677
|
+
|
|
1678
|
+
const getCenterPointsOnPolygon$1 = (points) => {
|
|
1679
|
+
const centerPoints = [];
|
|
1680
|
+
for (let i = 0; i < points.length; i++) {
|
|
1681
|
+
let j = i == points.length - 1 ? 0 : i + 1;
|
|
1682
|
+
centerPoints.push([(points[i][0] + points[j][0]) / 2, (points[i][1] + points[j][1]) / 2]);
|
|
1731
1683
|
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
if (Point.isAlign([currentPoint, nextPoint, startKeyPoint])) {
|
|
1742
|
-
index = Math.min(i + 1, midDataPoints.length - 1);
|
|
1743
|
-
deleteCount = 1;
|
|
1744
|
-
break;
|
|
1745
|
-
}
|
|
1746
|
-
if (Point.isAlign([currentPoint, nextPoint, endKeyPoint])) {
|
|
1747
|
-
index = Math.max(i - 1, 0);
|
|
1748
|
-
deleteCount = 1;
|
|
1749
|
-
break;
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1684
|
+
return centerPoints;
|
|
1685
|
+
};
|
|
1686
|
+
const getCrossingPointBetweenPointAndPolygon = (corners, point) => {
|
|
1687
|
+
const result = [];
|
|
1688
|
+
for (let index = 1; index <= corners.length; index++) {
|
|
1689
|
+
let start = corners[index - 1];
|
|
1690
|
+
let end = index === corners.length ? corners[0] : corners[index];
|
|
1691
|
+
const crossingPoint = getCrossingPointsBetweenPointAndSegment(point, start, end);
|
|
1692
|
+
result.push(...crossingPoint);
|
|
1752
1693
|
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
const mirrorDataPoints = getMirrorDataPoints(board, nextDataPoints, nextKeyPoints, params);
|
|
1762
|
-
for (let i = handleIndex - 1; i >= 0; i--) {
|
|
1763
|
-
const previousIndex = mirrorDataPoints.slice(1, -1).findIndex(item => Point.isEquals(item, nextRenderPoints[i]));
|
|
1764
|
-
if (previousIndex > -1) {
|
|
1765
|
-
index = previousIndex + 1;
|
|
1766
|
-
break;
|
|
1767
|
-
}
|
|
1768
|
-
}
|
|
1769
|
-
if (index === null) {
|
|
1770
|
-
index = 0;
|
|
1771
|
-
// When renderPoints is a straight line and dataPoints are not on the line,
|
|
1772
|
-
// the default 'deleteCount' is set to midDataPoints.length.
|
|
1773
|
-
if (Point.isAlign(nextRenderPoints)) {
|
|
1774
|
-
deleteCount = midDataPoints.length;
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
else {
|
|
1779
|
-
index = 0;
|
|
1694
|
+
return result;
|
|
1695
|
+
};
|
|
1696
|
+
const getPolygonEdgeByConnectionPoint = (corners, point) => {
|
|
1697
|
+
for (let index = 1; index <= corners.length; index++) {
|
|
1698
|
+
let start = corners[index - 1];
|
|
1699
|
+
let end = index === corners.length ? corners[0] : corners[index];
|
|
1700
|
+
if (isPointOnSegment(point, start, end)) {
|
|
1701
|
+
return [start, end];
|
|
1780
1702
|
}
|
|
1781
1703
|
}
|
|
1782
|
-
return
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
*
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1704
|
+
return null;
|
|
1705
|
+
};
|
|
1706
|
+
|
|
1707
|
+
function generateCloudPath(rectangle) {
|
|
1708
|
+
const divisionWidth = rectangle.width / 7;
|
|
1709
|
+
const divisionHeight = rectangle.height / 3.2;
|
|
1710
|
+
const xRadius = divisionWidth / 8.5;
|
|
1711
|
+
const yRadius = divisionHeight / 20;
|
|
1712
|
+
const startPoint = [rectangle.x + divisionWidth, rectangle.y + divisionHeight];
|
|
1713
|
+
const arcCommands = [
|
|
1714
|
+
{
|
|
1715
|
+
rx: xRadius,
|
|
1716
|
+
ry: yRadius * 1.2,
|
|
1717
|
+
xAxisRotation: 0,
|
|
1718
|
+
largeArcFlag: 1,
|
|
1719
|
+
sweepFlag: 1,
|
|
1720
|
+
endX: rectangle.x + divisionWidth * 2,
|
|
1721
|
+
endY: rectangle.y + divisionHeight / 2
|
|
1722
|
+
},
|
|
1723
|
+
{
|
|
1724
|
+
rx: xRadius,
|
|
1725
|
+
ry: yRadius,
|
|
1726
|
+
xAxisRotation: 0,
|
|
1727
|
+
largeArcFlag: 1,
|
|
1728
|
+
sweepFlag: 1,
|
|
1729
|
+
endX: rectangle.x + divisionWidth * 4.2,
|
|
1730
|
+
endY: rectangle.y + divisionHeight / 2.2
|
|
1731
|
+
},
|
|
1732
|
+
{
|
|
1733
|
+
rx: xRadius,
|
|
1734
|
+
ry: yRadius,
|
|
1735
|
+
xAxisRotation: 0,
|
|
1736
|
+
largeArcFlag: 1,
|
|
1737
|
+
sweepFlag: 1,
|
|
1738
|
+
endX: rectangle.x + divisionWidth * 5.8,
|
|
1739
|
+
endY: rectangle.y + divisionHeight
|
|
1740
|
+
},
|
|
1741
|
+
{
|
|
1742
|
+
rx: xRadius,
|
|
1743
|
+
ry: yRadius * 1.3,
|
|
1744
|
+
xAxisRotation: 0,
|
|
1745
|
+
largeArcFlag: 1,
|
|
1746
|
+
sweepFlag: 1,
|
|
1747
|
+
endX: rectangle.x + divisionWidth * 6,
|
|
1748
|
+
endY: rectangle.y + divisionHeight * 2.2
|
|
1749
|
+
},
|
|
1750
|
+
{
|
|
1751
|
+
rx: xRadius,
|
|
1752
|
+
ry: yRadius * 1.2,
|
|
1753
|
+
xAxisRotation: 0,
|
|
1754
|
+
largeArcFlag: 1,
|
|
1755
|
+
sweepFlag: 1,
|
|
1756
|
+
endX: rectangle.x + divisionWidth * 5,
|
|
1757
|
+
endY: rectangle.y + divisionHeight * 2.8
|
|
1758
|
+
},
|
|
1759
|
+
{
|
|
1760
|
+
rx: xRadius,
|
|
1761
|
+
ry: yRadius / 1.2,
|
|
1762
|
+
xAxisRotation: 0,
|
|
1763
|
+
largeArcFlag: 1,
|
|
1764
|
+
sweepFlag: 1,
|
|
1765
|
+
endX: rectangle.x + divisionWidth * 2.8,
|
|
1766
|
+
endY: rectangle.y + divisionHeight * 2.8
|
|
1767
|
+
},
|
|
1768
|
+
{
|
|
1769
|
+
rx: xRadius,
|
|
1770
|
+
ry: yRadius,
|
|
1771
|
+
xAxisRotation: 0,
|
|
1772
|
+
largeArcFlag: 1,
|
|
1773
|
+
sweepFlag: 1,
|
|
1774
|
+
endX: rectangle.x + divisionWidth,
|
|
1775
|
+
endY: rectangle.y + divisionHeight * 2.2
|
|
1776
|
+
},
|
|
1777
|
+
{
|
|
1778
|
+
rx: xRadius,
|
|
1779
|
+
ry: yRadius * 1.42,
|
|
1780
|
+
xAxisRotation: 0,
|
|
1781
|
+
largeArcFlag: 1,
|
|
1782
|
+
sweepFlag: 1,
|
|
1783
|
+
endX: rectangle.x + divisionWidth,
|
|
1784
|
+
endY: rectangle.y + divisionHeight
|
|
1826
1785
|
}
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1786
|
+
];
|
|
1787
|
+
return { startPoint, arcCommands };
|
|
1788
|
+
}
|
|
1789
|
+
const CloudEngine = {
|
|
1790
|
+
draw(board, rectangle, options) {
|
|
1791
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
1792
|
+
const { startPoint, arcCommands } = generateCloudPath(rectangle);
|
|
1793
|
+
const pathData = `M ${startPoint[0]} ${startPoint[1]} ` +
|
|
1794
|
+
arcCommands
|
|
1795
|
+
.map((command) => `A ${command.rx} ${command.ry} ${command.xAxisRotation} ${command.largeArcFlag} ${command.sweepFlag} ${command.endX} ${command.endY}`)
|
|
1796
|
+
.join('\n') +
|
|
1797
|
+
' Z';
|
|
1798
|
+
const svgElement = rs.path(pathData, { ...options, fillStyle: 'solid' });
|
|
1799
|
+
setPathStrokeLinecap(svgElement, 'round');
|
|
1800
|
+
return svgElement;
|
|
1801
|
+
},
|
|
1802
|
+
isInsidePoint(rectangle, point) {
|
|
1803
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
1804
|
+
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
1805
|
+
},
|
|
1806
|
+
getCornerPoints(rectangle) {
|
|
1807
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
1808
|
+
},
|
|
1809
|
+
getNearestPoint(rectangle, point) {
|
|
1810
|
+
const { startPoint, arcCommands } = generateCloudPath(rectangle);
|
|
1811
|
+
let minDistance = Infinity;
|
|
1812
|
+
let nearestPoint = point;
|
|
1813
|
+
let currentStart = startPoint;
|
|
1814
|
+
for (const arcCommand of arcCommands) {
|
|
1815
|
+
const arcNearestPoint = getNearestPointBetweenPointAndArc(point, currentStart, arcCommand);
|
|
1816
|
+
const distance = distanceBetweenPointAndPoint(point[0], point[1], arcNearestPoint[0], arcNearestPoint[1]);
|
|
1817
|
+
if (distance < minDistance) {
|
|
1818
|
+
minDistance = distance;
|
|
1819
|
+
nearestPoint = arcNearestPoint;
|
|
1839
1820
|
}
|
|
1821
|
+
currentStart = [arcCommand.endX, arcCommand.endY];
|
|
1840
1822
|
}
|
|
1823
|
+
return nearestPoint;
|
|
1824
|
+
},
|
|
1825
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
1826
|
+
const corners = CloudEngine.getCornerPoints(rectangle);
|
|
1827
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
1828
|
+
return getPolygonEdgeByConnectionPoint(corners, point);
|
|
1829
|
+
},
|
|
1830
|
+
getConnectorPoints(rectangle) {
|
|
1831
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
1832
|
+
},
|
|
1833
|
+
getTextRectangle(element) {
|
|
1834
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
1835
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1836
|
+
const height = element.textHeight;
|
|
1837
|
+
const originWidth = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
1838
|
+
const width = originWidth / 1.5;
|
|
1839
|
+
return {
|
|
1840
|
+
height,
|
|
1841
|
+
width: width > 0 ? width : 0,
|
|
1842
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + originWidth / 6,
|
|
1843
|
+
y: elementRectangle.y + elementRectangle.height / 6 + ((elementRectangle.height * 4) / 6 - height) / 2
|
|
1844
|
+
};
|
|
1841
1845
|
}
|
|
1842
1846
|
};
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1847
|
+
|
|
1848
|
+
const isTextExceedingBounds = (geometry) => {
|
|
1849
|
+
const client = RectangleClient.getRectangleByPoints(geometry.points);
|
|
1850
|
+
if (geometry.textHeight && geometry.textHeight > client.height) {
|
|
1846
1851
|
return true;
|
|
1847
1852
|
}
|
|
1848
1853
|
return false;
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1854
|
+
};
|
|
1855
|
+
const isHitArrowLineText = (board, element, point) => {
|
|
1856
|
+
return getHitArrowLineTextIndex(board, element, point) !== -1;
|
|
1857
|
+
};
|
|
1858
|
+
const isHitPolyLine = (pathPoints, point) => {
|
|
1859
|
+
const distance = distanceBetweenPointAndSegments(point, pathPoints);
|
|
1860
|
+
return distance <= HIT_DISTANCE_BUFFER;
|
|
1861
|
+
};
|
|
1862
|
+
const isHitArrowLine = (board, element, point) => {
|
|
1863
|
+
const points = getArrowLinePoints(board, element);
|
|
1864
|
+
const isHitText = isHitArrowLineText(board, element, point);
|
|
1865
|
+
return isHitText || isHitPolyLine(points, point);
|
|
1866
|
+
};
|
|
1867
|
+
const isHitVectorLine = (board, element, point) => {
|
|
1868
|
+
const points = getVectorLinePoints(board, element);
|
|
1869
|
+
if (isClosedPoints(element.points)) {
|
|
1870
|
+
return isPointInPolygon(point, points) || isHitPolyLine(points, point);
|
|
1862
1871
|
}
|
|
1863
|
-
|
|
1864
|
-
|
|
1872
|
+
else {
|
|
1873
|
+
return isHitPolyLine(points, point);
|
|
1865
1874
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
if (isHorizontalSegment && isHorizontal) {
|
|
1876
|
-
parallelSegments.push([current, next]);
|
|
1877
|
-
}
|
|
1878
|
-
if (!isHorizontalSegment && !isHorizontal) {
|
|
1879
|
-
parallelSegments.push([current, next]);
|
|
1880
|
-
}
|
|
1875
|
+
};
|
|
1876
|
+
const isRectangleHitElementText = (element, rectangle) => {
|
|
1877
|
+
const engine = getEngine(element.shape);
|
|
1878
|
+
if (isMultipleTextGeometry(element)) {
|
|
1879
|
+
const texts = element.texts;
|
|
1880
|
+
return texts.some((item) => {
|
|
1881
|
+
const textClient = engine.getTextRectangle(element, { id: item.id });
|
|
1882
|
+
return isRectangleHitRotatedPoints(rectangle, RectangleClient.getCornerPoints(textClient), element.angle);
|
|
1883
|
+
});
|
|
1881
1884
|
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
debugGenerator$3.isDebug() && debugGenerator$3.clear();
|
|
1886
|
-
const mirrorSegments = [];
|
|
1887
|
-
for (let index = 0; index < parallelSegments.length; index++) {
|
|
1888
|
-
const parallelPath = parallelSegments[index];
|
|
1889
|
-
const startPoint = [segment[0][0], segment[0][1]];
|
|
1890
|
-
const endPoint = [segment[1][0], segment[1][1]];
|
|
1891
|
-
const isHorizontal = Point.isHorizontal(startPoint, endPoint);
|
|
1892
|
-
const adjustDataIndex = isHorizontal ? 0 : 1;
|
|
1893
|
-
startPoint[adjustDataIndex] = parallelPath[0][adjustDataIndex];
|
|
1894
|
-
endPoint[adjustDataIndex] = parallelPath[1][adjustDataIndex];
|
|
1895
|
-
const fakeRectangle = RectangleClient.getRectangleByPoints([startPoint, endPoint, ...parallelPath]);
|
|
1896
|
-
const isValid = !RectangleClient.isHit(fakeRectangle, sourceRectangle) && !RectangleClient.isHit(fakeRectangle, targetRectangle);
|
|
1897
|
-
if (isValid) {
|
|
1898
|
-
mirrorSegments.push([startPoint, endPoint]);
|
|
1899
|
-
debugGenerator$3.isDebug() && debugGenerator$3.drawPolygon(board, RectangleClient.getCornerPoints(fakeRectangle));
|
|
1900
|
-
}
|
|
1885
|
+
else {
|
|
1886
|
+
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
1887
|
+
return isRectangleHitRotatedPoints(rectangle, RectangleClient.getCornerPoints(textClient), element.angle);
|
|
1901
1888
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
const
|
|
1905
|
-
if (
|
|
1889
|
+
};
|
|
1890
|
+
const isHitElementText = (element, point) => {
|
|
1891
|
+
const engine = getEngine(element.shape);
|
|
1892
|
+
if (isMultipleTextGeometry(element)) {
|
|
1893
|
+
const texts = element.texts;
|
|
1894
|
+
return texts.some((item) => {
|
|
1895
|
+
const textClient = engine.getTextRectangle(element, { id: item.id });
|
|
1896
|
+
return RectangleClient.isPointInRectangle(textClient, point);
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
else {
|
|
1900
|
+
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
1901
|
+
return RectangleClient.isPointInRectangle(textClient, point);
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
const isEmptyTextElement = (element) => {
|
|
1905
|
+
if (!isDrawElementIncludeText(element)) {
|
|
1906
1906
|
return true;
|
|
1907
1907
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
const
|
|
1915
|
-
if (
|
|
1916
|
-
return
|
|
1917
|
-
}
|
|
1918
|
-
if (index === midDataPoints.length - 1) {
|
|
1919
|
-
return !isStraightWithBefore;
|
|
1908
|
+
const editor = getFirstTextEditor(element);
|
|
1909
|
+
return Editor.isEmpty(editor, editor.children[0]);
|
|
1910
|
+
};
|
|
1911
|
+
const isRectangleHitDrawElement = (board, element, selection) => {
|
|
1912
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([selection.anchor, selection.focus]);
|
|
1913
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
1914
|
+
const isHitElement = isRectangleHitRotatedElement(board, rangeRectangle, element);
|
|
1915
|
+
if (isHitElement) {
|
|
1916
|
+
return isHitElement;
|
|
1920
1917
|
}
|
|
1921
|
-
return !
|
|
1922
|
-
}
|
|
1918
|
+
return !isEmptyTextElement(element) && isRectangleHitElementText(element, rangeRectangle);
|
|
1919
|
+
}
|
|
1920
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
1921
|
+
return isRectangleHitRotatedElement(board, rangeRectangle, element);
|
|
1922
|
+
}
|
|
1923
|
+
if (PlaitDrawElement.isArrowLine(element)) {
|
|
1924
|
+
const points = getArrowLinePoints(board, element);
|
|
1925
|
+
return isLineHitRectangle(points, rangeRectangle);
|
|
1926
|
+
}
|
|
1927
|
+
if (PlaitDrawElement.isVectorLine(element)) {
|
|
1928
|
+
const points = getVectorLinePoints(board, element);
|
|
1929
|
+
return isLineHitRectangle(points, rangeRectangle);
|
|
1930
|
+
}
|
|
1931
|
+
return null;
|
|
1923
1932
|
};
|
|
1924
|
-
|
|
1925
|
-
const
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1933
|
+
const isRectangleHitRotatedElement = (board, rectangle, element) => {
|
|
1934
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1935
|
+
return isRectangleHitRotatedPoints(rectangle, RectangleClient.getCornerPoints(client), element.angle);
|
|
1936
|
+
};
|
|
1937
|
+
const isRectangleHitRotatedPoints = (rectangle, points, angle) => {
|
|
1938
|
+
let rotatedPoints = rotatePointsByAngle(points, angle) || points;
|
|
1939
|
+
return isLineHitRectangle(rotatedPoints, rectangle);
|
|
1940
|
+
};
|
|
1941
|
+
const getHitDrawElement = (board, elements) => {
|
|
1942
|
+
let firstFilledElement = getFirstFilledDrawElement(board, elements);
|
|
1943
|
+
let endIndex = elements.length;
|
|
1944
|
+
if (firstFilledElement) {
|
|
1945
|
+
endIndex = elements.indexOf(firstFilledElement) + 1;
|
|
1930
1946
|
}
|
|
1931
|
-
const
|
|
1932
|
-
const
|
|
1933
|
-
if (
|
|
1934
|
-
|
|
1947
|
+
const newElements = elements.slice(0, endIndex);
|
|
1948
|
+
const element = getFirstTextOrLineElement(newElements);
|
|
1949
|
+
if (element) {
|
|
1950
|
+
return element;
|
|
1935
1951
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1952
|
+
const sortElements = sortElementsByArea(board, newElements, 'asc');
|
|
1953
|
+
return sortElements[0];
|
|
1954
|
+
};
|
|
1955
|
+
const getFirstFilledDrawElement = (board, elements) => {
|
|
1956
|
+
let filledElement = null;
|
|
1957
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1958
|
+
const element = elements[i];
|
|
1959
|
+
if (isClosedCustomGeometry(board, element) || isClosedDrawElement(element)) {
|
|
1960
|
+
const fill = getFillByElement(board, element);
|
|
1961
|
+
if (isFilled(fill)) {
|
|
1962
|
+
filledElement = element;
|
|
1963
|
+
break;
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1940
1966
|
}
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1967
|
+
return filledElement;
|
|
1968
|
+
};
|
|
1969
|
+
const isFilledDrawElement = (board, element) => {
|
|
1970
|
+
return getFirstFilledDrawElement(board, [element]) !== null;
|
|
1971
|
+
};
|
|
1972
|
+
const getFirstTextOrLineElement = (elements) => {
|
|
1973
|
+
const texts = elements.filter((item) => PlaitDrawElement.isText(item));
|
|
1974
|
+
if (texts.length) {
|
|
1975
|
+
return texts[0];
|
|
1976
|
+
}
|
|
1977
|
+
const lines = elements.filter((item) => PlaitDrawElement.isArrowLine(item));
|
|
1978
|
+
if (lines.length) {
|
|
1979
|
+
return lines[0];
|
|
1945
1980
|
}
|
|
1946
|
-
return
|
|
1981
|
+
return null;
|
|
1947
1982
|
};
|
|
1948
|
-
const
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1983
|
+
const debugKey$3 = 'debug:plait:hit:shape:edge:sample-points';
|
|
1984
|
+
const debugGenerator$3 = createDebugGenerator(debugKey$3);
|
|
1985
|
+
const shapes = [BasicShapes.cloud];
|
|
1986
|
+
const isHitDrawElement = (board, element, point, isStrict = true) => {
|
|
1987
|
+
const rectangle = board.getRectangle(element);
|
|
1988
|
+
point = rotateAntiPointsByElement(board, point, element) || point;
|
|
1989
|
+
if (PlaitDrawElement.isGeometry(element) && rectangle) {
|
|
1990
|
+
if (debugGenerator$3.isDebug() && shapes.includes(element.shape)) {
|
|
1991
|
+
debugGenerator$3.clear();
|
|
1992
|
+
const { startPoint, arcCommands } = generateCloudPath(rectangle);
|
|
1993
|
+
const points = [startPoint, ...arcCommands.map((arc) => [arc.endX, arc.endY])];
|
|
1994
|
+
debugGenerator$3.drawCircles(board, points, 5, false);
|
|
1995
|
+
let minDistance = Infinity;
|
|
1996
|
+
let nearestPoint = point;
|
|
1997
|
+
let currentStart = startPoint;
|
|
1998
|
+
for (const arc of arcCommands) {
|
|
1999
|
+
const arcNearestPoint = getNearestPointBetweenPointAndArc(point, currentStart, arc);
|
|
2000
|
+
const distance = distanceBetweenPointAndPoint(point[0], point[1], arcNearestPoint[0], arcNearestPoint[1]);
|
|
2001
|
+
const { center } = getEllipseArcCenter(currentStart, arc);
|
|
2002
|
+
debugGenerator$3.drawCircles(board, [center], 8, false, { fill: 'yellow' });
|
|
2003
|
+
if (distance < minDistance) {
|
|
2004
|
+
minDistance = distance;
|
|
2005
|
+
nearestPoint = arcNearestPoint;
|
|
2006
|
+
}
|
|
2007
|
+
currentStart = [arc.endX, arc.endY];
|
|
2008
|
+
}
|
|
2009
|
+
debugGenerator$3.drawCircles(board, [point], 12, false, { fill: 'black', stroke: 'black' });
|
|
2010
|
+
debugGenerator$3.drawCircles(board, [nearestPoint], 12, false, { fill: 'green', stroke: 'green' });
|
|
1971
2011
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
break;
|
|
2012
|
+
if (isHitEdgeOfShape(board, element, point, HIT_DISTANCE_BUFFER)) {
|
|
2013
|
+
return true;
|
|
1975
2014
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2015
|
+
const engine = getEngine(getElementShape(element));
|
|
2016
|
+
if (PlaitDrawElement.isText(element)) {
|
|
2017
|
+
const textClient = getTextRectangle(element);
|
|
2018
|
+
return RectangleClient.isPointInRectangle(textClient, point);
|
|
1979
2019
|
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
break;
|
|
2020
|
+
if (!!isStrict && isEmptyTextElement(element) && !isFilledDrawElement(board, element)) {
|
|
2021
|
+
return false;
|
|
1983
2022
|
}
|
|
2023
|
+
const isHitText = isHitElementText(element, point);
|
|
2024
|
+
return isHitText || engine.isInsidePoint(rectangle, point);
|
|
1984
2025
|
}
|
|
1985
|
-
|
|
2026
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
2027
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
2028
|
+
return RectangleClient.isPointInRectangle(client, point);
|
|
2029
|
+
}
|
|
2030
|
+
if (PlaitDrawElement.isArrowLine(element)) {
|
|
2031
|
+
return isHitArrowLine(board, element, point);
|
|
2032
|
+
}
|
|
2033
|
+
if (PlaitDrawElement.isVectorLine(element)) {
|
|
2034
|
+
return isHitVectorLine(board, element, point);
|
|
2035
|
+
}
|
|
2036
|
+
return null;
|
|
1986
2037
|
};
|
|
1987
|
-
const
|
|
1988
|
-
const
|
|
1989
|
-
const
|
|
1990
|
-
|
|
1991
|
-
const path = createPath();
|
|
1992
|
-
let polylinePath = `M${pointRight[0]},${pointRight[1]}A25,25,20,0,1,${pointLeft[0]},${pointLeft[1]}L${startPoint[0]},${startPoint[1]}Z`;
|
|
1993
|
-
path.setAttribute('d', polylinePath);
|
|
1994
|
-
path.setAttribute('stroke', `${options?.stroke}`);
|
|
1995
|
-
path.setAttribute('stroke-width', `${options?.strokeWidth}`);
|
|
1996
|
-
path.setAttribute('fill', `${options?.stroke}`);
|
|
1997
|
-
g.appendChild(path);
|
|
1998
|
-
return g;
|
|
2038
|
+
const isHitEdgeOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
2039
|
+
const nearestPoint = getNearestPoint(element, point);
|
|
2040
|
+
const distance = distanceBetweenPointAndPoint(nearestPoint[0], nearestPoint[1], point[0], point[1]);
|
|
2041
|
+
return distance <= hitDistanceBuffer;
|
|
1999
2042
|
};
|
|
2000
|
-
const
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2003
|
-
const endPoint = [target[0] + (strokeWidth * unitVector[0]) / 2, target[1] + (strokeWidth * unitVector[1]) / 2];
|
|
2004
|
-
const distance = distanceBetweenPointAndPoint(...source, ...endPoint);
|
|
2005
|
-
const middlePoint = [
|
|
2006
|
-
endPoint[0] - (((distance * 3) / 5 + strokeWidth) / 2) * unitVector[0],
|
|
2007
|
-
endPoint[1] - (((distance * 3) / 5 + strokeWidth) / 2) * unitVector[1]
|
|
2008
|
-
];
|
|
2009
|
-
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 30);
|
|
2010
|
-
const arrowG = drawLinearPath([pointLeft, endPoint, pointRight, middlePoint], { ...options, fill: options.stroke }, true);
|
|
2011
|
-
const path = arrowG.querySelector('path');
|
|
2012
|
-
path.setAttribute('stroke-linejoin', 'round');
|
|
2013
|
-
return arrowG;
|
|
2043
|
+
const isInsideOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
2044
|
+
const client = RectangleClient.inflate(RectangleClient.getRectangleByPoints(element.points), hitDistanceBuffer);
|
|
2045
|
+
return getEngine(getElementShape(element)).isInsidePoint(client, point);
|
|
2014
2046
|
};
|
|
2015
|
-
const
|
|
2016
|
-
const
|
|
2017
|
-
|
|
2018
|
-
|
|
2047
|
+
const isHitElementInside = (board, element, point) => {
|
|
2048
|
+
const rectangle = board.getRectangle(element);
|
|
2049
|
+
point = rotateAntiPointsByElement(board, point, element) || point;
|
|
2050
|
+
if (PlaitDrawElement.isGeometry(element) && !PlaitDrawElement.isGeometryByTable(element)) {
|
|
2051
|
+
const engine = getEngine(getElementShape(element));
|
|
2052
|
+
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
2053
|
+
if (isHitInside) {
|
|
2054
|
+
return isHitInside;
|
|
2055
|
+
}
|
|
2056
|
+
if (engine.getTextRectangle) {
|
|
2057
|
+
const isHitText = isHitElementText(element, point);
|
|
2058
|
+
if (isHitText) {
|
|
2059
|
+
return isHitText;
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
2064
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
2065
|
+
return RectangleClient.isPointInRectangle(client, point);
|
|
2066
|
+
}
|
|
2067
|
+
if (PlaitDrawElement.isArrowLine(element)) {
|
|
2068
|
+
return isHitArrowLine(board, element, point);
|
|
2069
|
+
}
|
|
2070
|
+
if (PlaitDrawElement.isVectorLine(element)) {
|
|
2071
|
+
return isHitVectorLine(board, element, point);
|
|
2072
|
+
}
|
|
2073
|
+
return null;
|
|
2019
2074
|
};
|
|
2020
|
-
|
|
2021
|
-
|
|
2075
|
+
|
|
2076
|
+
const getTextRectangle = (element) => {
|
|
2077
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2022
2078
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
2023
|
-
const
|
|
2024
|
-
const
|
|
2025
|
-
return
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2079
|
+
const height = element.textHeight;
|
|
2080
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
2081
|
+
return {
|
|
2082
|
+
height,
|
|
2083
|
+
width: width > 0 ? width : 0,
|
|
2084
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
2085
|
+
y: elementRectangle.y + (elementRectangle.height - height) / 2
|
|
2086
|
+
};
|
|
2030
2087
|
};
|
|
2031
|
-
const
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
return drawLinearPath([start, end], options);
|
|
2088
|
+
const getStrokeWidthByElement = (element) => {
|
|
2089
|
+
if (PlaitDrawElement.isText(element)) {
|
|
2090
|
+
return 0;
|
|
2091
|
+
}
|
|
2092
|
+
const strokeWidth = element.strokeWidth || DefaultDrawStyle.strokeWidth;
|
|
2093
|
+
return strokeWidth;
|
|
2038
2094
|
};
|
|
2039
|
-
const
|
|
2040
|
-
|
|
2041
|
-
|
|
2095
|
+
const insertElement = (board, element) => {
|
|
2096
|
+
memorizeLatestShape(board, element.shape);
|
|
2097
|
+
Transforms.insertNode(board, element, [board.children.length]);
|
|
2098
|
+
clearSelectedElement(board);
|
|
2099
|
+
addSelectedElement(board, element);
|
|
2100
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
2042
2101
|
};
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
canDraw(element) {
|
|
2102
|
+
const isDrawElementIncludeText = (element) => {
|
|
2103
|
+
if (PlaitDrawElement.isText(element)) {
|
|
2046
2104
|
return true;
|
|
2047
2105
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
lineG = drawArrowLine(this.board, element);
|
|
2051
|
-
return lineG;
|
|
2106
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
2107
|
+
return false;
|
|
2052
2108
|
}
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
target,
|
|
2063
|
-
opacity: 1,
|
|
2064
|
-
points,
|
|
2065
|
-
...options
|
|
2066
|
-
};
|
|
2067
|
-
};
|
|
2068
|
-
const getArrowLinePoints = (board, element) => {
|
|
2069
|
-
switch (element.shape) {
|
|
2070
|
-
case ArrowLineShape.elbow: {
|
|
2071
|
-
return getElbowPoints(board, element);
|
|
2072
|
-
}
|
|
2073
|
-
case ArrowLineShape.curve: {
|
|
2074
|
-
return getCurvePoints(board, element);
|
|
2075
|
-
}
|
|
2076
|
-
default: {
|
|
2077
|
-
const points = PlaitArrowLine.getPoints(board, element);
|
|
2078
|
-
const handleRefPair = getArrowLineHandleRefPair(board, element);
|
|
2079
|
-
points[0] = handleRefPair.source.point;
|
|
2080
|
-
points[points.length - 1] = handleRefPair.target.point;
|
|
2081
|
-
return points;
|
|
2082
|
-
}
|
|
2109
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
2110
|
+
return isGeometryIncludeText(element);
|
|
2111
|
+
}
|
|
2112
|
+
if (PlaitDrawElement.isArrowLine(element)) {
|
|
2113
|
+
const editors = getTextEditorsByElement(element);
|
|
2114
|
+
return editors.length > 0;
|
|
2115
|
+
}
|
|
2116
|
+
if (PlaitDrawElement.isElementByTable(element)) {
|
|
2117
|
+
return element.cells.some((cell) => isCellIncludeText(cell));
|
|
2083
2118
|
}
|
|
2119
|
+
return true;
|
|
2084
2120
|
};
|
|
2085
|
-
const
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
if (sourceBoundElement) {
|
|
2095
|
-
curvePoints.push(getPointByVectorComponent(source.point, source.vector, offset));
|
|
2096
|
-
}
|
|
2097
|
-
if (targetBoundElement) {
|
|
2098
|
-
curvePoints.push(getPointByVectorComponent(target.point, target.vector, offset));
|
|
2121
|
+
const isDrawElementsIncludeText = (elements) => {
|
|
2122
|
+
return elements.some((item) => {
|
|
2123
|
+
return isDrawElementIncludeText(item);
|
|
2124
|
+
});
|
|
2125
|
+
};
|
|
2126
|
+
const isClosedDrawElement = (element) => {
|
|
2127
|
+
if (PlaitDrawElement.isDrawElement(element)) {
|
|
2128
|
+
if (PlaitDrawElement.isText(element) || PlaitDrawElement.isArrowLine(element) || PlaitDrawElement.isImage(element)) {
|
|
2129
|
+
return false;
|
|
2099
2130
|
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
curvePoints.push(target.point);
|
|
2103
|
-
const points = Q2C(curvePoints);
|
|
2104
|
-
return pointsOnBezierCurves(points);
|
|
2131
|
+
if (PlaitDrawElement.isVectorLine(element)) {
|
|
2132
|
+
return isClosedPoints(element.points);
|
|
2105
2133
|
}
|
|
2106
|
-
if (
|
|
2107
|
-
|
|
2108
|
-
curvePoints.push(getPointByVectorComponent(target.point, target.vector, offset));
|
|
2134
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
2135
|
+
return isGeometryClosed(element);
|
|
2109
2136
|
}
|
|
2110
|
-
|
|
2111
|
-
return pointsOnBezierCurves(curvePoints);
|
|
2112
|
-
}
|
|
2113
|
-
else {
|
|
2114
|
-
let dataPoints = PlaitArrowLine.getPoints(board, element);
|
|
2115
|
-
dataPoints = removeDuplicatePoints(dataPoints);
|
|
2116
|
-
const points = catmullRomFitting(dataPoints);
|
|
2117
|
-
return pointsOnBezierCurves(points);
|
|
2137
|
+
return true;
|
|
2118
2138
|
}
|
|
2139
|
+
return false;
|
|
2119
2140
|
};
|
|
2120
|
-
const
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
line = PlaitBoard.getRoughSVG(board).curve(points, options);
|
|
2131
|
-
}
|
|
2132
|
-
else {
|
|
2133
|
-
line = drawLinearPath(points, options);
|
|
2134
|
-
}
|
|
2135
|
-
const id = idCreator();
|
|
2136
|
-
line.setAttribute('mask', `url(#${id})`);
|
|
2137
|
-
if (element.strokeStyle === StrokeStyle.dotted) {
|
|
2138
|
-
setStrokeLinecap(line, 'round');
|
|
2141
|
+
const isClosedCustomGeometry = (board, value) => {
|
|
2142
|
+
return PlaitDrawElement.isCustomGeometryElement(board, value) && isClosedPoints(value.points);
|
|
2143
|
+
};
|
|
2144
|
+
const getSnappingShape = (board, point) => {
|
|
2145
|
+
let hitElement = getHitShape(board, point);
|
|
2146
|
+
if (hitElement) {
|
|
2147
|
+
const ref = getSnappingRef(board, hitElement, point);
|
|
2148
|
+
if (ref.isHitConnector || ref.isHitEdge) {
|
|
2149
|
+
return hitElement;
|
|
2150
|
+
}
|
|
2139
2151
|
}
|
|
2140
|
-
|
|
2141
|
-
const { mask, maskTargetFillRect } = drawArrowLineMask(board, element, id);
|
|
2142
|
-
lineG.appendChild(mask);
|
|
2143
|
-
line.appendChild(maskTargetFillRect);
|
|
2144
|
-
const arrow = drawArrowLineArrow(element, points, { stroke: strokeColor, strokeWidth });
|
|
2145
|
-
arrow && lineG.appendChild(arrow);
|
|
2146
|
-
return lineG;
|
|
2152
|
+
return null;
|
|
2147
2153
|
};
|
|
2148
|
-
const
|
|
2149
|
-
|
|
2150
|
-
const
|
|
2151
|
-
const
|
|
2152
|
-
|
|
2154
|
+
const getSnappingRef = (board, hitElement, point) => {
|
|
2155
|
+
const rotatedPoint = rotateAntiPointsByElement(board, point, hitElement) || point;
|
|
2156
|
+
const connectorPoint = getHitConnectorPoint(rotatedPoint, hitElement);
|
|
2157
|
+
const edgePoint = getNearestPoint(hitElement, rotatedPoint);
|
|
2158
|
+
const isHitEdge = isHitEdgeOfShape(board, hitElement, rotatedPoint, LINE_SNAPPING_BUFFER);
|
|
2159
|
+
return { isHitEdge, isHitConnector: !!connectorPoint, connectorPoint, edgePoint };
|
|
2153
2160
|
};
|
|
2154
|
-
const
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2161
|
+
const getHitShape = (board, point, offset = LINE_HIT_GEOMETRY_BUFFER) => {
|
|
2162
|
+
let hitShape = null;
|
|
2163
|
+
traverseDrawShapes(board, (element) => {
|
|
2164
|
+
if (hitShape === null && isInsideOfShape(board, element, rotateAntiPointsByElement(board, point, element) || point, offset * 2)) {
|
|
2165
|
+
hitShape = element;
|
|
2166
|
+
}
|
|
2160
2167
|
});
|
|
2168
|
+
return hitShape;
|
|
2161
2169
|
};
|
|
2162
|
-
const
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
y: point[1] - text.height / 2,
|
|
2169
|
-
width: text.width,
|
|
2170
|
-
height: text.height
|
|
2171
|
-
};
|
|
2170
|
+
const traverseDrawShapes = (board, callback) => {
|
|
2171
|
+
depthFirstRecursion(board, (node) => {
|
|
2172
|
+
if (!PlaitBoard.isBoard(node) && PlaitDrawElement.isShapeElement(node)) {
|
|
2173
|
+
callback(node);
|
|
2174
|
+
}
|
|
2175
|
+
}, getIsRecursionFunc(board), true);
|
|
2172
2176
|
};
|
|
2173
|
-
const
|
|
2174
|
-
return
|
|
2175
|
-
match: (element) => PlaitDrawElement.isArrowLine(element),
|
|
2176
|
-
recursion: (element) => PlaitDrawElement.isDrawElement(element)
|
|
2177
|
-
});
|
|
2177
|
+
const drawShape = (board, outerRectangle, shape, roughOptions, drawOptions) => {
|
|
2178
|
+
return getEngine(shape).draw(board, outerRectangle, roughOptions, drawOptions);
|
|
2178
2179
|
};
|
|
2179
|
-
|
|
2180
|
-
const
|
|
2181
|
-
const
|
|
2182
|
-
const
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
const startDistance = distanceBetweenPointAndPoint(...start, ...qControl);
|
|
2188
|
-
const endDistance = distanceBetweenPointAndPoint(...end, ...qControl);
|
|
2189
|
-
const cControl1 = getExtendPoint(start, qControl, (startDistance * 2) / 3);
|
|
2190
|
-
const cControl2 = getExtendPoint(end, qControl, (endDistance * 2) / 3);
|
|
2191
|
-
result.push(start, cControl1, cControl2, end);
|
|
2180
|
+
const drawBoundReaction = (board, element, roughOptions = { hasMask: true, hasConnector: true }) => {
|
|
2181
|
+
const g = createG();
|
|
2182
|
+
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2183
|
+
const activeRectangle = RectangleClient.inflate(rectangle, SNAPPING_STROKE_WIDTH);
|
|
2184
|
+
const shape = getElementShape(element);
|
|
2185
|
+
let drawOptions;
|
|
2186
|
+
if (PlaitDrawElement.isElementByTable(element)) {
|
|
2187
|
+
drawOptions = { element };
|
|
2192
2188
|
}
|
|
2193
|
-
|
|
2189
|
+
const strokeG = drawShape(board, activeRectangle, shape, {
|
|
2190
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
2191
|
+
strokeWidth: SNAPPING_STROKE_WIDTH
|
|
2192
|
+
}, drawOptions);
|
|
2193
|
+
g.appendChild(strokeG);
|
|
2194
|
+
if (roughOptions.hasMask) {
|
|
2195
|
+
const maskG = drawShape(board, activeRectangle, shape, {
|
|
2196
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
2197
|
+
strokeWidth: 0,
|
|
2198
|
+
fill: isClosedDrawElement(element) ? SELECTION_FILL_COLOR : DefaultDrawStyle.fill,
|
|
2199
|
+
fillStyle: 'solid'
|
|
2200
|
+
}, drawOptions);
|
|
2201
|
+
g.appendChild(maskG);
|
|
2202
|
+
}
|
|
2203
|
+
if (roughOptions.hasConnector) {
|
|
2204
|
+
const connectorPoints = getEngine(shape).getConnectorPoints(rectangle);
|
|
2205
|
+
connectorPoints.forEach((point) => {
|
|
2206
|
+
const circleG = drawCircle(PlaitBoard.getRoughSVG(board), point, 8, {
|
|
2207
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
2208
|
+
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
2209
|
+
fill: '#FFF',
|
|
2210
|
+
fillStyle: 'solid'
|
|
2211
|
+
});
|
|
2212
|
+
g.appendChild(circleG);
|
|
2213
|
+
});
|
|
2214
|
+
}
|
|
2215
|
+
return g;
|
|
2194
2216
|
};
|
|
2195
|
-
const
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
}
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
+
const getTextKey = (element, text) => {
|
|
2218
|
+
if (element && isMultipleTextGeometry(element)) {
|
|
2219
|
+
return `${element.id}-${text.id}`;
|
|
2220
|
+
}
|
|
2221
|
+
else {
|
|
2222
|
+
return text.id;
|
|
2223
|
+
}
|
|
2224
|
+
};
|
|
2225
|
+
const getGeometryAlign = (board, element) => {
|
|
2226
|
+
if (isMultipleTextGeometry(element)) {
|
|
2227
|
+
const drawShapeText = element.texts.find((item) => item.id.includes(GeometryCommonTextKeys.content));
|
|
2228
|
+
return drawShapeText?.text.align || Alignment.center;
|
|
2229
|
+
}
|
|
2230
|
+
if (isSingleTextGeometry(element)) {
|
|
2231
|
+
return element.text?.align || Alignment.center;
|
|
2232
|
+
}
|
|
2233
|
+
if (PlaitDrawElement.isElementByTable(element)) {
|
|
2234
|
+
const firstTextCell = element.cells.find((item) => item.text);
|
|
2235
|
+
return firstTextCell?.text?.align || Alignment.center;
|
|
2236
|
+
}
|
|
2237
|
+
return Alignment.center;
|
|
2238
|
+
};
|
|
2239
|
+
const isClosedPoints = (points) => {
|
|
2240
|
+
const startPoint = points[0];
|
|
2241
|
+
const endPoint = points[points.length - 1];
|
|
2242
|
+
return startPoint[0] === endPoint[0] && startPoint[1] === endPoint[1];
|
|
2243
|
+
};
|
|
2244
|
+
const getDefaultGeometryText = (board) => {
|
|
2245
|
+
return getI18nValue(board, DrawI18nKey.geometryText, DefaultTextProperty.text);
|
|
2217
2246
|
};
|
|
2218
|
-
function drawArrowLineMask(board, element, id) {
|
|
2219
|
-
const mask = createMask();
|
|
2220
|
-
mask.setAttribute('id', id);
|
|
2221
|
-
const points = getArrowLinePoints(board, element);
|
|
2222
|
-
let rectangle = RectangleClient.getRectangleByPoints(points);
|
|
2223
|
-
rectangle = RectangleClient.getOutlineRectangle(rectangle, -30);
|
|
2224
|
-
const maskFillRect = createRect(rectangle, {
|
|
2225
|
-
fill: 'white'
|
|
2226
|
-
});
|
|
2227
|
-
mask.appendChild(maskFillRect);
|
|
2228
|
-
const texts = element.texts;
|
|
2229
|
-
texts.forEach((text, index) => {
|
|
2230
|
-
let textRectangle = getArrowLineTextRectangle(board, element, index);
|
|
2231
|
-
textRectangle = RectangleClient.inflate(textRectangle, LINE_TEXT_SPACE * 2);
|
|
2232
|
-
const rect = createRect(textRectangle, {
|
|
2233
|
-
fill: 'black'
|
|
2234
|
-
});
|
|
2235
|
-
mask.appendChild(rect);
|
|
2236
|
-
});
|
|
2237
|
-
// open line
|
|
2238
|
-
const maskTargetFillRect = createRect(rectangle);
|
|
2239
|
-
maskTargetFillRect.setAttribute('opacity', '0');
|
|
2240
|
-
maskTargetFillRect.setAttribute('fill', 'none');
|
|
2241
|
-
return { mask, maskTargetFillRect };
|
|
2242
|
-
}
|
|
2243
2247
|
|
|
2244
2248
|
const createUMLClassOrInterfaceGeometryElement = (board, shape, points) => {
|
|
2245
2249
|
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
@@ -2301,8 +2305,9 @@ const buildTableCellsForGeometry = (board, rows, columns, shape) => {
|
|
|
2301
2305
|
const memorizedLatest = getMemorizedLatestByPointer(shape);
|
|
2302
2306
|
const cellCount = rows.length * columns.length;
|
|
2303
2307
|
const defaultTexts = getDefaultGeometryProperty(shape)?.texts || [];
|
|
2304
|
-
const
|
|
2305
|
-
return getTextShapeProperty(board, textItem.text ||
|
|
2308
|
+
const textHeights = defaultTexts.map((textItem) => {
|
|
2309
|
+
return getTextShapeProperty(board, textItem.text || getDefaultGeometryText(board), memorizedLatest.textProperties['font-size'])
|
|
2310
|
+
.height;
|
|
2306
2311
|
});
|
|
2307
2312
|
return new Array(cellCount).fill('').map((item, index) => {
|
|
2308
2313
|
const rowIndex = Math.floor(index / columns.length);
|
|
@@ -2311,7 +2316,7 @@ const buildTableCellsForGeometry = (board, rows, columns, shape) => {
|
|
|
2311
2316
|
id: idCreator(),
|
|
2312
2317
|
rowId: rows[rowIndex].id,
|
|
2313
2318
|
columnId: columns[columnIndex].id,
|
|
2314
|
-
textHeight:
|
|
2319
|
+
textHeight: textHeights[index],
|
|
2315
2320
|
text: {
|
|
2316
2321
|
children: [
|
|
2317
2322
|
{
|
|
@@ -2394,61 +2399,6 @@ const getDefaultBasicShapeProperty = (shape) => {
|
|
|
2394
2399
|
const getDefaultUMLProperty = (shape) => {
|
|
2395
2400
|
return DefaultUMLPropertyMap[shape];
|
|
2396
2401
|
};
|
|
2397
|
-
const createDefaultFlowchart = (point) => {
|
|
2398
|
-
const decisionProperty = getDefaultFlowchartProperty(FlowchartSymbols.decision);
|
|
2399
|
-
const processProperty = getDefaultFlowchartProperty(FlowchartSymbols.process);
|
|
2400
|
-
const terminalProperty = getDefaultFlowchartProperty(FlowchartSymbols.terminal);
|
|
2401
|
-
const options = {
|
|
2402
|
-
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
2403
|
-
};
|
|
2404
|
-
const lineOptions = {
|
|
2405
|
-
strokeWidth: DefaultLineStyle.strokeWidth
|
|
2406
|
-
};
|
|
2407
|
-
const startElement = createGeometryElement(FlowchartSymbols.terminal, getDefaultGeometryPoints(FlowchartSymbols.terminal, point), '开始', options);
|
|
2408
|
-
const processPoint1 = [point[0], point[1] + terminalProperty.height / 2 + 55 + processProperty.height / 2];
|
|
2409
|
-
const processElement1 = createGeometryElement(FlowchartSymbols.process, getDefaultGeometryPoints(FlowchartSymbols.process, processPoint1), '过程', options);
|
|
2410
|
-
const decisionPoint = [processPoint1[0], processPoint1[1] + processProperty.height / 2 + 55 + decisionProperty.height / 2];
|
|
2411
|
-
const decisionElement = createGeometryElement(FlowchartSymbols.decision, getDefaultGeometryPoints(FlowchartSymbols.decision, decisionPoint), '判断', options);
|
|
2412
|
-
const processPoint2 = [decisionPoint[0] + decisionProperty.width / 2 + 75 + processProperty.width / 2, decisionPoint[1]];
|
|
2413
|
-
const processElement2 = createGeometryElement(FlowchartSymbols.process, getDefaultGeometryPoints(FlowchartSymbols.process, processPoint2), '过程', options);
|
|
2414
|
-
const endPoint = [decisionPoint[0], decisionPoint[1] + decisionProperty.height / 2 + 95 + terminalProperty.height / 2];
|
|
2415
|
-
const endElement = createGeometryElement(FlowchartSymbols.terminal, getDefaultGeometryPoints(FlowchartSymbols.terminal, endPoint), '结束', options);
|
|
2416
|
-
const line1 = createArrowLineElement(ArrowLineShape.elbow, [
|
|
2417
|
-
[0, 0],
|
|
2418
|
-
[0, 0]
|
|
2419
|
-
], { marker: ArrowLineMarkerType.none, connection: [0.5, 1], boundId: startElement.id }, { marker: ArrowLineMarkerType.arrow, connection: [0.5, 0], boundId: processElement1.id }, [], lineOptions);
|
|
2420
|
-
const line2 = createArrowLineElement(ArrowLineShape.elbow, [
|
|
2421
|
-
[0, 0],
|
|
2422
|
-
[0, 0]
|
|
2423
|
-
], { marker: ArrowLineMarkerType.none, connection: [0.5, 1], boundId: processElement1.id }, { marker: ArrowLineMarkerType.arrow, connection: [0.5, 0], boundId: decisionElement.id }, [], lineOptions);
|
|
2424
|
-
const line3 = createArrowLineElement(ArrowLineShape.elbow, [
|
|
2425
|
-
[0, 0],
|
|
2426
|
-
[0, 0]
|
|
2427
|
-
], { marker: ArrowLineMarkerType.none, connection: [0.5, 1], boundId: decisionElement.id }, { marker: ArrowLineMarkerType.arrow, connection: [0.5, 0], boundId: endElement.id }, [
|
|
2428
|
-
{
|
|
2429
|
-
text: buildText('是'),
|
|
2430
|
-
position: 0.5,
|
|
2431
|
-
width: 14,
|
|
2432
|
-
height: 20
|
|
2433
|
-
}
|
|
2434
|
-
], lineOptions);
|
|
2435
|
-
const line4 = createArrowLineElement(ArrowLineShape.elbow, [
|
|
2436
|
-
[0, 0],
|
|
2437
|
-
[0, 0]
|
|
2438
|
-
], { marker: ArrowLineMarkerType.none, connection: [1, 0.5], boundId: decisionElement.id }, { marker: ArrowLineMarkerType.arrow, connection: [0, 0.5], boundId: processElement2.id }, [
|
|
2439
|
-
{
|
|
2440
|
-
text: buildText('否'),
|
|
2441
|
-
position: 0.5,
|
|
2442
|
-
width: 14,
|
|
2443
|
-
height: 20
|
|
2444
|
-
}
|
|
2445
|
-
], lineOptions);
|
|
2446
|
-
const line5 = createArrowLineElement(ArrowLineShape.elbow, [
|
|
2447
|
-
[0, 0],
|
|
2448
|
-
[0, 0]
|
|
2449
|
-
], { marker: ArrowLineMarkerType.none, connection: [0.5, 1], boundId: processElement2.id }, { marker: ArrowLineMarkerType.arrow, connection: [1, 0.5], boundId: endElement.id }, [], lineOptions);
|
|
2450
|
-
return [startElement, processElement1, decisionElement, processElement2, endElement, line1, line2, line3, line4, line5];
|
|
2451
|
-
};
|
|
2452
2402
|
const getAutoCompletePoints = (board, element, isToActive = false) => {
|
|
2453
2403
|
const AutoCompleteMargin = (12 + RESIZE_HANDLE_DIAMETER / 2) * 2;
|
|
2454
2404
|
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
@@ -2470,7 +2420,7 @@ const getDrawDefaultStrokeColor = (theme) => {
|
|
|
2470
2420
|
const getFlowchartDefaultFill = (theme) => {
|
|
2471
2421
|
return DrawThemeColors[theme].fill;
|
|
2472
2422
|
};
|
|
2473
|
-
const getTextShapeProperty = (board, text
|
|
2423
|
+
const getTextShapeProperty = (board, text, fontSize) => {
|
|
2474
2424
|
fontSize = fontSize ? Number(fontSize) : DEFAULT_FONT_SIZE;
|
|
2475
2425
|
const textSize = measureElement(buildText(text), { fontSize, fontFamily: DEFAULT_FONT_FAMILY });
|
|
2476
2426
|
return {
|
|
@@ -2499,7 +2449,7 @@ const getDefaultTextPoints = (board, centerPoint, fontSize) => {
|
|
|
2499
2449
|
const property = getTextShapeProperty(board, DefaultTextProperty.text, fontSize);
|
|
2500
2450
|
return RectangleClient.getPoints(RectangleClient.getRectangleByCenterPoint(centerPoint, property.width, property.height));
|
|
2501
2451
|
};
|
|
2502
|
-
const createTextElement = (board, points, text
|
|
2452
|
+
const createTextElement = (board, points, text, textHeight) => {
|
|
2503
2453
|
const memorizedLatest = getMemorizedLatestByPointer(BasicShapes.text);
|
|
2504
2454
|
textHeight = textHeight ? textHeight : RectangleClient.getRectangleByPoints(points).height;
|
|
2505
2455
|
return createGeometryElement(BasicShapes.text, points, text, memorizedLatest.geometryProperties, {
|
|
@@ -3480,23 +3430,9 @@ function withDrawResize(board) {
|
|
|
3480
3430
|
handleG.remove();
|
|
3481
3431
|
handleG = null;
|
|
3482
3432
|
}
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
const boundingRectangle = needCustomActiveRectangle
|
|
3487
|
-
? RectangleClient.getRectangleByPoints(resizeActivePoints)
|
|
3488
|
-
: getRectangleByElements(board, elements, false);
|
|
3489
|
-
const boundingActiveRectangle = toActiveRectangleFromViewBoxRectangle(board, boundingRectangle);
|
|
3490
|
-
let corners = RectangleClient.getCornerPoints(boundingActiveRectangle);
|
|
3491
|
-
const angle = getSelectionAngle(elements);
|
|
3492
|
-
if (angle) {
|
|
3493
|
-
const centerPoint = RectangleClient.getCenterPoint(boundingActiveRectangle);
|
|
3494
|
-
corners = rotatePoints(corners, centerPoint, angle);
|
|
3495
|
-
}
|
|
3496
|
-
corners.forEach((corner) => {
|
|
3497
|
-
const g = drawHandle(board, corner);
|
|
3498
|
-
handleG && handleG.append(g);
|
|
3499
|
-
});
|
|
3433
|
+
const selectedElements = getSelectedElements(board);
|
|
3434
|
+
if (canResize() && !isSelectionMoving(board) && selectedElements.length > 1) {
|
|
3435
|
+
handleG = generatorResizeHandles(board, resizeActivePoints, needCustomActiveRectangle);
|
|
3500
3436
|
PlaitBoard.getActiveHost(board).append(handleG);
|
|
3501
3437
|
}
|
|
3502
3438
|
};
|
|
@@ -3582,6 +3518,25 @@ const getResizePointsByOtherwiseAxis = (board, points, resizeOriginPoint, xZoom,
|
|
|
3582
3518
|
const newRectangle = RectangleClient.getRectangleByPoints(resultPoints);
|
|
3583
3519
|
return rotatePoints(resultPoints, RectangleClient.getCenterPoint(newRectangle), -(1 / 2) * Math.PI);
|
|
3584
3520
|
};
|
|
3521
|
+
const generatorResizeHandles = (board, resizeActivePoints, needCustomActiveRectangle) => {
|
|
3522
|
+
const handleG = createG();
|
|
3523
|
+
const elements = getSelectedElements(board);
|
|
3524
|
+
const boundingRectangle = needCustomActiveRectangle
|
|
3525
|
+
? RectangleClient.getRectangleByPoints(resizeActivePoints)
|
|
3526
|
+
: getRectangleByElements(board, elements, false);
|
|
3527
|
+
const boundingActiveRectangle = toActiveRectangleFromViewBoxRectangle(board, boundingRectangle);
|
|
3528
|
+
let corners = RectangleClient.getCornerPoints(boundingActiveRectangle);
|
|
3529
|
+
const angle = getSelectionAngle(elements);
|
|
3530
|
+
if (angle) {
|
|
3531
|
+
const centerPoint = RectangleClient.getCenterPoint(boundingActiveRectangle);
|
|
3532
|
+
corners = rotatePoints(corners, centerPoint, angle);
|
|
3533
|
+
}
|
|
3534
|
+
corners.forEach((corner) => {
|
|
3535
|
+
const g = drawHandle(board, corner);
|
|
3536
|
+
handleG.append(g);
|
|
3537
|
+
});
|
|
3538
|
+
return handleG;
|
|
3539
|
+
};
|
|
3585
3540
|
|
|
3586
3541
|
const debugKey$1 = 'debug:plait:point-for-geometry';
|
|
3587
3542
|
const debugGenerator$1 = createDebugGenerator(debugKey$1);
|
|
@@ -7214,8 +7169,7 @@ class GeometryComponent extends CommonElementFlavour {
|
|
|
7214
7169
|
}
|
|
7215
7170
|
else {
|
|
7216
7171
|
const hasSameSelected = value.selected === previous.selected;
|
|
7217
|
-
|
|
7218
|
-
if (!hasSameSelected || !hasSameHandleState || value.selected) {
|
|
7172
|
+
if (!hasSameSelected || value.selected) {
|
|
7219
7173
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getActiveHost(this.board), {
|
|
7220
7174
|
selected: this.selected
|
|
7221
7175
|
});
|
|
@@ -7706,9 +7660,9 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
7706
7660
|
if (dragMode) {
|
|
7707
7661
|
const memorizedLatest = getMemorizedLatestByPointer(pointer);
|
|
7708
7662
|
if (pointer === BasicShapes.text) {
|
|
7709
|
-
const property = getTextShapeProperty(board,
|
|
7663
|
+
const property = getTextShapeProperty(board, getDefaultGeometryText(board), memorizedLatest.textProperties['font-size']);
|
|
7710
7664
|
const points = RectangleClient.getPoints(RectangleClient.getRectangleByCenterPoint(movingPoint, property.width, property.height));
|
|
7711
|
-
temporaryElement = createTextElement(board, points);
|
|
7665
|
+
temporaryElement = createTextElement(board, points, getDefaultGeometryText(board));
|
|
7712
7666
|
if (!fakeCreateTextRef) {
|
|
7713
7667
|
const textManage = new TextManage(board, {
|
|
7714
7668
|
getRectangle: () => {
|
|
@@ -7779,9 +7733,9 @@ const withGeometryCreateByDrawing = (board) => {
|
|
|
7779
7733
|
const pointer = PlaitBoard.getPointer(board);
|
|
7780
7734
|
if (pointer === BasicShapes.text) {
|
|
7781
7735
|
const memorizedLatest = getMemorizedLatestByPointer(pointer);
|
|
7782
|
-
const property = getTextShapeProperty(board,
|
|
7736
|
+
const property = getTextShapeProperty(board, getDefaultGeometryText(board), memorizedLatest.textProperties['font-size']);
|
|
7783
7737
|
const points = RectangleClient.getPoints(RectangleClient.getRectangleByCenterPoint(point, property.width, property.height));
|
|
7784
|
-
const textElement = createTextElement(board, points);
|
|
7738
|
+
const textElement = createTextElement(board, points, getDefaultGeometryText(board));
|
|
7785
7739
|
insertElement(board, textElement);
|
|
7786
7740
|
start = null;
|
|
7787
7741
|
}
|
|
@@ -8173,6 +8127,9 @@ const withArrowLineBoundReaction = (board) => {
|
|
|
8173
8127
|
return board;
|
|
8174
8128
|
};
|
|
8175
8129
|
|
|
8130
|
+
const getDefaultLineText = (board) => {
|
|
8131
|
+
return getI18nValue(board, DrawI18nKey.lineText, LINE_TEXT);
|
|
8132
|
+
};
|
|
8176
8133
|
const withArrowLineText = (board) => {
|
|
8177
8134
|
const { dblClick } = board;
|
|
8178
8135
|
board.dblClick = (event) => {
|
|
@@ -8190,13 +8147,19 @@ const withArrowLineText = (board) => {
|
|
|
8190
8147
|
editHandle(board, hitTarget, textIndex);
|
|
8191
8148
|
}
|
|
8192
8149
|
else {
|
|
8193
|
-
const
|
|
8150
|
+
const defaultLineText = getDefaultLineText(board);
|
|
8194
8151
|
const textMemory = getMemorizedLatest('arrow-line')?.text || {};
|
|
8152
|
+
const textElement = buildText(defaultLineText, undefined, textMemory);
|
|
8153
|
+
const { width, height } = measureElement(textElement, {
|
|
8154
|
+
fontSize: DEFAULT_FONT_SIZE,
|
|
8155
|
+
fontFamily: DEFAULT_FONT_FAMILY
|
|
8156
|
+
});
|
|
8157
|
+
const ratio = getRatioByPoint(points, point);
|
|
8195
8158
|
texts.push({
|
|
8196
|
-
text:
|
|
8159
|
+
text: textElement,
|
|
8197
8160
|
position: ratio,
|
|
8198
|
-
width
|
|
8199
|
-
height
|
|
8161
|
+
width,
|
|
8162
|
+
height
|
|
8200
8163
|
});
|
|
8201
8164
|
DrawTransforms.setArrowLineTexts(board, hitTarget, texts);
|
|
8202
8165
|
setTimeout(() => {
|
|
@@ -8218,7 +8181,8 @@ function editHandle(board, element, manageIndex, isFirstEdit = false) {
|
|
|
8218
8181
|
const textManage = textManages[manageIndex];
|
|
8219
8182
|
textManage.edit(() => {
|
|
8220
8183
|
const text = Node.string(textManage.getText());
|
|
8221
|
-
const
|
|
8184
|
+
const defaultLineText = getDefaultLineText(board);
|
|
8185
|
+
const shouldRemove = !text || (isFirstEdit && text === defaultLineText);
|
|
8222
8186
|
if (shouldRemove) {
|
|
8223
8187
|
DrawTransforms.removeArrowLineText(board, element, manageIndex);
|
|
8224
8188
|
}
|
|
@@ -8274,9 +8238,7 @@ class ImageComponent extends CommonElementFlavour {
|
|
|
8274
8238
|
}
|
|
8275
8239
|
else {
|
|
8276
8240
|
const hasSameSelected = value.selected === previous.selected;
|
|
8277
|
-
|
|
8278
|
-
this.imageGenerator.activeGenerator.options.hasResizeHandle() === this.imageGenerator.activeGenerator.hasResizeHandle;
|
|
8279
|
-
if (!hasSameSelected || !hasSameHandleState || value.selected) {
|
|
8241
|
+
if (!hasSameSelected || value.selected) {
|
|
8280
8242
|
this.imageGenerator.setFocus(this.element, this.selected);
|
|
8281
8243
|
this.lineAutoCompleteGenerator.processDrawing(this.element, PlaitBoard.getActiveHost(this.board), {
|
|
8282
8244
|
selected: this.selected
|
|
@@ -8698,9 +8660,8 @@ class TableComponent extends CommonElementFlavour {
|
|
|
8698
8660
|
}
|
|
8699
8661
|
else {
|
|
8700
8662
|
const hasSameSelected = value.selected === previous.selected;
|
|
8701
|
-
const hasSameHandleState = this.activeGenerator.options.hasResizeHandle() === this.activeGenerator.hasResizeHandle;
|
|
8702
8663
|
const currentSelectedCells = getSelectedCells(value.element);
|
|
8703
|
-
if (!hasSameSelected ||
|
|
8664
|
+
if (!hasSameSelected || currentSelectedCells?.length || value.selected) {
|
|
8704
8665
|
this.activeGenerator.processDrawing(value.element, PlaitBoard.getActiveHost(this.board), {
|
|
8705
8666
|
selected: this.selected
|
|
8706
8667
|
});
|
|
@@ -8728,17 +8689,21 @@ function withTableResize(board) {
|
|
|
8728
8689
|
const options = {
|
|
8729
8690
|
key: 'draw-table',
|
|
8730
8691
|
canResize: () => {
|
|
8731
|
-
|
|
8692
|
+
const selectedElements = getSelectedElements(board);
|
|
8693
|
+
return isSingleSelectTable(board) && !hasValidAngle(selectedElements[0]);
|
|
8732
8694
|
},
|
|
8733
8695
|
hitTest: (point) => {
|
|
8734
|
-
const
|
|
8696
|
+
const selectedElements = getSelectedElements(board);
|
|
8697
|
+
const hitElement = selectedElements[0];
|
|
8698
|
+
// debugGenerator.clear();
|
|
8735
8699
|
if (hitElement && PlaitDrawElement.isElementByTable(hitElement)) {
|
|
8736
8700
|
let rectangle = board.getRectangle(hitElement);
|
|
8701
|
+
// debugGenerator.drawRectangle(board, rectangle);
|
|
8702
|
+
// debugGenerator.drawCircles(board, [point], 5);
|
|
8737
8703
|
let handleRef = getHitRectangleResizeHandleRef(board, rectangle, point, hitElement.angle);
|
|
8738
8704
|
if (handleRef) {
|
|
8739
8705
|
const selectElement = isSelectedElement(board, hitElement);
|
|
8740
|
-
if ((selectElement &&
|
|
8741
|
-
(!selectElement && !isCornerHandle(board, handleRef.handle))) {
|
|
8706
|
+
if ((selectElement && isSingleSelectTable(board)) || (!selectElement && !isCornerHandle(board, handleRef.handle))) {
|
|
8742
8707
|
return {
|
|
8743
8708
|
element: hitElement,
|
|
8744
8709
|
handle: handleRef.handle,
|
|
@@ -8857,7 +8822,9 @@ const withTable = (board) => {
|
|
|
8857
8822
|
tableBoard.isHit = (element, point, isStrict) => {
|
|
8858
8823
|
if (PlaitDrawElement.isElementByTable(element)) {
|
|
8859
8824
|
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
8860
|
-
|
|
8825
|
+
const nearestPoint = TableEngine.getNearestPoint(client, point);
|
|
8826
|
+
const distance = distanceBetweenPointAndPoint(nearestPoint[0], nearestPoint[1], point[0], point[1]);
|
|
8827
|
+
return distance <= HIT_DISTANCE_BUFFER || RectangleClient.isPointInRectangle(client, point);
|
|
8861
8828
|
}
|
|
8862
8829
|
return isHit(element, point, isStrict);
|
|
8863
8830
|
};
|
|
@@ -8894,9 +8861,9 @@ const withTable = (board) => {
|
|
|
8894
8861
|
event.preventDefault();
|
|
8895
8862
|
if (PlaitDrawElement.isElementByTable(targetElement)) {
|
|
8896
8863
|
const cells = getSelectedCells(targetElement);
|
|
8897
|
-
let cell = targetElement.cells.find(item => item.text && item.textHeight);
|
|
8864
|
+
let cell = targetElement.cells.find((item) => item.text && item.textHeight);
|
|
8898
8865
|
if (cells?.length) {
|
|
8899
|
-
cell = cells.find(item => item.text && item.textHeight);
|
|
8866
|
+
cell = cells.find((item) => item.text && item.textHeight);
|
|
8900
8867
|
}
|
|
8901
8868
|
if (cell) {
|
|
8902
8869
|
editCell(board, cell);
|
|
@@ -9338,5 +9305,5 @@ const withDraw = (board) => {
|
|
|
9338
9305
|
* Generated bundle index. Do not edit.
|
|
9339
9306
|
*/
|
|
9340
9307
|
|
|
9341
|
-
export { ArrowLineAutoCompleteGenerator, ArrowLineComponent, ArrowLineHandleKey, ArrowLineMarkerType, ArrowLineShape, BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultActivationProperty, DefaultActorProperty, DefaultArrowProperty, DefaultAssemblyProperty, DefaultBasicShapeProperty, DefaultBasicShapePropertyMap, DefaultClassProperty, DefaultCloudProperty, DefaultCombinedFragmentProperty, DefaultComponentBoxProperty, DefaultConnectorProperty, DefaultContainerProperty, DefaultDataBaseProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultDeletionProperty, DefaultDocumentProperty, DefaultDrawActiveStyle, DefaultDrawStyle, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultInterfaceProperty, DefaultInternalStorageProperty, DefaultManualInputProperty, DefaultMergeProperty, DefaultMultiDocumentProperty, DefaultNoteProperty, DefaultObjectProperty, DefaultPackageProperty, DefaultPentagonArrowProperty, DefaultPortProperty, DefaultProvidedInterfaceProperty, DefaultRequiredInterfaceProperty, DefaultSwimlaneHorizontalProperty, DefaultSwimlaneHorizontalWithHeaderProperty, DefaultSwimlanePropertyMap, DefaultSwimlaneVerticalProperty, DefaultSwimlaneVerticalWithHeaderProperty, DefaultTextProperty, DefaultTwoWayArrowProperty, DefaultUMLPropertyMap, DrawThemeColors, DrawTransforms, FlowchartSymbols, GEOMETRY_NOT_CLOSED, GEOMETRY_WITHOUT_TEXT, GEOMETRY_WITH_MULTIPLE_TEXT, GeometryCommonTextKeys, GeometryComponent, GeometryShapeGenerator, GeometryThreshold, KEY_TO_TEXT_MANAGE, LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER, LINE_SNAPPING_CONNECTOR_BUFFER, LineActiveGenerator, MIN_TEXT_WIDTH, MemorizeKey, MultipleTextGeometryTextKeys, PlaitArrowLine, PlaitDrawElement, PlaitGeometry, PlaitTableElement, Q2C, SELECTED_CELLS, SWIMLANE_HEADER_SIZE, ShapeDefaultSpace, SingleTextGenerator, SwimlaneDrawSymbols, SwimlaneSymbols, TableGenerator, TableSymbols, TextGenerator, UMLSymbols, VectorLineComponent, VectorLinePointerType, VectorLineShape, WithArrowLineAutoCompletePluginKey, WithDrawPluginKey, adjustSwimlaneShape, alignElbowSegment, alignPoints, buildClipboardData, buildDefaultTextsByShape, buildSwimlaneTable, clearSelectedCells, collectArrowLineUpdatedRefsByGeometry, createArrowLineElement, createCell, createDefaultCells,
|
|
9308
|
+
export { ArrowLineAutoCompleteGenerator, ArrowLineComponent, ArrowLineHandleKey, ArrowLineMarkerType, ArrowLineShape, BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultActivationProperty, DefaultActorProperty, DefaultArrowProperty, DefaultAssemblyProperty, DefaultBasicShapeProperty, DefaultBasicShapePropertyMap, DefaultClassProperty, DefaultCloudProperty, DefaultCombinedFragmentProperty, DefaultComponentBoxProperty, DefaultConnectorProperty, DefaultContainerProperty, DefaultDataBaseProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultDeletionProperty, DefaultDocumentProperty, DefaultDrawActiveStyle, DefaultDrawStyle, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultInterfaceProperty, DefaultInternalStorageProperty, DefaultLineStyle, DefaultManualInputProperty, DefaultMergeProperty, DefaultMultiDocumentProperty, DefaultNoteProperty, DefaultObjectProperty, DefaultPackageProperty, DefaultPentagonArrowProperty, DefaultPortProperty, DefaultProvidedInterfaceProperty, DefaultRequiredInterfaceProperty, DefaultSwimlaneHorizontalProperty, DefaultSwimlaneHorizontalWithHeaderProperty, DefaultSwimlanePropertyMap, DefaultSwimlaneVerticalProperty, DefaultSwimlaneVerticalWithHeaderProperty, DefaultTextProperty, DefaultTwoWayArrowProperty, DefaultUMLPropertyMap, DrawI18nKey, DrawThemeColors, DrawTransforms, FlowchartSymbols, GEOMETRY_NOT_CLOSED, GEOMETRY_WITHOUT_TEXT, GEOMETRY_WITH_MULTIPLE_TEXT, GeometryCommonTextKeys, GeometryComponent, GeometryShapeGenerator, GeometryThreshold, KEY_TO_TEXT_MANAGE, LINE_ALIGN_TOLERANCE, LINE_AUTO_COMPLETE_DIAMETER, LINE_AUTO_COMPLETE_HOVERED_DIAMETER, LINE_AUTO_COMPLETE_HOVERED_OPACITY, LINE_AUTO_COMPLETE_OPACITY, LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER, LINE_SNAPPING_CONNECTOR_BUFFER, LINE_TEXT, LINE_TEXT_SPACE, LineActiveGenerator, MIN_TEXT_WIDTH, MemorizeKey, MultipleTextGeometryTextKeys, PlaitArrowLine, PlaitDrawElement, PlaitGeometry, PlaitTableElement, Q2C, SELECTED_CELLS, SWIMLANE_HEADER_SIZE, ShapeDefaultSpace, SingleTextGenerator, SwimlaneDrawSymbols, SwimlaneSymbols, TableGenerator, TableSymbols, TextGenerator, UMLSymbols, VectorLineComponent, VectorLinePointerType, VectorLineShape, WithArrowLineAutoCompletePluginKey, WithDrawPluginKey, adjustSwimlaneShape, alignElbowSegment, alignPoints, buildClipboardData, buildDefaultTextsByShape, buildSwimlaneTable, clearSelectedCells, collectArrowLineUpdatedRefsByGeometry, createArrowLineElement, createCell, createDefaultCells, createDefaultGeometry, createDefaultRowsOrColumns, createDefaultSwimlane, createGeometryElement, createGeometryElementWithText, createGeometryElementWithoutText, createMultipleTextGeometryElement, createTextElement, createUMLClassOrInterfaceGeometryElement, createVectorLineElement, debugGenerator$1 as debugGenerator, deleteTextManage, drawArrowLine, drawArrowLineArrow, drawBoundReaction, drawGeometry, drawShape, drawVectorLine, editCell, editText, getArrowLineHandleRefPair, getArrowLinePointers, getArrowLinePoints, getArrowLineTextRectangle, getArrowLines, getAutoCompletePoints, getBasicPointers, getCellWithPoints, getCellsRectangle, getCellsWithPoints, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultBasicShapeProperty, getDefaultFlowchartProperty, getDefaultGeometryPoints, getDefaultGeometryProperty, getDefaultGeometryText, getDefaultSwimlanePoints, getDefaultTextPoints, getDefaultUMLProperty, getDrawDefaultStrokeColor, getElbowLineRouteOptions, getElbowPoints, getFillByElement, getFirstFilledDrawElement, getFirstTextOrLineElement, getFlowchartDefaultFill, getFlowchartPointers, getGeometryAlign, getGeometryPointers, getHitCell, getHitConnection, getHitConnectorPoint, getHitDrawElement, getHitIndexOfAutoCompletePoint, getHitMultipleGeometryText, getHitShape, getIndexAndDeleteCountByKeyPoint, getLineMemorizedLatest, getMemorizeKey, getMemorizedLatestByPointer, getMemorizedLatestShape, getMidKeyPoints, getMiddlePoints, getMirrorDataPoints, getMultipleTextGeometryTextKeys, getNearestPoint, getNextRenderPoints, getNextSourceAndTargetPoints, getResizedPreviousAndNextPoint, getSelectedArrowLineElements, getSelectedCells, getSelectedCustomGeometryElements, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedSwimlane, getSelectedTableCellsEditor, getSelectedTableElements, getSelectedVectorLineElements, getSnapResizingRef, getSnapResizingRefOptions, getSnappingRef, getSnappingShape, getSourceAndTargetRectangle, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getSwimlaneCount, getSwimlanePointers, getTextKey, getTextManage, getTextManageByCell, getTextRectangle, getTextShapeProperty, getUMLPointers, getVectorByConnection, getVectorLinePointers, getVectorLinePoints, handleArrowLineCreating, hasIllegalElbowPoint, insertClipboardData, insertElement, isCellIncludeText, isClosedCustomGeometry, isClosedDrawElement, isClosedPoints, isDrawElementIncludeText, isDrawElementsIncludeText, isEmptyTextElement, isFilledDrawElement, isGeometryClosed, isGeometryIncludeText, isHitArrowLine, isHitArrowLineText, isHitDrawElement, isHitEdgeOfShape, isHitElementInside, isHitElementText, isHitPolyLine, isHitVectorLine, isInsideOfShape, isMultipleTextGeometry, isMultipleTextShape, isRectangleHitDrawElement, isRectangleHitElementText, isRectangleHitRotatedElement, isRectangleHitRotatedPoints, isSelfLoop, isSingleSelectLine, isSingleSelectSwimlane, isSingleSelectTable, isSingleTextGeometry, isSingleTextShape, isSwimlanePointers, isSwimlaneWithHeader, isTextExceedingBounds, isUpdatedHandleIndex, isUseDefaultOrthogonalRoute, memorizeLatestShape, memorizeLatestText, setSelectedCells, setTextManage, traverseDrawShapes, updateCellIds, updateCellIdsByRowOrColumn, updateColumns, updateRowOrColumnIds, updateRows, vectorLineCreating, withArrowLineAutoComplete, withDraw };
|
|
9342
9309
|
//# sourceMappingURL=plait-draw.mjs.map
|