@plait/draw 0.53.0 → 0.55.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/geometry.d.ts +25 -1
- package/engines/basic-shapes/circle.d.ts +8 -0
- package/engines/basic-shapes/cloud.d.ts +2 -0
- package/engines/flowchart/off-page.d.ts +4 -0
- package/engines/flowchart/or.d.ts +2 -0
- package/engines/flowchart/predefined-process.d.ts +2 -0
- package/engines/flowchart/summing-junction.d.ts +2 -0
- package/esm2022/constants/geometry.mjs +15 -3
- package/esm2022/engines/basic-shapes/circle.mjs +51 -0
- package/esm2022/engines/basic-shapes/cloud.mjs +57 -0
- package/esm2022/engines/basic-shapes/ellipse.mjs +3 -41
- package/esm2022/engines/flowchart/off-page.mjs +32 -0
- package/esm2022/engines/flowchart/or.mjs +25 -0
- package/esm2022/engines/flowchart/predefined-process.mjs +47 -0
- package/esm2022/engines/flowchart/summing-junction.mjs +28 -0
- package/esm2022/engines/index.mjs +12 -2
- package/esm2022/generators/line-auto-complete.generator.mjs +1 -1
- package/esm2022/geometry.component.mjs +7 -8
- package/esm2022/image.component.mjs +6 -7
- package/esm2022/interfaces/element.mjs +2 -1
- package/esm2022/interfaces/geometry.mjs +6 -1
- package/esm2022/interfaces/index.mjs +2 -2
- package/esm2022/line.component.mjs +8 -9
- package/esm2022/plugins/with-draw-fragment.mjs +7 -7
- package/esm2022/plugins/with-draw-hotkey.mjs +1 -1
- package/esm2022/plugins/with-draw-resize.mjs +73 -26
- package/esm2022/plugins/with-draw-rotate.mjs +127 -0
- package/esm2022/plugins/with-draw.mjs +6 -5
- package/esm2022/plugins/with-geometry-create.mjs +21 -5
- package/esm2022/plugins/with-geometry-resize.mjs +17 -23
- package/esm2022/plugins/with-line-auto-complete-reaction.mjs +2 -2
- package/esm2022/plugins/with-line-auto-complete.mjs +15 -13
- package/esm2022/plugins/with-line-bound-reaction.mjs +19 -21
- package/esm2022/plugins/with-line-create.mjs +4 -4
- package/esm2022/plugins/with-line-resize.mjs +11 -12
- package/esm2022/transforms/line.mjs +4 -4
- package/esm2022/utils/geometry.mjs +35 -23
- package/esm2022/utils/hit.mjs +26 -26
- package/esm2022/utils/line/elbow.mjs +11 -6
- package/esm2022/utils/line/line-basic.mjs +25 -30
- package/esm2022/utils/line/line-common.mjs +3 -3
- package/esm2022/utils/line/line-resize.mjs +2 -2
- package/esm2022/utils/position/geometry.mjs +59 -21
- package/esm2022/utils/shape.mjs +2 -2
- package/esm2022/utils/snap-resizing.mjs +185 -0
- package/esm2022/utils/style/stroke.mjs +9 -2
- package/fesm2022/plait-draw.mjs +1393 -1121
- package/fesm2022/plait-draw.mjs.map +1 -1
- package/generators/line-auto-complete.generator.d.ts +3 -3
- package/geometry.component.d.ts +2 -3
- package/image.component.d.ts +2 -3
- package/interfaces/element.d.ts +2 -1
- package/interfaces/geometry.d.ts +7 -2
- package/interfaces/index.d.ts +2 -2
- package/line.component.d.ts +2 -3
- package/package.json +1 -1
- package/plugins/with-draw-fragment.d.ts +2 -2
- package/plugins/with-draw-resize.d.ts +9 -5
- package/plugins/with-draw-rotate.d.ts +2 -0
- package/utils/geometry.d.ts +7 -4
- package/utils/hit.d.ts +3 -1
- package/utils/line/elbow.d.ts +3 -0
- package/utils/line/line-basic.d.ts +4 -4
- package/utils/position/geometry.d.ts +16 -2
- package/utils/shape.d.ts +2 -2
- package/utils/snap-resizing.d.ts +25 -0
- package/esm2022/utils/resize-align-reaction.mjs +0 -316
- package/esm2022/utils/resize-align.mjs +0 -37
- package/utils/resize-align-reaction.d.ts +0 -42
- package/utils/resize-align.d.ts +0 -8
package/fesm2022/plait-draw.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ACTIVE_STROKE_WIDTH, ThemeColorMode, createDebugGenerator, Point, RectangleClient, getElementById, rotatePointsByElement, createG, arrowPoints, createPath, distanceBetweenPointAndPoint, drawLinearPath, rotate, rotatePoints, depthFirstRecursion,
|
|
2
|
-
import { removeDuplicatePoints, generateElbowLineRoute, simplifyOrthogonalPoints, isSourceAndTargetIntersect, getPoints, getPointByVectorComponent, getExtendPoint, getUnitVectorByPointAndPoint, Generator, getRectangleResizeHandleRefs,
|
|
1
|
+
import { ACTIVE_STROKE_WIDTH, ThemeColorMode, createDebugGenerator, Point, RectangleClient, getElementById, rotatePointsByElement, createG, arrowPoints, createPath, distanceBetweenPointAndPoint, drawLinearPath, rotate, distanceBetweenPointAndSegments, HIT_DISTANCE_BUFFER, isPolylineHitRectangle, rotateAntiPointsByElement, rotatePoints, depthFirstRecursion, PlaitBoard, getIsRecursionFunc, idCreator, catmullRomFitting, setStrokeLinecap, findElements, createMask, createRect, getSelectedElements, isPointInPolygon, getNearestPointBetweenPointAndSegments, isPointInEllipse, getEllipseTangentSlope, getVectorFromPointAndSlope, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, setPathStrokeLinecap, getCrossingPointsBetweenEllipseAndSegment, SNAPPING_STROKE_WIDTH, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType, Direction, hasValidAngle, Path, PlaitNode, toViewBoxPoint, toHostPoint, isSelectionMoving, RgbaToHEX, PlaitElement, getHitElementByPoint, getRectangleByElements, getSelectionAngle, rotatedDataPoints, isAxisChangedByAngle, getRectangleByAngle, getSnapRectangles, getTripleAxis, getMinPointDelta, SNAP_TOLERANCE, drawPointSnapLines, drawSolidLines, preventTouchMove, createClipboardContext, WritableClipboardType, addClipboardContext, setAngleForG, CursorClass, temporaryDisableSelection, PRESS_AND_MOVE_BUFFER, isMainPointer, throttleRAF, getAngleBetweenPoints, degreesToRadians, normalizeAngle, rotateElements, MERGING, ROTATE_HANDLE_CLASS_NAME, SELECTION_RECTANGLE_CLASS_NAME } from '@plait/core';
|
|
2
|
+
import { removeDuplicatePoints, generateElbowLineRoute, simplifyOrthogonalPoints, isSourceAndTargetIntersect, getPoints, DEFAULT_ROUTE_MARGIN, getPointByVectorComponent, getExtendPoint, getUnitVectorByPointAndPoint, Generator, RESIZE_HANDLE_DIAMETER, getPointOnPolyline, TRANSPARENT, getRectangleResizeHandleRefs, getRotatedResizeCursorClassByAngle, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, getMemorizedLatest, memorizeLatest, getCrossingPointsBetweenPointAndSegment, isPointOnSegment, getDirectionByVector, getOppositeDirection, getDirectionFactor, rotateVector, getDirectionByPointOfRectangle, rotateVectorAnti90, getSourceAndTargetOuterRectangle, getNextPoint, normalizeShapePoints, getFirstTextEditor, PRIMARY_COLOR, CommonPluginElement, ActiveGenerator, WithTextPluginKey, drawPrimaryHandle, drawFillPrimaryHandle, isVirtualKey, isDelete, isSpaceHotkey, isCornerHandle, getIndexByResizeHandle, resetPointsAfterResize, getFirstTextManage, withResize, drawHandle, getSymmetricHandleIndex, getResizeHandlePointByIndex, getDirectionFactorByDirectionComponent, isDndMode, isDrawingMode, getElementsText, acceptImageTypes, getElementOfFocusedImage, buildImage, isResizingByCondition, getRatioByPoint, ImageGenerator, ResizeHandle, addRotating, removeRotating, drawRotateHandle } from '@plait/common';
|
|
3
3
|
import { Alignment, buildText, DEFAULT_FONT_SIZE, getTextSize, AlignEditor, TextManage } from '@plait/text';
|
|
4
4
|
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
@@ -30,6 +30,7 @@ var BasicShapes;
|
|
|
30
30
|
BasicShapes["twoWayArrow"] = "twoWayArrow";
|
|
31
31
|
BasicShapes["comment"] = "comment";
|
|
32
32
|
BasicShapes["roundComment"] = "roundComment";
|
|
33
|
+
BasicShapes["cloud"] = "cloud";
|
|
33
34
|
})(BasicShapes || (BasicShapes = {}));
|
|
34
35
|
var FlowchartSymbols;
|
|
35
36
|
(function (FlowchartSymbols) {
|
|
@@ -44,6 +45,10 @@ var FlowchartSymbols;
|
|
|
44
45
|
FlowchartSymbols["merge"] = "merge";
|
|
45
46
|
FlowchartSymbols["delay"] = "delay";
|
|
46
47
|
FlowchartSymbols["storedData"] = "storedData";
|
|
48
|
+
FlowchartSymbols["or"] = "or";
|
|
49
|
+
FlowchartSymbols["summingJunction"] = "summingJunction";
|
|
50
|
+
FlowchartSymbols["predefinedProcess"] = "predefinedProcess";
|
|
51
|
+
FlowchartSymbols["offPage"] = "offPage";
|
|
47
52
|
})(FlowchartSymbols || (FlowchartSymbols = {}));
|
|
48
53
|
const PlaitGeometry = {};
|
|
49
54
|
|
|
@@ -66,6 +71,12 @@ const DefaultBasicShapeProperty = {
|
|
|
66
71
|
strokeColor: '#333',
|
|
67
72
|
strokeWidth: 2
|
|
68
73
|
};
|
|
74
|
+
const DefaultCloudShapeProperty = {
|
|
75
|
+
width: 120,
|
|
76
|
+
height: 100,
|
|
77
|
+
strokeColor: '#333',
|
|
78
|
+
strokeWidth: 2
|
|
79
|
+
};
|
|
69
80
|
const DefaultTextProperty = {
|
|
70
81
|
width: 36,
|
|
71
82
|
height: 20,
|
|
@@ -109,9 +120,15 @@ const DefaultFlowchartPropertyMap = {
|
|
|
109
120
|
[FlowchartSymbols.manualLoop]: DefaultFlowchartProperty,
|
|
110
121
|
[FlowchartSymbols.merge]: DefaultMergeProperty,
|
|
111
122
|
[FlowchartSymbols.delay]: DefaultFlowchartProperty,
|
|
112
|
-
[FlowchartSymbols.storedData]: DefaultFlowchartProperty
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
[FlowchartSymbols.storedData]: DefaultFlowchartProperty,
|
|
124
|
+
[FlowchartSymbols.or]: DefaultConnectorProperty,
|
|
125
|
+
[FlowchartSymbols.summingJunction]: DefaultConnectorProperty,
|
|
126
|
+
[FlowchartSymbols.predefinedProcess]: DefaultFlowchartProperty,
|
|
127
|
+
[FlowchartSymbols.offPage]: DefaultFlowchartProperty
|
|
128
|
+
};
|
|
129
|
+
const LINE_HIT_GEOMETRY_BUFFER = 10;
|
|
130
|
+
const LINE_SNAPPING_BUFFER = 6;
|
|
131
|
+
const LINE_SNAPPING_CONNECTOR_BUFFER = 8;
|
|
115
132
|
|
|
116
133
|
const getGeometryPointers = () => {
|
|
117
134
|
return [...Object.keys(BasicShapes), ...Object.keys(FlowchartSymbols)];
|
|
@@ -166,8 +183,8 @@ const LINE_AUTO_COMPLETE_HOVERED_OPACITY = 0.8;
|
|
|
166
183
|
const LINE_AUTO_COMPLETE_HOVERED_DIAMETER = 10;
|
|
167
184
|
const LINE_ALIGN_TOLERANCE = 3;
|
|
168
185
|
|
|
169
|
-
const debugKey$
|
|
170
|
-
const debugGenerator$
|
|
186
|
+
const debugKey$3 = 'debug:plait:line-mirror';
|
|
187
|
+
const debugGenerator$3 = createDebugGenerator(debugKey$3);
|
|
171
188
|
const alignPoints = (basePoint, movingPoint) => {
|
|
172
189
|
const newPoint = [...movingPoint];
|
|
173
190
|
if (Point.isVertical(newPoint, basePoint, LINE_ALIGN_TOLERANCE)) {
|
|
@@ -304,7 +321,7 @@ function getIndexAndDeleteCountByKeyPoint(board, element, dataPoints, nextRender
|
|
|
304
321
|
if (midDataPoints.length > 0) {
|
|
305
322
|
const handleRefPair = getLineHandleRefPair(board, element);
|
|
306
323
|
const params = getElbowLineRouteOptions(board, element, handleRefPair);
|
|
307
|
-
const keyPoints = removeDuplicatePoints(generateElbowLineRoute(params));
|
|
324
|
+
const keyPoints = removeDuplicatePoints(generateElbowLineRoute(params, board));
|
|
308
325
|
const nextKeyPoints = simplifyOrthogonalPoints(keyPoints.slice(1, keyPoints.length - 1));
|
|
309
326
|
const nextDataPoints = [nextRenderPoints[0], ...midDataPoints, nextRenderPoints[nextRenderPoints.length - 1]];
|
|
310
327
|
const mirrorDataPoints = getMirrorDataPoints(board, nextDataPoints, nextKeyPoints, params);
|
|
@@ -431,7 +448,7 @@ function findOrthogonalParallelSegments(segment, keyPoints) {
|
|
|
431
448
|
return parallelSegments;
|
|
432
449
|
}
|
|
433
450
|
function findMirrorSegments(board, segment, parallelSegments, sourceRectangle, targetRectangle) {
|
|
434
|
-
debugGenerator$
|
|
451
|
+
debugGenerator$3.isDebug() && debugGenerator$3.clear();
|
|
435
452
|
const mirrorSegments = [];
|
|
436
453
|
for (let index = 0; index < parallelSegments.length; index++) {
|
|
437
454
|
const parallelPath = parallelSegments[index];
|
|
@@ -445,7 +462,7 @@ function findMirrorSegments(board, segment, parallelSegments, sourceRectangle, t
|
|
|
445
462
|
const isValid = !RectangleClient.isHit(fakeRectangle, sourceRectangle) && !RectangleClient.isHit(fakeRectangle, targetRectangle);
|
|
446
463
|
if (isValid) {
|
|
447
464
|
mirrorSegments.push([startPoint, endPoint]);
|
|
448
|
-
debugGenerator$
|
|
465
|
+
debugGenerator$3.isDebug() && debugGenerator$3.drawPolygon(board, RectangleClient.getCornerPoints(fakeRectangle));
|
|
449
466
|
}
|
|
450
467
|
}
|
|
451
468
|
return mirrorSegments;
|
|
@@ -471,15 +488,20 @@ const hasIllegalElbowPoint = (midDataPoints) => {
|
|
|
471
488
|
});
|
|
472
489
|
};
|
|
473
490
|
|
|
491
|
+
const isSelfLoop = (element) => {
|
|
492
|
+
return element.source.boundId && element.source.boundId === element.target.boundId;
|
|
493
|
+
};
|
|
494
|
+
const isUseDefaultOrthogonalRoute = (element, options) => {
|
|
495
|
+
return isSourceAndTargetIntersect(options) && !isSelfLoop(element);
|
|
496
|
+
};
|
|
474
497
|
const getElbowPoints = (board, element) => {
|
|
475
498
|
const handleRefPair = getLineHandleRefPair(board, element);
|
|
476
499
|
const params = getElbowLineRouteOptions(board, element, handleRefPair);
|
|
477
500
|
// console.log(params, 'params');
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
return simplifyOrthogonalPoints(getPoints(handleRefPair.source.point, handleRefPair.source.direction, handleRefPair.target.point, handleRefPair.target.direction, 0));
|
|
501
|
+
if (isUseDefaultOrthogonalRoute(element, params)) {
|
|
502
|
+
return simplifyOrthogonalPoints(getPoints(handleRefPair.source.point, handleRefPair.source.direction, handleRefPair.target.point, handleRefPair.target.direction, DEFAULT_ROUTE_MARGIN));
|
|
481
503
|
}
|
|
482
|
-
const keyPoints = removeDuplicatePoints(generateElbowLineRoute(params));
|
|
504
|
+
const keyPoints = removeDuplicatePoints(generateElbowLineRoute(params, board));
|
|
483
505
|
const nextKeyPoints = keyPoints.slice(1, keyPoints.length - 1);
|
|
484
506
|
if (element.points.length === 2) {
|
|
485
507
|
return simplifyOrthogonalPoints(keyPoints);
|
|
@@ -692,7 +714,7 @@ const drawHollowTriangleArrow = (source, target, options) => {
|
|
|
692
714
|
return drawLinearPath([pointLeft, pointRight, target], { ...options, fill: 'white' }, true);
|
|
693
715
|
};
|
|
694
716
|
|
|
695
|
-
const
|
|
717
|
+
const getElementShape = (value) => {
|
|
696
718
|
if (PlaitDrawElement.isImage(value)) {
|
|
697
719
|
return BasicShapes.rectangle;
|
|
698
720
|
}
|
|
@@ -710,29 +732,246 @@ class LineShapeGenerator extends Generator {
|
|
|
710
732
|
}
|
|
711
733
|
}
|
|
712
734
|
|
|
735
|
+
var LineResizeHandle;
|
|
736
|
+
(function (LineResizeHandle) {
|
|
737
|
+
LineResizeHandle["source"] = "source";
|
|
738
|
+
LineResizeHandle["target"] = "target";
|
|
739
|
+
LineResizeHandle["addHandle"] = "addHandle";
|
|
740
|
+
})(LineResizeHandle || (LineResizeHandle = {}));
|
|
741
|
+
const getHitLineResizeHandleRef = (board, element, point) => {
|
|
742
|
+
let dataPoints = PlaitLine.getPoints(board, element);
|
|
743
|
+
const index = getHitPointIndex(dataPoints, point);
|
|
744
|
+
if (index !== -1) {
|
|
745
|
+
const handleIndex = index;
|
|
746
|
+
if (index === 0) {
|
|
747
|
+
return { handle: LineResizeHandle.source, handleIndex };
|
|
748
|
+
}
|
|
749
|
+
if (index === dataPoints.length - 1) {
|
|
750
|
+
return { handle: LineResizeHandle.target, handleIndex };
|
|
751
|
+
}
|
|
752
|
+
// elbow line, data points only verify source connection point and target connection point
|
|
753
|
+
if (element.shape !== LineShape.elbow) {
|
|
754
|
+
return { handleIndex };
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
const middlePoints = getMiddlePoints(board, element);
|
|
758
|
+
const indexOfMiddlePoints = getHitPointIndex(middlePoints, point);
|
|
759
|
+
if (indexOfMiddlePoints !== -1) {
|
|
760
|
+
return {
|
|
761
|
+
handle: LineResizeHandle.addHandle,
|
|
762
|
+
handleIndex: indexOfMiddlePoints
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
return undefined;
|
|
766
|
+
};
|
|
767
|
+
function getHitPointIndex(points, movingPoint) {
|
|
768
|
+
const rectangles = points.map(point => {
|
|
769
|
+
return {
|
|
770
|
+
x: point[0] - RESIZE_HANDLE_DIAMETER / 2,
|
|
771
|
+
y: point[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
772
|
+
width: RESIZE_HANDLE_DIAMETER,
|
|
773
|
+
height: RESIZE_HANDLE_DIAMETER
|
|
774
|
+
};
|
|
775
|
+
});
|
|
776
|
+
const rectangle = rectangles.find(rectangle => {
|
|
777
|
+
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([movingPoint, movingPoint]), rectangle);
|
|
778
|
+
});
|
|
779
|
+
return rectangle ? rectangles.indexOf(rectangle) : -1;
|
|
780
|
+
}
|
|
781
|
+
const getHitLineTextIndex = (board, element, point) => {
|
|
782
|
+
const texts = element.texts;
|
|
783
|
+
if (!texts.length)
|
|
784
|
+
return -1;
|
|
785
|
+
const points = getLinePoints(board, element);
|
|
786
|
+
return texts.findIndex(text => {
|
|
787
|
+
const center = getPointOnPolyline(points, text.position);
|
|
788
|
+
const rectangle = {
|
|
789
|
+
x: center[0] - text.width / 2,
|
|
790
|
+
y: center[1] - text.height / 2,
|
|
791
|
+
width: text.width,
|
|
792
|
+
height: text.height
|
|
793
|
+
};
|
|
794
|
+
return RectangleClient.isHit(rectangle, RectangleClient.getRectangleByPoints([point, point]));
|
|
795
|
+
});
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
const isTextExceedingBounds = (geometry) => {
|
|
799
|
+
const client = RectangleClient.getRectangleByPoints(geometry.points);
|
|
800
|
+
if (geometry.textHeight > client.height) {
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
return false;
|
|
804
|
+
};
|
|
805
|
+
const isHitLineText = (board, element, point) => {
|
|
806
|
+
return getHitLineTextIndex(board, element, point) !== -1;
|
|
807
|
+
};
|
|
808
|
+
const isHitPolyLine = (pathPoints, point) => {
|
|
809
|
+
const distance = distanceBetweenPointAndSegments(pathPoints, point);
|
|
810
|
+
return distance <= HIT_DISTANCE_BUFFER;
|
|
811
|
+
};
|
|
812
|
+
const isHitLine = (board, element, point) => {
|
|
813
|
+
const points = getLinePoints(board, element);
|
|
814
|
+
const isHitText = isHitLineText(board, element, point);
|
|
815
|
+
return isHitText || isHitPolyLine(points, point);
|
|
816
|
+
};
|
|
817
|
+
const isRectangleHitDrawElement = (board, element, selection) => {
|
|
818
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([selection.anchor, selection.focus]);
|
|
819
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
820
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
821
|
+
let rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(client), element) || RectangleClient.getCornerPoints(client);
|
|
822
|
+
if (isTextExceedingBounds(element)) {
|
|
823
|
+
const textClient = getTextRectangle(element);
|
|
824
|
+
rotatedCornerPoints =
|
|
825
|
+
rotatePointsByElement(RectangleClient.getCornerPoints(textClient), element) || RectangleClient.getCornerPoints(textClient);
|
|
826
|
+
}
|
|
827
|
+
return isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
828
|
+
}
|
|
829
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
830
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
831
|
+
const rotatedCornerPoints = rotatePointsByElement(RectangleClient.getCornerPoints(client), element) || RectangleClient.getCornerPoints(client);
|
|
832
|
+
return isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
833
|
+
}
|
|
834
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
835
|
+
const points = getLinePoints(board, element);
|
|
836
|
+
return isPolylineHitRectangle(points, rangeRectangle);
|
|
837
|
+
}
|
|
838
|
+
return null;
|
|
839
|
+
};
|
|
840
|
+
const isHitDrawElement = (board, element, point) => {
|
|
841
|
+
const rectangle = board.getRectangle(element);
|
|
842
|
+
point = rotateAntiPointsByElement(point, element) || point;
|
|
843
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
844
|
+
const fill = getFillByElement(board, element);
|
|
845
|
+
if (isHitEdgeOfShape(board, element, point, HIT_DISTANCE_BUFFER)) {
|
|
846
|
+
return true;
|
|
847
|
+
}
|
|
848
|
+
const engine = getEngine(getElementShape(element));
|
|
849
|
+
// when shape equals text, fill is not allowed
|
|
850
|
+
if (fill !== DefaultGeometryStyle.fill && fill !== TRANSPARENT && !PlaitDrawElement.isText(element)) {
|
|
851
|
+
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
852
|
+
if (isHitInside) {
|
|
853
|
+
return isHitInside;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
else {
|
|
857
|
+
// if shape equals text, only check text rectangle
|
|
858
|
+
if (PlaitDrawElement.isText(element)) {
|
|
859
|
+
const textClient = getTextRectangle(element);
|
|
860
|
+
let isHitText = RectangleClient.isPointInRectangle(textClient, point);
|
|
861
|
+
return isHitText;
|
|
862
|
+
}
|
|
863
|
+
// check textRectangle of element
|
|
864
|
+
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
865
|
+
const isHitTextRectangle = RectangleClient.isPointInRectangle(textClient, point);
|
|
866
|
+
if (isHitTextRectangle) {
|
|
867
|
+
return isHitTextRectangle;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
872
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
873
|
+
return RectangleClient.isPointInRectangle(client, point);
|
|
874
|
+
}
|
|
875
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
876
|
+
return isHitLine(board, element, point);
|
|
877
|
+
}
|
|
878
|
+
return null;
|
|
879
|
+
};
|
|
880
|
+
const isHitEdgeOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
881
|
+
const nearestPoint = getNearestPoint(element, point);
|
|
882
|
+
const distance = distanceBetweenPointAndPoint(nearestPoint[0], nearestPoint[1], point[0], point[1]);
|
|
883
|
+
return distance <= hitDistanceBuffer;
|
|
884
|
+
};
|
|
885
|
+
const isInsideOfShape = (board, element, point, hitDistanceBuffer) => {
|
|
886
|
+
const client = RectangleClient.inflate(RectangleClient.getRectangleByPoints(element.points), hitDistanceBuffer);
|
|
887
|
+
return getEngine(getElementShape(element)).isInsidePoint(client, point);
|
|
888
|
+
};
|
|
889
|
+
const isHitElementInside = (board, element, point) => {
|
|
890
|
+
const rectangle = board.getRectangle(element);
|
|
891
|
+
point = rotateAntiPointsByElement(point, element) || point;
|
|
892
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
893
|
+
const engine = getEngine(getElementShape(element));
|
|
894
|
+
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
895
|
+
if (isHitInside) {
|
|
896
|
+
return isHitInside;
|
|
897
|
+
}
|
|
898
|
+
if (engine.getTextRectangle) {
|
|
899
|
+
const textClient = engine.getTextRectangle(element);
|
|
900
|
+
const isHitTextRectangle = RectangleClient.isPointInRectangle(textClient, point);
|
|
901
|
+
if (isHitTextRectangle) {
|
|
902
|
+
return isHitTextRectangle;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
907
|
+
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
908
|
+
return RectangleClient.isPointInRectangle(client, point);
|
|
909
|
+
}
|
|
910
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
911
|
+
return isHitLine(board, element, point);
|
|
912
|
+
}
|
|
913
|
+
return null;
|
|
914
|
+
};
|
|
915
|
+
|
|
713
916
|
const getHitRectangleResizeHandleRef = (board, rectangle, point, angle = 0) => {
|
|
714
917
|
const centerPoint = RectangleClient.getCenterPoint(rectangle);
|
|
715
|
-
const
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
918
|
+
const resizeHandleRefs = getRectangleResizeHandleRefs(rectangle, RESIZE_HANDLE_DIAMETER);
|
|
919
|
+
if (angle) {
|
|
920
|
+
const rotatedPoint = rotatePoints([point], centerPoint, -angle)[0];
|
|
921
|
+
let result = resizeHandleRefs.find(resizeHandleRef => {
|
|
922
|
+
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([rotatedPoint, rotatedPoint]), resizeHandleRef.rectangle);
|
|
923
|
+
});
|
|
924
|
+
if (result) {
|
|
925
|
+
result.cursorClass = getRotatedResizeCursorClassByAngle(result.cursorClass, angle);
|
|
926
|
+
}
|
|
927
|
+
return result;
|
|
928
|
+
}
|
|
929
|
+
else {
|
|
930
|
+
return resizeHandleRefs.find(resizeHandleRef => {
|
|
931
|
+
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), resizeHandleRef.rectangle);
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
const getSnappingGeometry = (board, point) => {
|
|
936
|
+
let hitElement = getHitGeometry(board, point);
|
|
937
|
+
if (hitElement) {
|
|
938
|
+
const ref = getSnappingRef(board, hitElement, point);
|
|
939
|
+
if (ref.isHitConnector || ref.isHitEdge) {
|
|
940
|
+
return hitElement;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return null;
|
|
944
|
+
};
|
|
945
|
+
const getSnappingRef = (board, hitElement, point) => {
|
|
946
|
+
const rotatedPoint = rotateAntiPointsByElement(point, hitElement) || point;
|
|
947
|
+
const connectorPoint = getHitConnectorPoint(rotatedPoint, hitElement);
|
|
948
|
+
const edgePoint = getNearestPoint(hitElement, rotatedPoint);
|
|
949
|
+
const isHitEdge = isHitEdgeOfShape(board, hitElement, rotatedPoint, LINE_SNAPPING_BUFFER);
|
|
950
|
+
return { isHitEdge, isHitConnector: !!connectorPoint, connectorPoint, edgePoint };
|
|
951
|
+
};
|
|
952
|
+
const getHitGeometry = (board, point, offset = LINE_HIT_GEOMETRY_BUFFER) => {
|
|
953
|
+
let hitShape = null;
|
|
954
|
+
traverseDrawShapes(board, (element) => {
|
|
955
|
+
if (hitShape === null && isInsideOfShape(board, element, rotateAntiPointsByElement(point, element) || point, offset * 2)) {
|
|
956
|
+
hitShape = element;
|
|
957
|
+
}
|
|
719
958
|
});
|
|
720
|
-
return
|
|
959
|
+
return hitShape;
|
|
721
960
|
};
|
|
722
|
-
const
|
|
723
|
-
let geometry = null;
|
|
961
|
+
const traverseDrawShapes = (board, callback) => {
|
|
724
962
|
depthFirstRecursion(board, node => {
|
|
725
|
-
if (
|
|
726
|
-
|
|
727
|
-
client = RectangleClient.getOutlineRectangle(client, offset);
|
|
728
|
-
const shape = getShape(node);
|
|
729
|
-
const isHit = getEngine(shape).isInsidePoint(client, rotateAntiPointsByElement(point, node) || point);
|
|
730
|
-
if (isHit) {
|
|
731
|
-
geometry = node;
|
|
732
|
-
}
|
|
963
|
+
if (!PlaitBoard.isBoard(node) && PlaitDrawElement.isShapeElement(node)) {
|
|
964
|
+
callback(node);
|
|
733
965
|
}
|
|
734
966
|
}, getIsRecursionFunc(board), true);
|
|
735
|
-
|
|
967
|
+
};
|
|
968
|
+
const getRotateHandleRectangle = (rectangle) => {
|
|
969
|
+
return {
|
|
970
|
+
x: rectangle.x - ROTATE_HANDLE_DISTANCE_TO_ELEMENT - ROTATE_HANDLE_SIZE,
|
|
971
|
+
y: rectangle.y + rectangle.height + ROTATE_HANDLE_DISTANCE_TO_ELEMENT,
|
|
972
|
+
width: ROTATE_HANDLE_SIZE,
|
|
973
|
+
height: ROTATE_HANDLE_SIZE
|
|
974
|
+
};
|
|
736
975
|
};
|
|
737
976
|
|
|
738
977
|
const SHAPE_MAX_LENGTH = 6;
|
|
@@ -910,8 +1149,7 @@ function getMiddlePoints(board, element) {
|
|
|
910
1149
|
if (shape === LineShape.elbow) {
|
|
911
1150
|
const renderPoints = getElbowPoints(board, element);
|
|
912
1151
|
const options = getElbowLineRouteOptions(board, element);
|
|
913
|
-
|
|
914
|
-
if (!isIntersect) {
|
|
1152
|
+
if (!isUseDefaultOrthogonalRoute(element, options)) {
|
|
915
1153
|
const [nextSourcePoint, nextTargetPoint] = getNextSourceAndTargetPoints(board, element);
|
|
916
1154
|
for (let i = 0; i < renderPoints.length - 1; i++) {
|
|
917
1155
|
if ((i == 0 && Point.isEquals(renderPoints[i + 1], nextSourcePoint)) ||
|
|
@@ -943,6 +1181,9 @@ const drawLine = (board, element) => {
|
|
|
943
1181
|
}
|
|
944
1182
|
const id = idCreator();
|
|
945
1183
|
line.setAttribute('mask', `url(#${id})`);
|
|
1184
|
+
if (element.strokeStyle === StrokeStyle.dotted) {
|
|
1185
|
+
setStrokeLinecap(line, 'round');
|
|
1186
|
+
}
|
|
946
1187
|
lineG.appendChild(line);
|
|
947
1188
|
const { mask, maskTargetFillRect } = drawMask(board, element, id);
|
|
948
1189
|
lineG.appendChild(mask);
|
|
@@ -951,20 +1192,18 @@ const drawLine = (board, element) => {
|
|
|
951
1192
|
arrow && lineG.appendChild(arrow);
|
|
952
1193
|
return lineG;
|
|
953
1194
|
};
|
|
954
|
-
const
|
|
1195
|
+
const getHitConnection = (board, point, hitElement) => {
|
|
955
1196
|
let rectangle = RectangleClient.getRectangleByPoints(hitElement.points);
|
|
956
|
-
|
|
957
|
-
const
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
const
|
|
962
|
-
const shape =
|
|
963
|
-
const
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
return connector.find(point => {
|
|
967
|
-
return RectangleClient.isHit(pointRectangle, RectangleClient.getRectangleByPoints([point, point]));
|
|
1197
|
+
const ref = getSnappingRef(board, hitElement, point);
|
|
1198
|
+
const connectionPoint = ref.connectorPoint || ref.edgePoint;
|
|
1199
|
+
return [(connectionPoint[0] - rectangle.x) / rectangle.width, (connectionPoint[1] - rectangle.y) / rectangle.height];
|
|
1200
|
+
};
|
|
1201
|
+
const getHitConnectorPoint = (point, hitElement) => {
|
|
1202
|
+
const rectangle = RectangleClient.getRectangleByPoints(hitElement.points);
|
|
1203
|
+
const shape = getElementShape(hitElement);
|
|
1204
|
+
const connectorPoints = getEngine(shape).getConnectorPoints(rectangle);
|
|
1205
|
+
return connectorPoints.find(connectorPoint => {
|
|
1206
|
+
return distanceBetweenPointAndPoint(...connectorPoint, ...point) <= LINE_SNAPPING_CONNECTOR_BUFFER;
|
|
968
1207
|
});
|
|
969
1208
|
};
|
|
970
1209
|
const getLineTextRectangle = (board, element, index) => {
|
|
@@ -1001,13 +1240,9 @@ const Q2C = (points) => {
|
|
|
1001
1240
|
return result;
|
|
1002
1241
|
};
|
|
1003
1242
|
const handleLineCreating = (board, lineShape, sourcePoint, movingPoint, sourceElement, lineShapeG) => {
|
|
1004
|
-
const hitElement =
|
|
1005
|
-
const targetConnection = hitElement
|
|
1006
|
-
|
|
1007
|
-
: undefined;
|
|
1008
|
-
const sourceConnection = sourceElement
|
|
1009
|
-
? getConnectionByNearestPoint(board, rotateAntiPointsByElement(sourcePoint, sourceElement) || sourcePoint, sourceElement)
|
|
1010
|
-
: undefined;
|
|
1243
|
+
const hitElement = getSnappingGeometry(board, movingPoint);
|
|
1244
|
+
const targetConnection = hitElement ? getHitConnection(board, movingPoint, hitElement) : undefined;
|
|
1245
|
+
const sourceConnection = sourceElement ? getHitConnection(board, sourcePoint, sourceElement) : undefined;
|
|
1011
1246
|
const targetBoundId = hitElement ? hitElement.id : undefined;
|
|
1012
1247
|
const lineGenerator = new LineShapeGenerator(board);
|
|
1013
1248
|
const memorizedLatest = getLineMemorizedLatest();
|
|
@@ -1070,204 +1305,23 @@ const getSelectedImageElements = (board) => {
|
|
|
1070
1305
|
return selectedElements;
|
|
1071
1306
|
};
|
|
1072
1307
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
})(LineResizeHandle || (LineResizeHandle = {}));
|
|
1079
|
-
const getHitLineResizeHandleRef = (board, element, point) => {
|
|
1080
|
-
let dataPoints = PlaitLine.getPoints(board, element);
|
|
1081
|
-
const index = getHitPointIndex(dataPoints, point);
|
|
1082
|
-
if (index !== -1) {
|
|
1083
|
-
const handleIndex = index;
|
|
1084
|
-
if (index === 0) {
|
|
1085
|
-
return { handle: LineResizeHandle.source, handleIndex };
|
|
1086
|
-
}
|
|
1087
|
-
if (index === dataPoints.length - 1) {
|
|
1088
|
-
return { handle: LineResizeHandle.target, handleIndex };
|
|
1089
|
-
}
|
|
1090
|
-
// elbow line, data points only verify source connection point and target connection point
|
|
1091
|
-
if (element.shape !== LineShape.elbow) {
|
|
1092
|
-
return { handleIndex };
|
|
1093
|
-
}
|
|
1308
|
+
const getCenterPointsOnPolygon$1 = (points) => {
|
|
1309
|
+
const centerPoints = [];
|
|
1310
|
+
for (let i = 0; i < points.length; i++) {
|
|
1311
|
+
let j = i == points.length - 1 ? 0 : i + 1;
|
|
1312
|
+
centerPoints.push([(points[i][0] + points[j][0]) / 2, (points[i][1] + points[j][1]) / 2]);
|
|
1094
1313
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1314
|
+
return centerPoints;
|
|
1315
|
+
};
|
|
1316
|
+
const getCrossingPointBetweenPointAndPolygon = (corners, point) => {
|
|
1317
|
+
const result = [];
|
|
1318
|
+
for (let index = 1; index <= corners.length; index++) {
|
|
1319
|
+
let start = corners[index - 1];
|
|
1320
|
+
let end = index === corners.length ? corners[0] : corners[index];
|
|
1321
|
+
const crossingPoint = getCrossingPointsBetweenPointAndSegment(point, start, end);
|
|
1322
|
+
result.push(...crossingPoint);
|
|
1102
1323
|
}
|
|
1103
|
-
return
|
|
1104
|
-
};
|
|
1105
|
-
function getHitPointIndex(points, movingPoint) {
|
|
1106
|
-
const rectangles = points.map(point => {
|
|
1107
|
-
return {
|
|
1108
|
-
x: point[0] - RESIZE_HANDLE_DIAMETER / 2,
|
|
1109
|
-
y: point[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
1110
|
-
width: RESIZE_HANDLE_DIAMETER,
|
|
1111
|
-
height: RESIZE_HANDLE_DIAMETER
|
|
1112
|
-
};
|
|
1113
|
-
});
|
|
1114
|
-
const rectangle = rectangles.find(rectangle => {
|
|
1115
|
-
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([movingPoint, movingPoint]), rectangle);
|
|
1116
|
-
});
|
|
1117
|
-
return rectangle ? rectangles.indexOf(rectangle) : -1;
|
|
1118
|
-
}
|
|
1119
|
-
const getHitLineTextIndex = (board, element, point) => {
|
|
1120
|
-
const texts = element.texts;
|
|
1121
|
-
if (!texts.length)
|
|
1122
|
-
return -1;
|
|
1123
|
-
const points = getLinePoints(board, element);
|
|
1124
|
-
return texts.findIndex(text => {
|
|
1125
|
-
const center = getPointOnPolyline(points, text.position);
|
|
1126
|
-
const rectangle = {
|
|
1127
|
-
x: center[0] - text.width / 2,
|
|
1128
|
-
y: center[1] - text.height / 2,
|
|
1129
|
-
width: text.width,
|
|
1130
|
-
height: text.height
|
|
1131
|
-
};
|
|
1132
|
-
return RectangleClient.isHit(rectangle, RectangleClient.getRectangleByPoints([point, point]));
|
|
1133
|
-
});
|
|
1134
|
-
};
|
|
1135
|
-
|
|
1136
|
-
const isTextExceedingBounds = (geometry) => {
|
|
1137
|
-
const client = RectangleClient.getRectangleByPoints(geometry.points);
|
|
1138
|
-
if (geometry.textHeight > client.height) {
|
|
1139
|
-
return true;
|
|
1140
|
-
}
|
|
1141
|
-
return false;
|
|
1142
|
-
};
|
|
1143
|
-
const isHitLineText = (board, element, point) => {
|
|
1144
|
-
return getHitLineTextIndex(board, element, point) !== -1;
|
|
1145
|
-
};
|
|
1146
|
-
const isHitPolyLine = (pathPoints, point) => {
|
|
1147
|
-
const distance = distanceBetweenPointAndSegments(pathPoints, point);
|
|
1148
|
-
return distance <= HIT_DISTANCE_BUFFER;
|
|
1149
|
-
};
|
|
1150
|
-
const isHitLine = (board, element, point) => {
|
|
1151
|
-
const points = getLinePoints(board, element);
|
|
1152
|
-
const isHitText = isHitLineText(board, element, point);
|
|
1153
|
-
return isHitText || isHitPolyLine(points, point);
|
|
1154
|
-
};
|
|
1155
|
-
const isRectangleHitDrawElement = (board, element, selection) => {
|
|
1156
|
-
const rangeRectangle = RectangleClient.getRectangleByPoints([selection.anchor, selection.focus]);
|
|
1157
|
-
if (PlaitDrawElement.isGeometry(element)) {
|
|
1158
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1159
|
-
const centerPoint = RectangleClient.getCenterPoint(client);
|
|
1160
|
-
let rotatedCornerPoints = rotatePoints(RectangleClient.getCornerPoints(client), centerPoint, element.angle);
|
|
1161
|
-
if (isTextExceedingBounds(element)) {
|
|
1162
|
-
const textClient = getTextRectangle(element);
|
|
1163
|
-
rotatedCornerPoints = rotatePoints(RectangleClient.getCornerPoints(textClient), centerPoint, element.angle);
|
|
1164
|
-
}
|
|
1165
|
-
return isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
1166
|
-
}
|
|
1167
|
-
if (PlaitDrawElement.isImage(element)) {
|
|
1168
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1169
|
-
const rotatedCornerPoints = rotatePoints(RectangleClient.getCornerPoints(client), RectangleClient.getCenterPoint(client), element.angle);
|
|
1170
|
-
return isPolylineHitRectangle(rotatedCornerPoints, rangeRectangle);
|
|
1171
|
-
}
|
|
1172
|
-
if (PlaitDrawElement.isLine(element)) {
|
|
1173
|
-
const points = getLinePoints(board, element);
|
|
1174
|
-
return isPolylineHitRectangle(points, rangeRectangle);
|
|
1175
|
-
}
|
|
1176
|
-
return null;
|
|
1177
|
-
};
|
|
1178
|
-
const isHitDrawElement = (board, element, point) => {
|
|
1179
|
-
const rectangle = board.getRectangle(element);
|
|
1180
|
-
const centerPoint = RectangleClient.getCenterPoint(rectangle);
|
|
1181
|
-
if (element.angle) {
|
|
1182
|
-
point = rotate(point[0], point[1], centerPoint[0], centerPoint[1], -element.angle);
|
|
1183
|
-
}
|
|
1184
|
-
if (PlaitDrawElement.isGeometry(element)) {
|
|
1185
|
-
const fill = getFillByElement(board, element);
|
|
1186
|
-
const engine = getEngine(getShape(element));
|
|
1187
|
-
const nearestPoint = engine.getNearestPoint(rectangle, point);
|
|
1188
|
-
const distance = distanceBetweenPointAndPoint(nearestPoint[0], nearestPoint[1], point[0], point[1]);
|
|
1189
|
-
const isHitEdge = distance <= HIT_DISTANCE_BUFFER;
|
|
1190
|
-
if (isHitEdge) {
|
|
1191
|
-
return isHitEdge;
|
|
1192
|
-
}
|
|
1193
|
-
// when shape equals text, fill is not allowed
|
|
1194
|
-
if (fill !== DefaultGeometryStyle.fill && fill !== TRANSPARENT && !PlaitDrawElement.isText(element)) {
|
|
1195
|
-
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
1196
|
-
if (isHitInside) {
|
|
1197
|
-
return isHitInside;
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
else {
|
|
1201
|
-
// if shape equals text, only check text rectangle
|
|
1202
|
-
if (PlaitDrawElement.isText(element)) {
|
|
1203
|
-
const textClient = getTextRectangle(element);
|
|
1204
|
-
let isHitText = RectangleClient.isPointInRectangle(textClient, point);
|
|
1205
|
-
return isHitText;
|
|
1206
|
-
}
|
|
1207
|
-
// check textRectangle of element
|
|
1208
|
-
const textClient = engine.getTextRectangle ? engine.getTextRectangle(element) : getTextRectangle(element);
|
|
1209
|
-
const isHitTextRectangle = RectangleClient.isPointInRectangle(textClient, point);
|
|
1210
|
-
if (isHitTextRectangle) {
|
|
1211
|
-
return isHitTextRectangle;
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
if (PlaitDrawElement.isImage(element)) {
|
|
1216
|
-
const client = RectangleClient.getRectangleByPoints(element.points);
|
|
1217
|
-
const rotatedCornerPoints = rotatePoints(RectangleClient.getCornerPoints(client), RectangleClient.getCenterPoint(client), element.angle);
|
|
1218
|
-
return isPointInPolygon(point, rotatedCornerPoints);
|
|
1219
|
-
}
|
|
1220
|
-
if (PlaitDrawElement.isLine(element)) {
|
|
1221
|
-
return isHitLine(board, element, point);
|
|
1222
|
-
}
|
|
1223
|
-
return null;
|
|
1224
|
-
};
|
|
1225
|
-
const isHitElementInside = (board, element, point) => {
|
|
1226
|
-
const rectangle = board.getRectangle(element);
|
|
1227
|
-
const centerPoint = RectangleClient.getCenterPoint(rectangle);
|
|
1228
|
-
if (element.angle) {
|
|
1229
|
-
point = rotate(point[0], point[1], centerPoint[0], centerPoint[1], -element.angle);
|
|
1230
|
-
}
|
|
1231
|
-
if (PlaitDrawElement.isGeometry(element)) {
|
|
1232
|
-
const engine = getEngine(getShape(element));
|
|
1233
|
-
const isHitInside = engine.isInsidePoint(rectangle, point);
|
|
1234
|
-
if (isHitInside) {
|
|
1235
|
-
return isHitInside;
|
|
1236
|
-
}
|
|
1237
|
-
if (engine.getTextRectangle) {
|
|
1238
|
-
const textClient = engine.getTextRectangle(element);
|
|
1239
|
-
const isHitTextRectangle = RectangleClient.isPointInRectangle(textClient, point);
|
|
1240
|
-
if (isHitTextRectangle) {
|
|
1241
|
-
return isHitTextRectangle;
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
if (PlaitDrawElement.isImage(element)) {
|
|
1246
|
-
return isRectangleHitDrawElement(board, element, { anchor: point, focus: point });
|
|
1247
|
-
}
|
|
1248
|
-
if (PlaitDrawElement.isLine(element)) {
|
|
1249
|
-
return isHitLine(board, element, point);
|
|
1250
|
-
}
|
|
1251
|
-
return null;
|
|
1252
|
-
};
|
|
1253
|
-
|
|
1254
|
-
const getCenterPointsOnPolygon$1 = (points) => {
|
|
1255
|
-
const centerPoints = [];
|
|
1256
|
-
for (let i = 0; i < points.length; i++) {
|
|
1257
|
-
let j = i == points.length - 1 ? 0 : i + 1;
|
|
1258
|
-
centerPoints.push([(points[i][0] + points[j][0]) / 2, (points[i][1] + points[j][1]) / 2]);
|
|
1259
|
-
}
|
|
1260
|
-
return centerPoints;
|
|
1261
|
-
};
|
|
1262
|
-
const getCrossingPointBetweenPointAndPolygon = (corners, point) => {
|
|
1263
|
-
const result = [];
|
|
1264
|
-
for (let index = 1; index <= corners.length; index++) {
|
|
1265
|
-
let start = corners[index - 1];
|
|
1266
|
-
let end = index === corners.length ? corners[0] : corners[index];
|
|
1267
|
-
const crossingPoint = getCrossingPointsBetweenPointAndSegment(point, start, end);
|
|
1268
|
-
result.push(...crossingPoint);
|
|
1269
|
-
}
|
|
1270
|
-
return result;
|
|
1324
|
+
return result;
|
|
1271
1325
|
};
|
|
1272
1326
|
const getPolygonEdgeByConnectionPoint = (corners, point) => {
|
|
1273
1327
|
for (let index = 1; index <= corners.length; index++) {
|
|
@@ -1429,44 +1483,55 @@ const DiamondEngine = createPolygonEngine({
|
|
|
1429
1483
|
}
|
|
1430
1484
|
});
|
|
1431
1485
|
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1486
|
+
function createEllipseEngine(createOptions) {
|
|
1487
|
+
const engine = {
|
|
1488
|
+
draw(board, rectangle, options) {
|
|
1489
|
+
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
1490
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
1491
|
+
return rs.ellipse(centerPoint[0], centerPoint[1], rectangle.width, rectangle.height, { ...options, fillStyle: 'solid' });
|
|
1492
|
+
},
|
|
1493
|
+
isInsidePoint(rectangle, point) {
|
|
1494
|
+
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
1495
|
+
return isPointInEllipse(point, centerPoint, rectangle.width / 2, rectangle.height / 2);
|
|
1496
|
+
},
|
|
1497
|
+
getCornerPoints(rectangle) {
|
|
1498
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
1499
|
+
},
|
|
1500
|
+
getNearestPoint(rectangle, point) {
|
|
1501
|
+
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
1502
|
+
return getNearestPointBetweenPointAndEllipse(point, centerPoint, rectangle.width / 2, rectangle.height / 2);
|
|
1503
|
+
},
|
|
1504
|
+
getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
|
|
1505
|
+
const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
1506
|
+
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
1507
|
+
const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
|
|
1508
|
+
const a = rectangle.width / 2;
|
|
1509
|
+
const b = rectangle.height / 2;
|
|
1510
|
+
const slope = getEllipseTangentSlope(point[0], point[1], a, b);
|
|
1511
|
+
const vector = getVectorFromPointAndSlope(point[0], point[1], slope);
|
|
1512
|
+
return vector;
|
|
1513
|
+
},
|
|
1514
|
+
getConnectorPoints(rectangle) {
|
|
1515
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
1516
|
+
},
|
|
1517
|
+
getTextRectangle(element) {
|
|
1518
|
+
const rectangle = getTextRectangle(element);
|
|
1519
|
+
const width = rectangle.width;
|
|
1520
|
+
rectangle.width = (rectangle.width * 3) / 4;
|
|
1521
|
+
rectangle.x += width / 8;
|
|
1522
|
+
return rectangle;
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
if (createOptions?.draw) {
|
|
1526
|
+
engine.draw = createOptions.draw;
|
|
1468
1527
|
}
|
|
1469
|
-
|
|
1528
|
+
if (createOptions?.getTextRectangle) {
|
|
1529
|
+
engine.getTextRectangle = createOptions.getTextRectangle;
|
|
1530
|
+
}
|
|
1531
|
+
return engine;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
const EllipseEngine = createEllipseEngine();
|
|
1470
1535
|
function getNearestPointBetweenPointAndEllipse(point, center, rx, ry, rotation = 0) {
|
|
1471
1536
|
const rectangleClient = {
|
|
1472
1537
|
x: center[0] - rx,
|
|
@@ -2254,54 +2319,229 @@ const StoredDataEngine = {
|
|
|
2254
2319
|
}
|
|
2255
2320
|
};
|
|
2256
2321
|
|
|
2257
|
-
const
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2322
|
+
const PredefinedProcessEngine = {
|
|
2323
|
+
draw(board, rectangle, options) {
|
|
2324
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
2325
|
+
const shape = rs.path(`M${rectangle.x} ${rectangle.y} H${rectangle.x + rectangle.width} V${rectangle.y + rectangle.height} H${rectangle.x} Z M${rectangle.x + rectangle.width * 0.06} ${rectangle.y} L${rectangle.x + rectangle.width * 0.06} ${rectangle.y +
|
|
2326
|
+
rectangle.height} M${rectangle.x + rectangle.width - rectangle.width * 0.06} ${rectangle.y} L${rectangle.x +
|
|
2327
|
+
rectangle.width -
|
|
2328
|
+
rectangle.width * 0.06} ${rectangle.y + rectangle.height}`, { ...options, fillStyle: 'solid' });
|
|
2329
|
+
setStrokeLinecap(shape, 'round');
|
|
2330
|
+
return shape;
|
|
2331
|
+
},
|
|
2332
|
+
isInsidePoint(rectangle, point) {
|
|
2333
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
2334
|
+
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
2335
|
+
},
|
|
2336
|
+
getCornerPoints(rectangle) {
|
|
2337
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
2338
|
+
},
|
|
2339
|
+
getNearestPoint(rectangle, point) {
|
|
2340
|
+
return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
2341
|
+
},
|
|
2342
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
2343
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
2344
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
2345
|
+
return getPolygonEdgeByConnectionPoint(corners, point);
|
|
2346
|
+
},
|
|
2347
|
+
getConnectorPoints(rectangle) {
|
|
2348
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
2349
|
+
},
|
|
2350
|
+
getTextRectangle: (element) => {
|
|
2351
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2352
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
2353
|
+
const height = element.textHeight;
|
|
2354
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2 - elementRectangle.width * 0.06 * 2;
|
|
2355
|
+
return {
|
|
2356
|
+
height,
|
|
2357
|
+
width: width > 0 ? width : 0,
|
|
2358
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + elementRectangle.width * 0.06,
|
|
2359
|
+
y: elementRectangle.y + (elementRectangle.height - height) / 2
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2292
2362
|
};
|
|
2293
2363
|
|
|
2294
|
-
const
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2364
|
+
const getOffPagePoints = (rectangle) => {
|
|
2365
|
+
return [
|
|
2366
|
+
[rectangle.x, rectangle.y],
|
|
2367
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
2368
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
2369
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height],
|
|
2370
|
+
[rectangle.x, rectangle.y + rectangle.height / 2]
|
|
2371
|
+
];
|
|
2372
|
+
};
|
|
2373
|
+
const OffPageEngine = createPolygonEngine({
|
|
2374
|
+
getPolygonPoints: getOffPagePoints,
|
|
2375
|
+
getConnectorPoints: (rectangle) => {
|
|
2376
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
2377
|
+
},
|
|
2378
|
+
getTextRectangle: (element) => {
|
|
2379
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2380
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
2381
|
+
const height = element.textHeight;
|
|
2382
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
2383
|
+
return {
|
|
2384
|
+
width: width > 0 ? width : 0,
|
|
2385
|
+
height: height,
|
|
2386
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
2387
|
+
y: elementRectangle.y + (elementRectangle.height - elementRectangle.height / 2 - height) / 2
|
|
2388
|
+
};
|
|
2389
|
+
}
|
|
2390
|
+
});
|
|
2391
|
+
|
|
2392
|
+
const CloudEngine = {
|
|
2393
|
+
draw(board, rectangle, options) {
|
|
2394
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
2395
|
+
const divisionWidth = rectangle.width / 7;
|
|
2396
|
+
const divisionHeight = rectangle.height / 3.2;
|
|
2397
|
+
const xRadius = divisionWidth / 8.5;
|
|
2398
|
+
const yRadius = divisionHeight / 20;
|
|
2399
|
+
const svgElement = rs.path(`M ${rectangle.x + divisionWidth} ${rectangle.y + divisionHeight}
|
|
2400
|
+
A ${xRadius} ${yRadius * 1.2} 0 1 1 ${rectangle.x + divisionWidth * 2} ${rectangle.y + divisionHeight / 2}
|
|
2401
|
+
A ${xRadius} ${yRadius} 0 1 1 ${rectangle.x + divisionWidth * 4.2} ${rectangle.y + divisionHeight / 2.2}
|
|
2402
|
+
A ${xRadius} ${yRadius} 0 1 1 ${rectangle.x + divisionWidth * 5.8} ${rectangle.y + divisionHeight}
|
|
2403
|
+
A ${xRadius} ${yRadius * 1.3} 0 1 1 ${rectangle.x + divisionWidth * 6} ${rectangle.y + divisionHeight * 2.2}
|
|
2404
|
+
A ${xRadius} ${yRadius * 1.2} 0 1 1 ${rectangle.x + divisionWidth * 5} ${rectangle.y + divisionHeight * 2.8}
|
|
2405
|
+
A ${xRadius} ${yRadius / 1.2} 0 1 1 ${rectangle.x + divisionWidth * 2.8} ${rectangle.y + divisionHeight * 2.8}
|
|
2406
|
+
A ${xRadius} ${yRadius} 0 1 1 ${rectangle.x + divisionWidth} ${rectangle.y + divisionHeight * 2.2}
|
|
2407
|
+
A ${xRadius} ${yRadius * 1.42} 0 1 1 ${rectangle.x + divisionWidth} ${rectangle.y + divisionHeight}
|
|
2408
|
+
Z`, { ...options, fillStyle: 'solid' });
|
|
2409
|
+
setPathStrokeLinecap(svgElement, 'round');
|
|
2410
|
+
return svgElement;
|
|
2411
|
+
},
|
|
2412
|
+
isInsidePoint(rectangle, point) {
|
|
2413
|
+
const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
|
|
2414
|
+
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
2415
|
+
},
|
|
2416
|
+
getCornerPoints(rectangle) {
|
|
2417
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
2418
|
+
},
|
|
2419
|
+
getNearestPoint(rectangle, point) {
|
|
2420
|
+
return getNearestPointBetweenPointAndSegments(point, CloudEngine.getCornerPoints(rectangle));
|
|
2421
|
+
},
|
|
2422
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
2423
|
+
const corners = CloudEngine.getCornerPoints(rectangle);
|
|
2424
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
2425
|
+
return getPolygonEdgeByConnectionPoint(corners, point);
|
|
2426
|
+
},
|
|
2427
|
+
getConnectorPoints(rectangle) {
|
|
2428
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
2429
|
+
},
|
|
2430
|
+
getTextRectangle(element) {
|
|
2431
|
+
const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2432
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
2433
|
+
const height = element.textHeight;
|
|
2434
|
+
const originWidth = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
2435
|
+
const width = originWidth / 1.5;
|
|
2436
|
+
return {
|
|
2437
|
+
height,
|
|
2438
|
+
width: width > 0 ? width : 0,
|
|
2439
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + originWidth / 6,
|
|
2440
|
+
y: elementRectangle.y + elementRectangle.height / 6 + ((elementRectangle.height * 4) / 6 - height) / 2
|
|
2441
|
+
};
|
|
2442
|
+
}
|
|
2443
|
+
};
|
|
2444
|
+
|
|
2445
|
+
const OrEngine = createEllipseEngine({
|
|
2446
|
+
draw(board, rectangle, options) {
|
|
2447
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
2448
|
+
const rx = rectangle.width / 2;
|
|
2449
|
+
const ry = rectangle.height / 2;
|
|
2450
|
+
const startPoint = [rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2];
|
|
2451
|
+
return rs.path(`M${startPoint[0]} ${startPoint[1]}
|
|
2452
|
+
A${rx},${ry} 0 1,1 ${startPoint[0]} ${startPoint[1] - 0.01}
|
|
2453
|
+
M${rectangle.x} ${rectangle.y + rectangle.height / 2}
|
|
2454
|
+
L${rectangle.x + rectangle.width} ${rectangle.y + rectangle.height / 2}
|
|
2455
|
+
M${rectangle.x + rectangle.width / 2} ${rectangle.y}
|
|
2456
|
+
L${rectangle.x + rectangle.width / 2} ${rectangle.y + rectangle.height}
|
|
2457
|
+
`, { ...options, fillStyle: 'solid' });
|
|
2458
|
+
},
|
|
2459
|
+
getTextRectangle(element) {
|
|
2460
|
+
const rectangle = getTextRectangle(element);
|
|
2461
|
+
rectangle.width = 0;
|
|
2462
|
+
rectangle.height = 0;
|
|
2463
|
+
return rectangle;
|
|
2464
|
+
}
|
|
2465
|
+
});
|
|
2466
|
+
|
|
2467
|
+
const SummingJunctionEngine = createEllipseEngine({
|
|
2468
|
+
draw(board, rectangle, options) {
|
|
2469
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
2470
|
+
const rx = rectangle.width / 2;
|
|
2471
|
+
const ry = rectangle.height / 2;
|
|
2472
|
+
const startPoint = [rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2];
|
|
2473
|
+
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
2474
|
+
const line1Points = getCrossingPointsBetweenEllipseAndSegment([rectangle.x, rectangle.y], [rectangle.x + rectangle.width, rectangle.y + rectangle.height], centerPoint[0], centerPoint[1], rx, ry);
|
|
2475
|
+
const line2Points = getCrossingPointsBetweenEllipseAndSegment([rectangle.x + rectangle.width, rectangle.y], [rectangle.x, rectangle.y + rectangle.height], centerPoint[0], centerPoint[1], rx, ry);
|
|
2476
|
+
return rs.path(`M${startPoint[0]} ${startPoint[1]}
|
|
2477
|
+
A${rx},${ry} 0 1,1 ${startPoint[0]} ${startPoint[1] - 0.01}
|
|
2478
|
+
M${line1Points[0][0]} ${line1Points[0][1]}
|
|
2479
|
+
L${line1Points[1][0]} ${line1Points[1][1]}
|
|
2480
|
+
M${line2Points[0][0]} ${line2Points[0][1]}
|
|
2481
|
+
L${line2Points[1][0]} ${line2Points[1][1]}
|
|
2482
|
+
`, { ...options, fillStyle: 'solid' });
|
|
2483
|
+
},
|
|
2484
|
+
getTextRectangle(element) {
|
|
2485
|
+
const rectangle = getTextRectangle(element);
|
|
2486
|
+
rectangle.width = 0;
|
|
2487
|
+
rectangle.height = 0;
|
|
2488
|
+
return rectangle;
|
|
2489
|
+
}
|
|
2490
|
+
});
|
|
2491
|
+
|
|
2492
|
+
const ShapeEngineMap = {
|
|
2493
|
+
[BasicShapes.rectangle]: RectangleEngine,
|
|
2494
|
+
[BasicShapes.diamond]: DiamondEngine,
|
|
2495
|
+
[BasicShapes.ellipse]: EllipseEngine,
|
|
2496
|
+
[BasicShapes.parallelogram]: ParallelogramEngine,
|
|
2497
|
+
[BasicShapes.roundRectangle]: RoundRectangleEngine,
|
|
2498
|
+
[BasicShapes.text]: RectangleEngine,
|
|
2499
|
+
[BasicShapes.triangle]: TriangleEngine,
|
|
2500
|
+
[BasicShapes.leftArrow]: LeftArrowEngine,
|
|
2501
|
+
[BasicShapes.trapezoid]: TrapezoidEngine,
|
|
2502
|
+
[BasicShapes.rightArrow]: RightArrowEngine,
|
|
2503
|
+
[BasicShapes.cross]: CrossEngine,
|
|
2504
|
+
[BasicShapes.star]: StarEngine,
|
|
2505
|
+
[BasicShapes.pentagon]: PentagonEngine,
|
|
2506
|
+
[BasicShapes.hexagon]: HexagonEngine,
|
|
2507
|
+
[BasicShapes.octagon]: OctagonEngine,
|
|
2508
|
+
[BasicShapes.pentagonArrow]: PentagonArrowEngine,
|
|
2509
|
+
[BasicShapes.processArrow]: ProcessArrowEngine,
|
|
2510
|
+
[BasicShapes.twoWayArrow]: TwoWayArrowEngine,
|
|
2511
|
+
[BasicShapes.comment]: CommentEngine,
|
|
2512
|
+
[BasicShapes.roundComment]: RoundCommentEngine,
|
|
2513
|
+
[BasicShapes.cloud]: CloudEngine,
|
|
2514
|
+
[FlowchartSymbols.process]: RectangleEngine,
|
|
2515
|
+
[FlowchartSymbols.decision]: DiamondEngine,
|
|
2516
|
+
[FlowchartSymbols.connector]: EllipseEngine,
|
|
2517
|
+
[FlowchartSymbols.data]: ParallelogramEngine,
|
|
2518
|
+
[FlowchartSymbols.terminal]: TerminalEngine,
|
|
2519
|
+
[FlowchartSymbols.manualInput]: ManualInputEngine,
|
|
2520
|
+
[FlowchartSymbols.preparation]: PreparationEngine,
|
|
2521
|
+
[FlowchartSymbols.manualLoop]: ManualLoopEngine,
|
|
2522
|
+
[FlowchartSymbols.merge]: MergeEngine,
|
|
2523
|
+
[FlowchartSymbols.delay]: DelayEngine,
|
|
2524
|
+
[FlowchartSymbols.storedData]: StoredDataEngine,
|
|
2525
|
+
[FlowchartSymbols.or]: OrEngine,
|
|
2526
|
+
[FlowchartSymbols.summingJunction]: SummingJunctionEngine,
|
|
2527
|
+
[FlowchartSymbols.predefinedProcess]: PredefinedProcessEngine,
|
|
2528
|
+
[FlowchartSymbols.offPage]: OffPageEngine
|
|
2529
|
+
};
|
|
2530
|
+
const getEngine = (shape) => {
|
|
2531
|
+
return ShapeEngineMap[shape];
|
|
2532
|
+
};
|
|
2533
|
+
|
|
2534
|
+
const createGeometryElement = (shape, points, text, options = {}, textProperties = {}) => {
|
|
2535
|
+
let textOptions = {};
|
|
2536
|
+
let alignment = Alignment.center;
|
|
2537
|
+
let textHeight = DefaultTextProperty.height;
|
|
2538
|
+
if (shape === BasicShapes.text) {
|
|
2539
|
+
textOptions = { autoSize: true };
|
|
2540
|
+
alignment = undefined;
|
|
2541
|
+
}
|
|
2542
|
+
textProperties = { ...textProperties };
|
|
2543
|
+
textProperties?.align && (alignment = textProperties?.align);
|
|
2544
|
+
textProperties?.textHeight && (textHeight = textProperties?.textHeight);
|
|
2305
2545
|
delete textProperties?.align;
|
|
2306
2546
|
delete textProperties?.textHeight;
|
|
2307
2547
|
return {
|
|
@@ -2329,36 +2569,45 @@ const getTextRectangle = (element) => {
|
|
|
2329
2569
|
y: elementRectangle.y + (elementRectangle.height - height) / 2
|
|
2330
2570
|
};
|
|
2331
2571
|
};
|
|
2332
|
-
const
|
|
2333
|
-
const
|
|
2572
|
+
const drawBoundReaction = (board, element, options = { hasMask: true, hasConnector: true }) => {
|
|
2573
|
+
const g = createG();
|
|
2334
2574
|
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2335
|
-
const activeRectangle = RectangleClient.inflate(rectangle,
|
|
2336
|
-
const shape =
|
|
2337
|
-
const
|
|
2575
|
+
const activeRectangle = RectangleClient.inflate(rectangle, SNAPPING_STROKE_WIDTH);
|
|
2576
|
+
const shape = getElementShape(element);
|
|
2577
|
+
const strokeG = drawGeometry(board, activeRectangle, shape, {
|
|
2338
2578
|
stroke: SELECTION_BORDER_COLOR,
|
|
2339
|
-
strokeWidth:
|
|
2340
|
-
fill: SELECTION_FILL_COLOR,
|
|
2341
|
-
fillStyle: 'solid'
|
|
2579
|
+
strokeWidth: SNAPPING_STROKE_WIDTH
|
|
2342
2580
|
});
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
fill: '#FFF',
|
|
2581
|
+
g.appendChild(strokeG);
|
|
2582
|
+
if (options.hasMask) {
|
|
2583
|
+
const maskG = drawGeometry(board, activeRectangle, shape, {
|
|
2584
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
2585
|
+
strokeWidth: 0,
|
|
2586
|
+
fill: SELECTION_FILL_COLOR,
|
|
2350
2587
|
fillStyle: 'solid'
|
|
2351
2588
|
});
|
|
2352
|
-
|
|
2353
|
-
}
|
|
2354
|
-
|
|
2589
|
+
g.appendChild(maskG);
|
|
2590
|
+
}
|
|
2591
|
+
if (options.hasConnector) {
|
|
2592
|
+
const connectorPoints = getEngine(shape).getConnectorPoints(rectangle);
|
|
2593
|
+
connectorPoints.forEach(point => {
|
|
2594
|
+
const circleG = drawCircle(PlaitBoard.getRoughSVG(board), point, 8, {
|
|
2595
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
2596
|
+
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
2597
|
+
fill: '#FFF',
|
|
2598
|
+
fillStyle: 'solid'
|
|
2599
|
+
});
|
|
2600
|
+
g.appendChild(circleG);
|
|
2601
|
+
});
|
|
2602
|
+
}
|
|
2603
|
+
return g;
|
|
2355
2604
|
};
|
|
2356
2605
|
const drawGeometry = (board, outerRectangle, shape, options) => {
|
|
2357
2606
|
return getEngine(shape).draw(board, outerRectangle, options);
|
|
2358
2607
|
};
|
|
2359
2608
|
const getNearestPoint = (element, point) => {
|
|
2360
2609
|
const rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2361
|
-
const shape =
|
|
2610
|
+
const shape = getElementShape(element);
|
|
2362
2611
|
return getEngine(shape).getNearestPoint(rectangle, point);
|
|
2363
2612
|
};
|
|
2364
2613
|
const getCenterPointsOnPolygon = (points) => {
|
|
@@ -2465,6 +2714,9 @@ const getDefaultGeometryProperty = (pointer) => {
|
|
|
2465
2714
|
return getDefaultFlowchartProperty(pointer);
|
|
2466
2715
|
}
|
|
2467
2716
|
else {
|
|
2717
|
+
if (pointer === BasicShapes.cloud) {
|
|
2718
|
+
return DefaultCloudShapeProperty;
|
|
2719
|
+
}
|
|
2468
2720
|
return DefaultBasicShapeProperty;
|
|
2469
2721
|
}
|
|
2470
2722
|
};
|
|
@@ -2516,7 +2768,14 @@ const getFillByElement = (board, element) => {
|
|
|
2516
2768
|
return fill;
|
|
2517
2769
|
};
|
|
2518
2770
|
const getLineDashByElement = (element) => {
|
|
2519
|
-
|
|
2771
|
+
switch (element.strokeStyle) {
|
|
2772
|
+
case StrokeStyle.dashed:
|
|
2773
|
+
return [8, 8 + getStrokeWidthByElement(element)];
|
|
2774
|
+
case StrokeStyle.dotted:
|
|
2775
|
+
return [0, 4 + getStrokeWidthByElement(element)];
|
|
2776
|
+
default:
|
|
2777
|
+
return undefined;
|
|
2778
|
+
}
|
|
2520
2779
|
};
|
|
2521
2780
|
const getStrokeStyleByElement = (element) => {
|
|
2522
2781
|
return element.strokeStyle || StrokeStyle.solid;
|
|
@@ -2595,7 +2854,7 @@ const getConnectionPoint = (geometry, connection, direction, delta) => {
|
|
|
2595
2854
|
};
|
|
2596
2855
|
const getVectorByConnection = (boundElement, connection) => {
|
|
2597
2856
|
const rectangle = RectangleClient.getRectangleByPoints(boundElement.points);
|
|
2598
|
-
const shape =
|
|
2857
|
+
const shape = getElementShape(boundElement);
|
|
2599
2858
|
const engine = getEngine(shape);
|
|
2600
2859
|
let vector = [0, 0];
|
|
2601
2860
|
const direction = getDirectionByPointOfRectangle(connection);
|
|
@@ -2710,6 +2969,7 @@ var StrokeStyle;
|
|
|
2710
2969
|
(function (StrokeStyle) {
|
|
2711
2970
|
StrokeStyle["solid"] = "solid";
|
|
2712
2971
|
StrokeStyle["dashed"] = "dashed";
|
|
2972
|
+
StrokeStyle["dotted"] = "dotted";
|
|
2713
2973
|
})(StrokeStyle || (StrokeStyle = {}));
|
|
2714
2974
|
var MemorizeKey;
|
|
2715
2975
|
(function (MemorizeKey) {
|
|
@@ -2740,7 +3000,7 @@ const PlaitDrawElement = {
|
|
|
2740
3000
|
return false;
|
|
2741
3001
|
}
|
|
2742
3002
|
},
|
|
2743
|
-
|
|
3003
|
+
isShapeElement: (value) => {
|
|
2744
3004
|
return PlaitDrawElement.isImage(value) || PlaitDrawElement.isGeometry(value);
|
|
2745
3005
|
},
|
|
2746
3006
|
isBasicShape: (value) => {
|
|
@@ -2826,7 +3086,7 @@ const collectLineUpdatedRefsByGeometry = (board, geometry, refs) => {
|
|
|
2826
3086
|
const object = { ...line[handle] };
|
|
2827
3087
|
const linePoints = getLinePoints(board, line);
|
|
2828
3088
|
const point = isSourceBound ? linePoints[0] : linePoints[linePoints.length - 1];
|
|
2829
|
-
object.connection =
|
|
3089
|
+
object.connection = getHitConnection(board, point, geometry);
|
|
2830
3090
|
const path = PlaitBoard.findPath(board, line);
|
|
2831
3091
|
const index = refs.findIndex(obj => Path.equals(obj.path, path));
|
|
2832
3092
|
if (index === -1) {
|
|
@@ -2846,7 +3106,7 @@ const collectLineUpdatedRefsByGeometry = (board, geometry, refs) => {
|
|
|
2846
3106
|
const connectLineToGeometry = (board, lineElement, handle, geometryElement) => {
|
|
2847
3107
|
const linePoints = PlaitLine.getPoints(board, lineElement);
|
|
2848
3108
|
const point = handle === LineHandleKey.source ? linePoints[0] : linePoints[linePoints.length - 1];
|
|
2849
|
-
const connection =
|
|
3109
|
+
const connection = getHitConnection(board, point, geometryElement);
|
|
2850
3110
|
if (connection) {
|
|
2851
3111
|
let source = lineElement.source;
|
|
2852
3112
|
let target = lineElement.target;
|
|
@@ -3058,9 +3318,8 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
3058
3318
|
get textManage() {
|
|
3059
3319
|
return this.getTextManages()[0];
|
|
3060
3320
|
}
|
|
3061
|
-
constructor(
|
|
3321
|
+
constructor(cdr) {
|
|
3062
3322
|
super(cdr);
|
|
3063
|
-
this.viewContainerRef = viewContainerRef;
|
|
3064
3323
|
this.cdr = cdr;
|
|
3065
3324
|
this.destroy$ = new Subject();
|
|
3066
3325
|
}
|
|
@@ -3102,7 +3361,7 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
3102
3361
|
ngOnInit() {
|
|
3103
3362
|
super.ngOnInit();
|
|
3104
3363
|
this.initializeGenerator();
|
|
3105
|
-
this.shapeGenerator.processDrawing(this.element, this.
|
|
3364
|
+
this.shapeGenerator.processDrawing(this.element, this.getElementG());
|
|
3106
3365
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
3107
3366
|
this.lineAutoCompleteGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
|
|
3108
3367
|
selected: this.selected
|
|
@@ -3112,7 +3371,7 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
3112
3371
|
onContextChanged(value, previous) {
|
|
3113
3372
|
const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
|
|
3114
3373
|
if (value.element !== previous.element || isChangeTheme) {
|
|
3115
|
-
this.shapeGenerator.processDrawing(this.element, this.
|
|
3374
|
+
this.shapeGenerator.processDrawing(this.element, this.getElementG());
|
|
3116
3375
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
3117
3376
|
this.lineAutoCompleteGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
|
|
3118
3377
|
selected: this.selected
|
|
@@ -3136,7 +3395,7 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
3136
3395
|
}
|
|
3137
3396
|
drawText() {
|
|
3138
3397
|
this.textManage.draw(this.element.text);
|
|
3139
|
-
this.
|
|
3398
|
+
this.getElementG().append(this.textManage.g);
|
|
3140
3399
|
const centerPoint = RectangleClient.getCenterPoint(this.board.getRectangle(this.element));
|
|
3141
3400
|
this.textManage.updateAngle(centerPoint, this.element.angle);
|
|
3142
3401
|
}
|
|
@@ -3187,7 +3446,7 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
3187
3446
|
this.activeGenerator.destroy();
|
|
3188
3447
|
this.lineAutoCompleteGenerator.destroy();
|
|
3189
3448
|
}
|
|
3190
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: GeometryComponent, deps: [{ token: i0.
|
|
3449
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: GeometryComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3191
3450
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: GeometryComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3192
3451
|
}
|
|
3193
3452
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: GeometryComponent, decorators: [{
|
|
@@ -3198,7 +3457,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
3198
3457
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3199
3458
|
standalone: true
|
|
3200
3459
|
}]
|
|
3201
|
-
}], ctorParameters: () => [{ type: i0.
|
|
3460
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
|
|
3202
3461
|
|
|
3203
3462
|
class LineActiveGenerator extends Generator {
|
|
3204
3463
|
constructor() {
|
|
@@ -3271,12 +3530,11 @@ class LineActiveGenerator extends Generator {
|
|
|
3271
3530
|
}
|
|
3272
3531
|
}
|
|
3273
3532
|
|
|
3274
|
-
const debugKey$
|
|
3275
|
-
const debugGenerator$
|
|
3533
|
+
const debugKey$2 = 'debug:plait:line-turning';
|
|
3534
|
+
const debugGenerator$2 = createDebugGenerator(debugKey$2);
|
|
3276
3535
|
class LineComponent extends CommonPluginElement {
|
|
3277
|
-
constructor(
|
|
3536
|
+
constructor(cdr) {
|
|
3278
3537
|
super(cdr);
|
|
3279
|
-
this.viewContainerRef = viewContainerRef;
|
|
3280
3538
|
this.cdr = cdr;
|
|
3281
3539
|
this.destroy$ = new Subject();
|
|
3282
3540
|
this.boundedElements = {};
|
|
@@ -3288,7 +3546,7 @@ class LineComponent extends CommonPluginElement {
|
|
|
3288
3546
|
}
|
|
3289
3547
|
ngOnInit() {
|
|
3290
3548
|
this.initializeGenerator();
|
|
3291
|
-
this.shapeGenerator.processDrawing(this.element, this.
|
|
3549
|
+
this.shapeGenerator.processDrawing(this.element, this.getElementG());
|
|
3292
3550
|
const linePoints = getLinePoints(this.board, this.element);
|
|
3293
3551
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
|
|
3294
3552
|
selected: this.selected,
|
|
@@ -3297,7 +3555,7 @@ class LineComponent extends CommonPluginElement {
|
|
|
3297
3555
|
super.ngOnInit();
|
|
3298
3556
|
this.boundedElements = this.getBoundedElements();
|
|
3299
3557
|
this.drawText();
|
|
3300
|
-
debugGenerator$
|
|
3558
|
+
debugGenerator$2.isDebug() && debugGenerator$2.drawCircles(this.board, this.element.points.slice(1, -1), 4, true);
|
|
3301
3559
|
}
|
|
3302
3560
|
getBoundedElements() {
|
|
3303
3561
|
const boundedElements = {};
|
|
@@ -3322,7 +3580,7 @@ class LineComponent extends CommonPluginElement {
|
|
|
3322
3580
|
const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
|
|
3323
3581
|
const linePoints = getLinePoints(this.board, this.element);
|
|
3324
3582
|
if (value.element !== previous.element || isChangeTheme) {
|
|
3325
|
-
this.shapeGenerator.processDrawing(this.element, this.
|
|
3583
|
+
this.shapeGenerator.processDrawing(this.element, this.getElementG());
|
|
3326
3584
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
|
|
3327
3585
|
selected: this.selected,
|
|
3328
3586
|
linePoints
|
|
@@ -3340,7 +3598,7 @@ class LineComponent extends CommonPluginElement {
|
|
|
3340
3598
|
}
|
|
3341
3599
|
}
|
|
3342
3600
|
if (isBoundedElementsChanged) {
|
|
3343
|
-
this.shapeGenerator.processDrawing(this.element, this.
|
|
3601
|
+
this.shapeGenerator.processDrawing(this.element, this.getElementG());
|
|
3344
3602
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
|
|
3345
3603
|
selected: this.selected,
|
|
3346
3604
|
linePoints
|
|
@@ -3363,7 +3621,7 @@ class LineComponent extends CommonPluginElement {
|
|
|
3363
3621
|
if (this.element.texts?.length) {
|
|
3364
3622
|
this.getTextManages().forEach((manage, index) => {
|
|
3365
3623
|
manage.draw(this.element.texts[index].text);
|
|
3366
|
-
this.
|
|
3624
|
+
this.getElementG().append(manage.g);
|
|
3367
3625
|
});
|
|
3368
3626
|
}
|
|
3369
3627
|
}
|
|
@@ -3420,7 +3678,7 @@ class LineComponent extends CommonPluginElement {
|
|
|
3420
3678
|
this.destroy$.complete();
|
|
3421
3679
|
this.destroyTextManages();
|
|
3422
3680
|
}
|
|
3423
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: LineComponent, deps: [{ token: i0.
|
|
3681
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: LineComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3424
3682
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: LineComponent, isStandalone: true, selector: "plait-draw-line", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3425
3683
|
}
|
|
3426
3684
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: LineComponent, decorators: [{
|
|
@@ -3431,7 +3689,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
3431
3689
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3432
3690
|
standalone: true
|
|
3433
3691
|
}]
|
|
3434
|
-
}], ctorParameters: () => [{ type: i0.
|
|
3692
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
|
|
3435
3693
|
|
|
3436
3694
|
const withDrawHotkey = (board) => {
|
|
3437
3695
|
const { keyDown, dblClick } = board;
|
|
@@ -3466,57 +3724,483 @@ const withDrawHotkey = (board) => {
|
|
|
3466
3724
|
return board;
|
|
3467
3725
|
};
|
|
3468
3726
|
|
|
3469
|
-
const
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
let
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
const
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3727
|
+
const debugKey$1 = 'debug:plait:resize-for-rotation';
|
|
3728
|
+
const debugGenerator$1 = createDebugGenerator(debugKey$1);
|
|
3729
|
+
function withDrawResize(board) {
|
|
3730
|
+
const { afterChange, drawActiveRectangle } = board;
|
|
3731
|
+
let snapG;
|
|
3732
|
+
let handleG;
|
|
3733
|
+
let needCustomActiveRectangle = false;
|
|
3734
|
+
let resizeActivePoints = null;
|
|
3735
|
+
const canResize = () => {
|
|
3736
|
+
const elements = getSelectedElements(board);
|
|
3737
|
+
return elements.length > 1 && elements.every(el => PlaitDrawElement.isDrawElement(el));
|
|
3738
|
+
};
|
|
3739
|
+
const options = {
|
|
3740
|
+
key: 'draw-elements',
|
|
3741
|
+
canResize,
|
|
3742
|
+
hitTest: (point) => {
|
|
3743
|
+
const elements = getSelectedElements(board);
|
|
3744
|
+
const boundingRectangle = getRectangleByElements(board, elements, false);
|
|
3745
|
+
const angle = getSelectionAngle(elements);
|
|
3746
|
+
const handleRef = getHitRectangleResizeHandleRef(board, boundingRectangle, point, angle);
|
|
3747
|
+
if (handleRef) {
|
|
3748
|
+
return {
|
|
3749
|
+
element: elements,
|
|
3750
|
+
rectangle: boundingRectangle,
|
|
3751
|
+
handle: handleRef.handle,
|
|
3752
|
+
cursorClass: handleRef.cursorClass
|
|
3753
|
+
};
|
|
3754
|
+
}
|
|
3755
|
+
return null;
|
|
3756
|
+
},
|
|
3757
|
+
onResize: (resizeRef, resizeState) => {
|
|
3758
|
+
snapG?.remove();
|
|
3759
|
+
debugGenerator$1.isDebug() && debugGenerator$1.clear();
|
|
3760
|
+
const isFromCorner = isCornerHandle(board, resizeRef.handle);
|
|
3761
|
+
const isAspectRatio = resizeState.isShift || isFromCorner;
|
|
3762
|
+
const centerPoint = RectangleClient.getCenterPoint(resizeRef.rectangle);
|
|
3763
|
+
const handleIndex = getIndexByResizeHandle(resizeRef.handle);
|
|
3764
|
+
const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, handleIndex, resizeRef.rectangle);
|
|
3765
|
+
const angle = getSelectionAngle(resizeRef.element);
|
|
3766
|
+
let bulkRotationRef;
|
|
3767
|
+
if (angle) {
|
|
3768
|
+
bulkRotationRef = {
|
|
3769
|
+
angle: angle,
|
|
3770
|
+
offsetX: 0,
|
|
3771
|
+
offsetY: 0,
|
|
3772
|
+
newCenterPoint: [0, 0]
|
|
3773
|
+
};
|
|
3774
|
+
const [rotatedStartPoint, rotateEndPoint] = rotatePoints([resizeState.startPoint, resizeState.endPoint], centerPoint, -bulkRotationRef.angle);
|
|
3775
|
+
resizeState.startPoint = rotatedStartPoint;
|
|
3776
|
+
resizeState.endPoint = rotateEndPoint;
|
|
3777
|
+
}
|
|
3778
|
+
const resizeSnapRefOptions = getSnapResizingRefOptions(board, resizeRef, resizeState, {
|
|
3779
|
+
originPoint,
|
|
3780
|
+
handlePoint
|
|
3781
|
+
}, isAspectRatio, isFromCorner);
|
|
3782
|
+
const resizeSnapRef = getSnapResizingRef(board, resizeRef.element, resizeSnapRefOptions);
|
|
3783
|
+
resizeActivePoints = resizeSnapRef.activePoints;
|
|
3784
|
+
snapG = resizeSnapRef.snapG;
|
|
3785
|
+
PlaitBoard.getElementActiveHost(board).append(snapG);
|
|
3786
|
+
if (bulkRotationRef) {
|
|
3787
|
+
const boundingBoxCornerPoints = RectangleClient.getPoints(resizeRef.rectangle);
|
|
3788
|
+
const resizedBoundingBoxCornerPoints = boundingBoxCornerPoints.map(p => {
|
|
3789
|
+
return movePointByZoomAndOriginPoint(p, originPoint, resizeSnapRef.xZoom, resizeSnapRef.yZoom);
|
|
3790
|
+
});
|
|
3791
|
+
const newBoundingBox = RectangleClient.getRectangleByPoints(resizedBoundingBoxCornerPoints);
|
|
3792
|
+
debugGenerator$1.isDebug() && debugGenerator$1.drawRectangle(board, newBoundingBox, { stroke: 'blue' });
|
|
3793
|
+
const newBoundingBoxCenter = RectangleClient.getCenterPoint(newBoundingBox);
|
|
3794
|
+
const adjustedNewBoundingBoxPoints = resetPointsAfterResize(RectangleClient.getRectangleByPoints(boundingBoxCornerPoints), RectangleClient.getRectangleByPoints(resizedBoundingBoxCornerPoints), centerPoint, newBoundingBoxCenter, bulkRotationRef.angle);
|
|
3795
|
+
const newCenter = RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(adjustedNewBoundingBoxPoints));
|
|
3796
|
+
bulkRotationRef = Object.assign(bulkRotationRef, {
|
|
3797
|
+
offsetX: newCenter[0] - newBoundingBoxCenter[0],
|
|
3798
|
+
offsetY: newCenter[1] - newBoundingBoxCenter[1],
|
|
3799
|
+
newCenterPoint: newCenter
|
|
3800
|
+
});
|
|
3801
|
+
debugGenerator$1.isDebug() && debugGenerator$1.drawRectangle(board, adjustedNewBoundingBoxPoints);
|
|
3802
|
+
}
|
|
3803
|
+
resizeRef.element.forEach(target => {
|
|
3804
|
+
const path = PlaitBoard.findPath(board, target);
|
|
3805
|
+
let points;
|
|
3806
|
+
if (bulkRotationRef) {
|
|
3807
|
+
const reversedPoints = rotatedDataPoints(target.points, centerPoint, -bulkRotationRef.angle);
|
|
3808
|
+
points = reversedPoints.map((p) => {
|
|
3809
|
+
return movePointByZoomAndOriginPoint(p, originPoint, resizeSnapRef.xZoom, resizeSnapRef.yZoom);
|
|
3499
3810
|
});
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
fakeCreateTextRef.g.append(textManage.g);
|
|
3811
|
+
const adjustTargetPoints = points.map(p => [
|
|
3812
|
+
p[0] + bulkRotationRef.offsetX,
|
|
3813
|
+
p[1] + bulkRotationRef.offsetY
|
|
3814
|
+
]);
|
|
3815
|
+
points = rotatedDataPoints(adjustTargetPoints, bulkRotationRef.newCenterPoint, bulkRotationRef.angle);
|
|
3506
3816
|
}
|
|
3507
3817
|
else {
|
|
3508
|
-
|
|
3509
|
-
|
|
3818
|
+
if (hasValidAngle(target)) {
|
|
3819
|
+
needCustomActiveRectangle = true;
|
|
3820
|
+
}
|
|
3821
|
+
if (hasValidAngle(target) && isAxisChangedByAngle(target.angle)) {
|
|
3822
|
+
points = getResizePointsByOtherwiseAxis(board, target.points, originPoint, resizeSnapRef.xZoom, resizeSnapRef.yZoom);
|
|
3823
|
+
}
|
|
3824
|
+
else {
|
|
3825
|
+
points = target.points.map(p => {
|
|
3826
|
+
return movePointByZoomAndOriginPoint(p, originPoint, resizeSnapRef.xZoom, resizeSnapRef.yZoom);
|
|
3827
|
+
});
|
|
3828
|
+
}
|
|
3510
3829
|
}
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3830
|
+
if (PlaitDrawElement.isGeometry(target)) {
|
|
3831
|
+
const { height: textHeight } = getFirstTextManage(target).getSize();
|
|
3832
|
+
DrawTransforms.resizeGeometry(board, points, textHeight, path);
|
|
3833
|
+
}
|
|
3834
|
+
else if (PlaitDrawElement.isLine(target)) {
|
|
3835
|
+
Transforms.setNode(board, { points }, path);
|
|
3836
|
+
}
|
|
3837
|
+
else if (PlaitDrawElement.isImage(target)) {
|
|
3838
|
+
if (isAspectRatio) {
|
|
3839
|
+
Transforms.setNode(board, { points }, path);
|
|
3840
|
+
}
|
|
3841
|
+
else {
|
|
3842
|
+
// The image element does not follow the resize, but moves based on the center point.
|
|
3843
|
+
const targetRectangle = RectangleClient.getRectangleByPoints(target.points);
|
|
3844
|
+
const centerPoint = RectangleClient.getCenterPoint(targetRectangle);
|
|
3845
|
+
const newCenterPoint = movePointByZoomAndOriginPoint(centerPoint, originPoint, resizeSnapRef.xZoom, resizeSnapRef.yZoom);
|
|
3846
|
+
const newTargetRectangle = RectangleClient.getRectangleByCenterPoint(newCenterPoint, targetRectangle.width, targetRectangle.height);
|
|
3847
|
+
Transforms.setNode(board, { points: RectangleClient.getPoints(newTargetRectangle) }, path);
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
});
|
|
3851
|
+
},
|
|
3852
|
+
afterResize: (resizeRef) => {
|
|
3853
|
+
snapG?.remove();
|
|
3854
|
+
snapG = null;
|
|
3855
|
+
if (needCustomActiveRectangle) {
|
|
3856
|
+
needCustomActiveRectangle = false;
|
|
3857
|
+
resizeActivePoints = null;
|
|
3858
|
+
const selectedElements = getSelectedElements(board);
|
|
3859
|
+
Transforms.addSelectionWithTemporaryElements(board, selectedElements);
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
};
|
|
3863
|
+
withResize(board, options);
|
|
3864
|
+
board.afterChange = () => {
|
|
3865
|
+
afterChange();
|
|
3866
|
+
if (handleG) {
|
|
3867
|
+
handleG.remove();
|
|
3868
|
+
handleG = null;
|
|
3869
|
+
}
|
|
3870
|
+
if (canResize() && !isSelectionMoving(board)) {
|
|
3871
|
+
handleG = createG();
|
|
3872
|
+
const elements = getSelectedElements(board);
|
|
3873
|
+
const boundingRectangle = needCustomActiveRectangle
|
|
3874
|
+
? RectangleClient.getRectangleByPoints(resizeActivePoints)
|
|
3875
|
+
: getRectangleByElements(board, elements, false);
|
|
3876
|
+
let corners = RectangleClient.getCornerPoints(boundingRectangle);
|
|
3877
|
+
const angle = getSelectionAngle(elements);
|
|
3878
|
+
if (angle) {
|
|
3879
|
+
const centerPoint = RectangleClient.getCenterPoint(boundingRectangle);
|
|
3880
|
+
corners = rotatePoints(corners, centerPoint, angle);
|
|
3881
|
+
}
|
|
3882
|
+
corners.forEach(corner => {
|
|
3883
|
+
const g = drawHandle(board, corner);
|
|
3884
|
+
handleG && handleG.append(g);
|
|
3885
|
+
});
|
|
3886
|
+
PlaitBoard.getElementActiveHost(board).append(handleG);
|
|
3887
|
+
}
|
|
3888
|
+
};
|
|
3889
|
+
board.drawActiveRectangle = () => {
|
|
3890
|
+
if (needCustomActiveRectangle) {
|
|
3891
|
+
const rectangle = RectangleClient.getRectangleByPoints(resizeActivePoints);
|
|
3892
|
+
return drawRectangle(board, RectangleClient.inflate(rectangle, ACTIVE_STROKE_WIDTH), {
|
|
3893
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
3894
|
+
strokeWidth: ACTIVE_STROKE_WIDTH
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
return drawActiveRectangle();
|
|
3898
|
+
};
|
|
3899
|
+
return board;
|
|
3900
|
+
}
|
|
3901
|
+
const getResizeOriginPointAndHandlePoint = (board, handleIndex, rectangle) => {
|
|
3902
|
+
const symmetricHandleIndex = getSymmetricHandleIndex(board, handleIndex);
|
|
3903
|
+
const originPoint = getResizeHandlePointByIndex(rectangle, symmetricHandleIndex);
|
|
3904
|
+
const handlePoint = getResizeHandlePointByIndex(rectangle, handleIndex);
|
|
3905
|
+
return {
|
|
3906
|
+
originPoint,
|
|
3907
|
+
handlePoint
|
|
3908
|
+
};
|
|
3909
|
+
};
|
|
3910
|
+
const getResizeZoom = (resizeStartAndEnd, resizeOriginPoint, resizeHandlePoint, isFromCorner, isAspectRatio) => {
|
|
3911
|
+
const [startPoint, endPoint] = resizeStartAndEnd;
|
|
3912
|
+
let xZoom = 0;
|
|
3913
|
+
let yZoom = 0;
|
|
3914
|
+
if (isFromCorner) {
|
|
3915
|
+
if (isAspectRatio) {
|
|
3916
|
+
let normalizedOffsetX = Point.getOffsetX(startPoint, endPoint);
|
|
3917
|
+
xZoom = normalizedOffsetX / (resizeHandlePoint[0] - resizeOriginPoint[0]);
|
|
3918
|
+
yZoom = xZoom;
|
|
3919
|
+
}
|
|
3920
|
+
else {
|
|
3921
|
+
let normalizedOffsetX = Point.getOffsetX(startPoint, endPoint);
|
|
3922
|
+
let normalizedOffsetY = Point.getOffsetY(startPoint, endPoint);
|
|
3923
|
+
xZoom = normalizedOffsetX / (resizeHandlePoint[0] - resizeOriginPoint[0]);
|
|
3924
|
+
yZoom = normalizedOffsetY / (resizeHandlePoint[1] - resizeOriginPoint[1]);
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
else {
|
|
3928
|
+
const isHorizontal = Point.isHorizontal(resizeOriginPoint, resizeHandlePoint, 0.1) || false;
|
|
3929
|
+
let normalizedOffset = isHorizontal ? Point.getOffsetX(startPoint, endPoint) : Point.getOffsetY(startPoint, endPoint);
|
|
3930
|
+
let benchmarkOffset = isHorizontal ? resizeHandlePoint[0] - resizeOriginPoint[0] : resizeHandlePoint[1] - resizeOriginPoint[1];
|
|
3931
|
+
const zoom = normalizedOffset / benchmarkOffset;
|
|
3932
|
+
if (isAspectRatio) {
|
|
3933
|
+
xZoom = zoom;
|
|
3934
|
+
yZoom = zoom;
|
|
3935
|
+
}
|
|
3936
|
+
else {
|
|
3937
|
+
if (isHorizontal) {
|
|
3938
|
+
xZoom = zoom;
|
|
3939
|
+
}
|
|
3940
|
+
else {
|
|
3941
|
+
yZoom = zoom;
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3945
|
+
return { xZoom, yZoom };
|
|
3946
|
+
};
|
|
3947
|
+
const movePointByZoomAndOriginPoint = (p, resizeOriginPoint, xZoom, yZoom) => {
|
|
3948
|
+
const offsetX = (p[0] - resizeOriginPoint[0]) * xZoom;
|
|
3949
|
+
const offsetY = (p[1] - resizeOriginPoint[1]) * yZoom;
|
|
3950
|
+
return [p[0] + offsetX, p[1] + offsetY];
|
|
3951
|
+
};
|
|
3952
|
+
/**
|
|
3953
|
+
* 1. Rotate 90°
|
|
3954
|
+
* 2. Scale based on the rotated points
|
|
3955
|
+
* 3. Reverse rotate the scaled points by 90°
|
|
3956
|
+
*/
|
|
3957
|
+
const getResizePointsByOtherwiseAxis = (board, points, resizeOriginPoint, xZoom, yZoom) => {
|
|
3958
|
+
const currentRectangle = RectangleClient.getRectangleByPoints(points);
|
|
3959
|
+
debugGenerator$1.isDebug() && debugGenerator$1.drawRectangle(board, currentRectangle, { stroke: 'black' });
|
|
3960
|
+
let resultPoints = points;
|
|
3961
|
+
resultPoints = rotatePoints(resultPoints, RectangleClient.getCenterPoint(currentRectangle), (1 / 2) * Math.PI);
|
|
3962
|
+
debugGenerator$1.isDebug() && debugGenerator$1.drawRectangle(board, resultPoints, { stroke: 'blue' });
|
|
3963
|
+
resultPoints = resultPoints.map(p => {
|
|
3964
|
+
return movePointByZoomAndOriginPoint(p, resizeOriginPoint, xZoom, yZoom);
|
|
3965
|
+
});
|
|
3966
|
+
debugGenerator$1.isDebug() && debugGenerator$1.drawRectangle(board, resultPoints);
|
|
3967
|
+
const newRectangle = RectangleClient.getRectangleByPoints(resultPoints);
|
|
3968
|
+
return rotatePoints(resultPoints, RectangleClient.getCenterPoint(newRectangle), -(1 / 2) * Math.PI);
|
|
3969
|
+
};
|
|
3970
|
+
|
|
3971
|
+
const debugKey = 'debug:plait:point-for-geometry';
|
|
3972
|
+
const debugGenerator = createDebugGenerator(debugKey);
|
|
3973
|
+
const EQUAL_SPACING = 10;
|
|
3974
|
+
function getSnapResizingRefOptions(board, resizeRef, resizeState, resizeOriginPointAndHandlePoint, isAspectRatio, isFromCorner) {
|
|
3975
|
+
const { originPoint, handlePoint } = resizeOriginPointAndHandlePoint;
|
|
3976
|
+
const resizePoints = [resizeState.startPoint, resizeState.endPoint];
|
|
3977
|
+
const { xZoom, yZoom } = getResizeZoom(resizePoints, originPoint, handlePoint, isFromCorner, isAspectRatio);
|
|
3978
|
+
let activeElements;
|
|
3979
|
+
let resizeOriginPoint = [];
|
|
3980
|
+
if (Array.isArray(resizeRef.element)) {
|
|
3981
|
+
activeElements = resizeRef.element;
|
|
3982
|
+
const rectangle = getRectangleByElements(board, resizeRef.element, false);
|
|
3983
|
+
resizeOriginPoint = RectangleClient.getPoints(rectangle);
|
|
3984
|
+
}
|
|
3985
|
+
else {
|
|
3986
|
+
activeElements = [resizeRef.element];
|
|
3987
|
+
resizeOriginPoint = resizeRef.element.points;
|
|
3988
|
+
}
|
|
3989
|
+
const points = resizeOriginPoint.map(p => {
|
|
3990
|
+
return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom);
|
|
3991
|
+
});
|
|
3992
|
+
const activeRectangle = getRectangleByAngle(RectangleClient.getRectangleByPoints(points), getSelectionAngle(activeElements)) ||
|
|
3993
|
+
RectangleClient.getRectangleByPoints(points);
|
|
3994
|
+
const resizeHandlePoint = movePointByZoomAndOriginPoint(handlePoint, originPoint, xZoom, yZoom);
|
|
3995
|
+
const [x, y] = getUnitVectorByPointAndPoint(originPoint, resizeHandlePoint);
|
|
3996
|
+
return {
|
|
3997
|
+
resizePoints,
|
|
3998
|
+
resizeOriginPoint,
|
|
3999
|
+
activeRectangle,
|
|
4000
|
+
originPoint,
|
|
4001
|
+
handlePoint,
|
|
4002
|
+
directionFactors: [getDirectionFactorByDirectionComponent(x), getDirectionFactorByDirectionComponent(y)],
|
|
4003
|
+
isAspectRatio,
|
|
4004
|
+
isFromCorner
|
|
4005
|
+
};
|
|
4006
|
+
}
|
|
4007
|
+
function getSnapResizingRef(board, activeElements, resizeSnapOptions) {
|
|
4008
|
+
const snapG = createG();
|
|
4009
|
+
const snapRectangles = getSnapRectangles(board, activeElements);
|
|
4010
|
+
let snapLineDelta = getIsometricLineDelta(snapRectangles, resizeSnapOptions);
|
|
4011
|
+
if (snapLineDelta.deltaX === 0 && snapLineDelta.deltaY === 0) {
|
|
4012
|
+
snapLineDelta = getSnapPointDelta(snapRectangles, resizeSnapOptions);
|
|
4013
|
+
}
|
|
4014
|
+
const angle = getSelectionAngle(activeElements);
|
|
4015
|
+
const activePointAndZoom = getActivePointAndZoom(snapLineDelta, resizeSnapOptions, angle);
|
|
4016
|
+
const isometricLinesG = drawIsometricSnapLines(board, activePointAndZoom.activePoints, snapRectangles, resizeSnapOptions, angle);
|
|
4017
|
+
const pointLinesG = drawResizingPointSnapLines(board, activePointAndZoom.activePoints, snapRectangles, resizeSnapOptions, angle);
|
|
4018
|
+
snapG.append(isometricLinesG, pointLinesG);
|
|
4019
|
+
return { ...activePointAndZoom, ...snapLineDelta, snapG };
|
|
4020
|
+
}
|
|
4021
|
+
function getSnapPointDelta(snapRectangles, resizeSnapOptions) {
|
|
4022
|
+
let pointLineDelta = {
|
|
4023
|
+
deltaX: 0,
|
|
4024
|
+
deltaY: 0
|
|
4025
|
+
};
|
|
4026
|
+
const { isAspectRatio, activeRectangle, directionFactors } = resizeSnapOptions;
|
|
4027
|
+
const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
|
|
4028
|
+
const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
|
|
4029
|
+
if (drawHorizontal) {
|
|
4030
|
+
const xSnapAxis = getTripleAxis(activeRectangle, true);
|
|
4031
|
+
const pointX = directionFactors[0] === -1 ? xSnapAxis[0] : xSnapAxis[2];
|
|
4032
|
+
const deltaX = getMinPointDelta(snapRectangles, pointX, true);
|
|
4033
|
+
if (Math.abs(deltaX) < SNAP_TOLERANCE) {
|
|
4034
|
+
pointLineDelta.deltaX = deltaX;
|
|
4035
|
+
if (pointLineDelta.deltaX !== 0 && isAspectRatio) {
|
|
4036
|
+
pointLineDelta.deltaY = pointLineDelta.deltaX / (activeRectangle.width / activeRectangle.height);
|
|
4037
|
+
return pointLineDelta;
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
4041
|
+
if (drawVertical) {
|
|
4042
|
+
const ySnapAxis = getTripleAxis(activeRectangle, false);
|
|
4043
|
+
const pointY = directionFactors[1] === -1 ? ySnapAxis[0] : ySnapAxis[2];
|
|
4044
|
+
const deltaY = getMinPointDelta(snapRectangles, pointY, false);
|
|
4045
|
+
if (Math.abs(deltaY) < SNAP_TOLERANCE) {
|
|
4046
|
+
pointLineDelta.deltaY = deltaY;
|
|
4047
|
+
if (pointLineDelta.deltaY !== 0 && isAspectRatio) {
|
|
4048
|
+
pointLineDelta.deltaX = pointLineDelta.deltaY * (activeRectangle.width / activeRectangle.height);
|
|
4049
|
+
return pointLineDelta;
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
return pointLineDelta;
|
|
4054
|
+
}
|
|
4055
|
+
function getActivePointAndZoom(resizeSnapDelta, resizeSnapOptions, angle) {
|
|
4056
|
+
const { deltaX, deltaY } = resizeSnapDelta;
|
|
4057
|
+
const { resizePoints, isCreate } = resizeSnapOptions;
|
|
4058
|
+
const newResizePoints = [resizePoints[0], [resizePoints[1][0] + deltaX, resizePoints[1][1] + deltaY]];
|
|
4059
|
+
let activePoints = newResizePoints;
|
|
4060
|
+
let xZoom = 0;
|
|
4061
|
+
let yZoom = 0;
|
|
4062
|
+
if (!isCreate) {
|
|
4063
|
+
const { originPoint, handlePoint, isFromCorner, isAspectRatio, resizeOriginPoint } = resizeSnapOptions;
|
|
4064
|
+
const resizeZoom = getResizeZoom(newResizePoints, originPoint, handlePoint, isFromCorner, isAspectRatio);
|
|
4065
|
+
xZoom = resizeZoom.xZoom;
|
|
4066
|
+
yZoom = resizeZoom.yZoom;
|
|
4067
|
+
activePoints = resizeOriginPoint.map(p => {
|
|
4068
|
+
return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom);
|
|
4069
|
+
});
|
|
4070
|
+
if (angle) {
|
|
4071
|
+
activePoints = resetPointsAfterResize(RectangleClient.getRectangleByPoints(resizeOriginPoint), RectangleClient.getRectangleByPoints(activePoints), RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(resizeOriginPoint)), RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(activePoints)), angle);
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
return {
|
|
4075
|
+
xZoom,
|
|
4076
|
+
yZoom,
|
|
4077
|
+
activePoints
|
|
4078
|
+
};
|
|
4079
|
+
}
|
|
4080
|
+
function getIsometricLineDelta(snapRectangles, resizeSnapOptions) {
|
|
4081
|
+
let isometricLineDelta = {
|
|
4082
|
+
deltaX: 0,
|
|
4083
|
+
deltaY: 0
|
|
4084
|
+
};
|
|
4085
|
+
const { isAspectRatio, activeRectangle } = resizeSnapOptions;
|
|
4086
|
+
const widthSnapRectangle = snapRectangles.find(item => Math.abs(item.width - activeRectangle.width) < SNAP_TOLERANCE);
|
|
4087
|
+
if (widthSnapRectangle) {
|
|
4088
|
+
const deltaWidth = widthSnapRectangle.width - activeRectangle.width;
|
|
4089
|
+
isometricLineDelta.deltaX = deltaWidth * resizeSnapOptions.directionFactors[0];
|
|
4090
|
+
if (isAspectRatio) {
|
|
4091
|
+
const deltaHeight = deltaWidth / (activeRectangle.width / activeRectangle.height);
|
|
4092
|
+
isometricLineDelta.deltaY = deltaHeight * resizeSnapOptions.directionFactors[1];
|
|
4093
|
+
return isometricLineDelta;
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
const heightSnapRectangle = snapRectangles.find(item => Math.abs(item.height - activeRectangle.height) < SNAP_TOLERANCE);
|
|
4097
|
+
if (heightSnapRectangle) {
|
|
4098
|
+
const deltaHeight = heightSnapRectangle.height - activeRectangle.height;
|
|
4099
|
+
isometricLineDelta.deltaY = deltaHeight * resizeSnapOptions.directionFactors[1];
|
|
4100
|
+
if (isAspectRatio) {
|
|
4101
|
+
const deltaWidth = deltaHeight * (activeRectangle.width / activeRectangle.height);
|
|
4102
|
+
isometricLineDelta.deltaX = deltaWidth * resizeSnapOptions.directionFactors[0];
|
|
4103
|
+
return isometricLineDelta;
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
return isometricLineDelta;
|
|
4107
|
+
}
|
|
4108
|
+
function getIsometricLinePoints(rectangle, isHorizontal) {
|
|
4109
|
+
return isHorizontal
|
|
4110
|
+
? [
|
|
4111
|
+
[rectangle.x, rectangle.y - EQUAL_SPACING],
|
|
4112
|
+
[rectangle.x + rectangle.width, rectangle.y - EQUAL_SPACING]
|
|
4113
|
+
]
|
|
4114
|
+
: [
|
|
4115
|
+
[rectangle.x - EQUAL_SPACING, rectangle.y],
|
|
4116
|
+
[rectangle.x - EQUAL_SPACING, rectangle.y + rectangle.height]
|
|
4117
|
+
];
|
|
4118
|
+
}
|
|
4119
|
+
function drawResizingPointSnapLines(board, activePoints, snapRectangles, resizeSnapOptions, angle) {
|
|
4120
|
+
debugGenerator.isDebug() && debugGenerator.clear();
|
|
4121
|
+
const activeRectangle = getRectangleByAngle(RectangleClient.getRectangleByPoints(activePoints), angle) ||
|
|
4122
|
+
RectangleClient.getRectangleByPoints(activePoints);
|
|
4123
|
+
const { isAspectRatio, directionFactors } = resizeSnapOptions;
|
|
4124
|
+
const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
|
|
4125
|
+
const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
|
|
4126
|
+
return drawPointSnapLines(board, activeRectangle, snapRectangles, drawHorizontal, drawVertical);
|
|
4127
|
+
}
|
|
4128
|
+
function drawIsometricSnapLines(board, activePoints, snapRectangles, resizeSnapOptions, angle) {
|
|
4129
|
+
let widthIsometricPoints = [];
|
|
4130
|
+
let heightIsometricPoints = [];
|
|
4131
|
+
const drawHorizontalLine = resizeSnapOptions.directionFactors[0] !== 0 || resizeSnapOptions.isAspectRatio;
|
|
4132
|
+
const drawVerticalLine = resizeSnapOptions.directionFactors[1] !== 0 || resizeSnapOptions.isAspectRatio;
|
|
4133
|
+
const activeRectangle = getRectangleByAngle(RectangleClient.getRectangleByPoints(activePoints), angle) ||
|
|
4134
|
+
RectangleClient.getRectangleByPoints(activePoints);
|
|
4135
|
+
for (let snapRectangle of snapRectangles) {
|
|
4136
|
+
if (activeRectangle.width === snapRectangle.width && drawHorizontalLine) {
|
|
4137
|
+
widthIsometricPoints.push(getIsometricLinePoints(snapRectangle, true));
|
|
4138
|
+
}
|
|
4139
|
+
if (activeRectangle.height === snapRectangle.height && drawVerticalLine) {
|
|
4140
|
+
heightIsometricPoints.push(getIsometricLinePoints(snapRectangle, false));
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
if (widthIsometricPoints.length && drawHorizontalLine) {
|
|
4144
|
+
widthIsometricPoints.push(getIsometricLinePoints(activeRectangle, true));
|
|
4145
|
+
}
|
|
4146
|
+
if (heightIsometricPoints.length && drawVerticalLine) {
|
|
4147
|
+
heightIsometricPoints.push(getIsometricLinePoints(activeRectangle, false));
|
|
4148
|
+
}
|
|
4149
|
+
const isometricLines = [...widthIsometricPoints, ...heightIsometricPoints];
|
|
4150
|
+
return drawSolidLines(board, isometricLines);
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4153
|
+
const withGeometryCreateByDrag = (board) => {
|
|
4154
|
+
const { pointerMove, globalPointerUp } = board;
|
|
4155
|
+
let geometryShapeG = null;
|
|
4156
|
+
let temporaryElement = null;
|
|
4157
|
+
let fakeCreateTextRef = null;
|
|
4158
|
+
board.pointerMove = (event) => {
|
|
4159
|
+
geometryShapeG?.remove();
|
|
4160
|
+
geometryShapeG = createG();
|
|
4161
|
+
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
4162
|
+
const geometryPointers = getGeometryPointers();
|
|
4163
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
4164
|
+
const dragMode = isGeometryPointer && isDndMode(board);
|
|
4165
|
+
const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
4166
|
+
const pointer = PlaitBoard.getPointer(board);
|
|
4167
|
+
if (dragMode) {
|
|
4168
|
+
const memorizedLatest = getMemorizedLatestByPointer(pointer);
|
|
4169
|
+
if (pointer === BasicShapes.text) {
|
|
4170
|
+
const property = getTextShapeProperty(board, DefaultTextProperty.text, memorizedLatest.textProperties['font-size']);
|
|
4171
|
+
const points = RectangleClient.getPoints(RectangleClient.getRectangleByCenterPoint(movingPoint, property.width, property.height));
|
|
4172
|
+
temporaryElement = createTextElement(board, points);
|
|
4173
|
+
if (!fakeCreateTextRef) {
|
|
4174
|
+
const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, {
|
|
4175
|
+
getRectangle: () => {
|
|
4176
|
+
return getTextRectangle(temporaryElement);
|
|
4177
|
+
}
|
|
4178
|
+
});
|
|
4179
|
+
PlaitBoard.getComponent(board)
|
|
4180
|
+
.viewContainerRef.injector.get(NgZone)
|
|
4181
|
+
.run(() => {
|
|
4182
|
+
textManage.draw(temporaryElement.text);
|
|
4183
|
+
});
|
|
4184
|
+
fakeCreateTextRef = {
|
|
4185
|
+
g: createG(),
|
|
4186
|
+
textManage
|
|
4187
|
+
};
|
|
4188
|
+
PlaitBoard.getHost(board).append(fakeCreateTextRef.g);
|
|
4189
|
+
fakeCreateTextRef.g.append(textManage.g);
|
|
4190
|
+
}
|
|
4191
|
+
else {
|
|
4192
|
+
fakeCreateTextRef.textManage.updateRectangle();
|
|
4193
|
+
fakeCreateTextRef.g.append(fakeCreateTextRef.textManage.g);
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
else {
|
|
4197
|
+
const points = getDefaultGeometryPoints(pointer, movingPoint);
|
|
4198
|
+
temporaryElement = createDefaultGeometry(board, points, pointer);
|
|
4199
|
+
geometryGenerator.processDrawing(temporaryElement, geometryShapeG);
|
|
4200
|
+
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
pointerMove(event);
|
|
3520
4204
|
};
|
|
3521
4205
|
board.globalPointerUp = (event) => {
|
|
3522
4206
|
const geometryPointers = getGeometryPointers();
|
|
@@ -3541,6 +4225,7 @@ const withGeometryCreateByDrawing = (board) => {
|
|
|
3541
4225
|
let geometryShapeG = null;
|
|
3542
4226
|
let temporaryElement = null;
|
|
3543
4227
|
let isShift = false;
|
|
4228
|
+
let snapG;
|
|
3544
4229
|
board.keyDown = (event) => {
|
|
3545
4230
|
isShift = isKeyHotkey('shift', event);
|
|
3546
4231
|
keyDown(event);
|
|
@@ -3572,11 +4257,24 @@ const withGeometryCreateByDrawing = (board) => {
|
|
|
3572
4257
|
geometryShapeG?.remove();
|
|
3573
4258
|
geometryShapeG = createG();
|
|
3574
4259
|
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
3575
|
-
const drawMode = !!start;
|
|
3576
4260
|
const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
3577
4261
|
const pointer = PlaitBoard.getPointer(board);
|
|
3578
|
-
|
|
3579
|
-
|
|
4262
|
+
snapG?.remove();
|
|
4263
|
+
if (start && pointer !== BasicShapes.text) {
|
|
4264
|
+
let points = normalizeShapePoints([start, movingPoint], isShift);
|
|
4265
|
+
const activeRectangle = RectangleClient.getRectangleByPoints(points);
|
|
4266
|
+
const [x, y] = getUnitVectorByPointAndPoint(start, movingPoint);
|
|
4267
|
+
const resizeSnapRef = getSnapResizingRef(board, [], {
|
|
4268
|
+
resizePoints: points,
|
|
4269
|
+
activeRectangle,
|
|
4270
|
+
directionFactors: [getDirectionFactorByDirectionComponent(x), getDirectionFactorByDirectionComponent(y)],
|
|
4271
|
+
isAspectRatio: isShift,
|
|
4272
|
+
isFromCorner: true,
|
|
4273
|
+
isCreate: true
|
|
4274
|
+
});
|
|
4275
|
+
snapG = resizeSnapRef.snapG;
|
|
4276
|
+
PlaitBoard.getElementActiveHost(board).append(snapG);
|
|
4277
|
+
points = normalizeShapePoints(resizeSnapRef.activePoints, isShift);
|
|
3580
4278
|
temporaryElement = createDefaultGeometry(board, points, pointer);
|
|
3581
4279
|
geometryGenerator.processDrawing(temporaryElement, geometryShapeG);
|
|
3582
4280
|
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
@@ -3599,6 +4297,7 @@ const withGeometryCreateByDrawing = (board) => {
|
|
|
3599
4297
|
if (temporaryElement) {
|
|
3600
4298
|
insertElement(board, temporaryElement);
|
|
3601
4299
|
}
|
|
4300
|
+
snapG?.remove();
|
|
3602
4301
|
geometryShapeG?.remove();
|
|
3603
4302
|
geometryShapeG = null;
|
|
3604
4303
|
start = null;
|
|
@@ -3670,7 +4369,7 @@ const insertClipboardData = (board, elements, startPoint) => {
|
|
|
3670
4369
|
|
|
3671
4370
|
const withDrawFragment = (baseBoard) => {
|
|
3672
4371
|
const board = baseBoard;
|
|
3673
|
-
const { getDeletedFragment,
|
|
4372
|
+
const { getDeletedFragment, buildFragment, insertFragment } = board;
|
|
3674
4373
|
board.getDeletedFragment = (data) => {
|
|
3675
4374
|
const drawElements = getSelectedDrawElements(board);
|
|
3676
4375
|
if (drawElements.length) {
|
|
@@ -3690,7 +4389,7 @@ const withDrawFragment = (baseBoard) => {
|
|
|
3690
4389
|
}
|
|
3691
4390
|
return getDeletedFragment(data);
|
|
3692
4391
|
};
|
|
3693
|
-
board.
|
|
4392
|
+
board.buildFragment = (clipboardContext, rectangle, type) => {
|
|
3694
4393
|
const targetDrawElements = getSelectedDrawElements(board);
|
|
3695
4394
|
let boundLineElements = [];
|
|
3696
4395
|
if (targetDrawElements.length) {
|
|
@@ -3699,655 +4398,111 @@ const withDrawFragment = (baseBoard) => {
|
|
|
3699
4398
|
const lineElements = targetDrawElements.filter(value => PlaitDrawElement.isLine(value));
|
|
3700
4399
|
boundLineElements = getBoundedLineElements(board, geometryElements).filter(line => !lineElements.includes(line));
|
|
3701
4400
|
}
|
|
3702
|
-
const selectedElements = [...targetDrawElements, ...boundLineElements];
|
|
3703
|
-
const elements = buildClipboardData(board, selectedElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
|
|
3704
|
-
const text = getElementsText(selectedElements);
|
|
3705
|
-
if (!clipboardContext) {
|
|
3706
|
-
clipboardContext = createClipboardContext(WritableClipboardType.elements, elements, text);
|
|
3707
|
-
}
|
|
3708
|
-
else {
|
|
3709
|
-
clipboardContext = addClipboardContext(clipboardContext, {
|
|
3710
|
-
text,
|
|
3711
|
-
type: WritableClipboardType.elements,
|
|
3712
|
-
|
|
3713
|
-
});
|
|
3714
|
-
}
|
|
3715
|
-
}
|
|
3716
|
-
setFragment(data, clipboardContext, rectangle, type);
|
|
3717
|
-
};
|
|
3718
|
-
board.insertFragment = (data, clipboardData, targetPoint) => {
|
|
3719
|
-
const selectedElements = getSelectedElements(board);
|
|
3720
|
-
if (clipboardData?.files?.length) {
|
|
3721
|
-
const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
|
|
3722
|
-
const canInsertionImage = !getElementOfFocusedImage(board) && !(selectedElements.length === 1 && board.isImageBindingAllowed(selectedElements[0]));
|
|
3723
|
-
if (acceptImageArray.includes(clipboardData.files[0].type) && canInsertionImage) {
|
|
3724
|
-
const imageFile = clipboardData.files[0];
|
|
3725
|
-
buildImage(board, imageFile, DEFAULT_IMAGE_WIDTH, imageItem => {
|
|
3726
|
-
DrawTransforms.insertImage(board, imageItem, targetPoint);
|
|
3727
|
-
});
|
|
3728
|
-
return;
|
|
3729
|
-
}
|
|
3730
|
-
}
|
|
3731
|
-
if (clipboardData?.elements?.length) {
|
|
3732
|
-
const drawElements = clipboardData.elements?.filter(value => PlaitDrawElement.isDrawElement(value));
|
|
3733
|
-
if (clipboardData.elements && clipboardData.elements.length > 0 && drawElements.length > 0) {
|
|
3734
|
-
insertClipboardData(board, drawElements, targetPoint);
|
|
3735
|
-
}
|
|
3736
|
-
}
|
|
3737
|
-
if (clipboardData?.text) {
|
|
3738
|
-
if (!clipboardData.elements || clipboardData.elements.length === 0) {
|
|
3739
|
-
// (* ̄︶ ̄)
|
|
3740
|
-
const insertAsChildren = selectedElements.length === 1 && selectedElements[0].children;
|
|
3741
|
-
const insertAsFreeText = !insertAsChildren;
|
|
3742
|
-
if (insertAsFreeText) {
|
|
3743
|
-
DrawTransforms.insertText(board, targetPoint, clipboardData.text);
|
|
3744
|
-
return;
|
|
3745
|
-
}
|
|
3746
|
-
}
|
|
3747
|
-
}
|
|
3748
|
-
insertFragment(data, clipboardData, targetPoint);
|
|
3749
|
-
};
|
|
3750
|
-
return board;
|
|
3751
|
-
};
|
|
3752
|
-
const getBoundedLineElements = (board, plaitShapes) => {
|
|
3753
|
-
const lines = getLines(board);
|
|
3754
|
-
return lines.filter(line => plaitShapes.find(shape => PlaitLine.isBoundElementOfSource(line, shape) || PlaitLine.isBoundElementOfTarget(line, shape)));
|
|
3755
|
-
};
|
|
3756
|
-
|
|
3757
|
-
const withLineCreateByDraw = (board) => {
|
|
3758
|
-
const { pointerDown, pointerMove, globalPointerUp } = board;
|
|
3759
|
-
let start = null;
|
|
3760
|
-
let sourceElement;
|
|
3761
|
-
let lineShapeG = null;
|
|
3762
|
-
let temporaryElement = null;
|
|
3763
|
-
board.pointerDown = (event) => {
|
|
3764
|
-
const linePointers = getLinePointers();
|
|
3765
|
-
const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
|
|
3766
|
-
if (!PlaitBoard.isReadonly(board) && isLinePointer && isDrawingMode(board)) {
|
|
3767
|
-
const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
3768
|
-
start = point;
|
|
3769
|
-
const hitElement = getHitOutlineGeometry(board, point, REACTION_MARGIN);
|
|
3770
|
-
if (hitElement) {
|
|
3771
|
-
sourceElement = hitElement;
|
|
3772
|
-
}
|
|
3773
|
-
preventTouchMove(board, event, true);
|
|
3774
|
-
}
|
|
3775
|
-
pointerDown(event);
|
|
3776
|
-
};
|
|
3777
|
-
board.pointerMove = (event) => {
|
|
3778
|
-
lineShapeG?.remove();
|
|
3779
|
-
lineShapeG = createG();
|
|
3780
|
-
let movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
3781
|
-
if (start) {
|
|
3782
|
-
const lineShape = PlaitBoard.getPointer(board);
|
|
3783
|
-
temporaryElement = handleLineCreating(board, lineShape, start, movingPoint, sourceElement, lineShapeG);
|
|
3784
|
-
}
|
|
3785
|
-
pointerMove(event);
|
|
3786
|
-
};
|
|
3787
|
-
board.globalPointerUp = (event) => {
|
|
3788
|
-
if (temporaryElement) {
|
|
3789
|
-
Transforms.insertNode(board, temporaryElement, [board.children.length]);
|
|
3790
|
-
clearSelectedElement(board);
|
|
3791
|
-
addSelectedElement(board, temporaryElement);
|
|
3792
|
-
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
3793
|
-
}
|
|
3794
|
-
lineShapeG?.remove();
|
|
3795
|
-
lineShapeG = null;
|
|
3796
|
-
sourceElement = null;
|
|
3797
|
-
start = null;
|
|
3798
|
-
temporaryElement = null;
|
|
3799
|
-
preventTouchMove(board, event, false);
|
|
3800
|
-
globalPointerUp(event);
|
|
3801
|
-
};
|
|
3802
|
-
return board;
|
|
3803
|
-
};
|
|
3804
|
-
|
|
3805
|
-
const ALIGN_TOLERANCE = 2;
|
|
3806
|
-
const EQUAL_SPACING = 10;
|
|
3807
|
-
const ALIGN_SPACING = 24;
|
|
3808
|
-
class ResizeAlignReaction {
|
|
3809
|
-
constructor(board, activeElements) {
|
|
3810
|
-
this.board = board;
|
|
3811
|
-
this.activeElements = activeElements;
|
|
3812
|
-
this.alignRectangles = this.getAlignRectangle();
|
|
3813
|
-
}
|
|
3814
|
-
getAlignRectangle() {
|
|
3815
|
-
const elements = findElements(this.board, {
|
|
3816
|
-
match: element => this.board.isAlign(element) && !this.activeElements.some(item => item.id === element.id),
|
|
3817
|
-
recursion: () => false,
|
|
3818
|
-
isReverse: false
|
|
3819
|
-
});
|
|
3820
|
-
return elements.map(item => this.board.getRectangle(item));
|
|
3821
|
-
}
|
|
3822
|
-
getAlignLineRef(resizeAlignDelta, resizeAlignOptions) {
|
|
3823
|
-
const { deltaX, deltaY } = resizeAlignDelta;
|
|
3824
|
-
const { resizeState, originPoint, handlePoint, isFromCorner, isAspectRatio, resizeOriginPoints } = resizeAlignOptions;
|
|
3825
|
-
const newResizeState = {
|
|
3826
|
-
...resizeState,
|
|
3827
|
-
endPoint: [resizeState.endPoint[0] + deltaX, resizeState.endPoint[1] + deltaY]
|
|
3828
|
-
};
|
|
3829
|
-
const { xZoom, yZoom } = getResizeZoom(newResizeState, originPoint, handlePoint, isFromCorner, isAspectRatio);
|
|
3830
|
-
const activePoints = resizeOriginPoints.map(p => {
|
|
3831
|
-
return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom);
|
|
3832
|
-
});
|
|
3833
|
-
return {
|
|
3834
|
-
deltaX,
|
|
3835
|
-
deltaY,
|
|
3836
|
-
xZoom,
|
|
3837
|
-
yZoom,
|
|
3838
|
-
activePoints
|
|
3839
|
-
};
|
|
3840
|
-
}
|
|
3841
|
-
getEqualLineDelta(resizeAlignOptions) {
|
|
3842
|
-
let equalLineDelta = {
|
|
3843
|
-
deltaX: 0,
|
|
3844
|
-
deltaY: 0
|
|
3845
|
-
};
|
|
3846
|
-
const { isAspectRatio, activeRectangle } = resizeAlignOptions;
|
|
3847
|
-
const widthAlignRectangle = this.alignRectangles.find(item => Math.abs(item.width - activeRectangle.width) < ALIGN_TOLERANCE);
|
|
3848
|
-
if (widthAlignRectangle) {
|
|
3849
|
-
const deltaWidth = widthAlignRectangle.width - activeRectangle.width;
|
|
3850
|
-
equalLineDelta.deltaX = deltaWidth * resizeAlignOptions.directionFactors[0];
|
|
3851
|
-
if (isAspectRatio) {
|
|
3852
|
-
const deltaHeight = deltaWidth / (activeRectangle.width / activeRectangle.height);
|
|
3853
|
-
equalLineDelta.deltaY = deltaHeight * resizeAlignOptions.directionFactors[1];
|
|
3854
|
-
return equalLineDelta;
|
|
3855
|
-
}
|
|
3856
|
-
}
|
|
3857
|
-
const heightAlignRectangle = this.alignRectangles.find(item => Math.abs(item.height - activeRectangle.height) < ALIGN_TOLERANCE);
|
|
3858
|
-
if (heightAlignRectangle) {
|
|
3859
|
-
const deltaHeight = heightAlignRectangle.height - activeRectangle.height;
|
|
3860
|
-
equalLineDelta.deltaY = deltaHeight * resizeAlignOptions.directionFactors[1];
|
|
3861
|
-
if (isAspectRatio) {
|
|
3862
|
-
const deltaWidth = deltaHeight * (activeRectangle.width / activeRectangle.height);
|
|
3863
|
-
equalLineDelta.deltaX = deltaWidth * resizeAlignOptions.directionFactors[0];
|
|
3864
|
-
return equalLineDelta;
|
|
3865
|
-
}
|
|
3866
|
-
}
|
|
3867
|
-
return equalLineDelta;
|
|
3868
|
-
}
|
|
3869
|
-
drawEqualLines(activePoints, resizeAlignOptions) {
|
|
3870
|
-
let widthEqualPoints = [];
|
|
3871
|
-
let heightEqualPoints = [];
|
|
3872
|
-
const drawHorizontalLine = resizeAlignOptions.directionFactors[0] !== 0 || resizeAlignOptions.isAspectRatio;
|
|
3873
|
-
const drawVerticalLine = resizeAlignOptions.directionFactors[1] !== 0 || resizeAlignOptions.isAspectRatio;
|
|
3874
|
-
const activeRectangle = RectangleClient.getRectangleByPoints(activePoints);
|
|
3875
|
-
for (let alignRectangle of this.alignRectangles) {
|
|
3876
|
-
if (activeRectangle.width === alignRectangle.width && drawHorizontalLine) {
|
|
3877
|
-
widthEqualPoints.push(getEqualLinePoints(alignRectangle, true));
|
|
3878
|
-
}
|
|
3879
|
-
if (activeRectangle.height === alignRectangle.height && drawVerticalLine) {
|
|
3880
|
-
heightEqualPoints.push(getEqualLinePoints(alignRectangle, false));
|
|
3881
|
-
}
|
|
3882
|
-
}
|
|
3883
|
-
if (widthEqualPoints.length && drawHorizontalLine) {
|
|
3884
|
-
widthEqualPoints.push(getEqualLinePoints(activeRectangle, true));
|
|
3885
|
-
}
|
|
3886
|
-
if (heightEqualPoints.length && drawVerticalLine) {
|
|
3887
|
-
heightEqualPoints.push(getEqualLinePoints(activeRectangle, false));
|
|
3888
|
-
}
|
|
3889
|
-
const equalLinePoints = [...widthEqualPoints, ...heightEqualPoints];
|
|
3890
|
-
return drawEqualLines(this.board, equalLinePoints);
|
|
3891
|
-
}
|
|
3892
|
-
getAlignLineDelta(resizeAlignOptions) {
|
|
3893
|
-
let alignLineDelta = {
|
|
3894
|
-
deltaX: 0,
|
|
3895
|
-
deltaY: 0
|
|
3896
|
-
};
|
|
3897
|
-
const { isAspectRatio, activeRectangle, directionFactors } = resizeAlignOptions;
|
|
3898
|
-
const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
|
|
3899
|
-
const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
|
|
3900
|
-
if (drawHorizontal) {
|
|
3901
|
-
const xAlignAxis = getTripleAlignAxis(activeRectangle, true);
|
|
3902
|
-
const alignX = directionFactors[0] === -1 ? xAlignAxis[0] : xAlignAxis[2];
|
|
3903
|
-
const deltaX = getMinAlignDelta(this.alignRectangles, alignX, true);
|
|
3904
|
-
if (Math.abs(deltaX) < ALIGN_TOLERANCE) {
|
|
3905
|
-
alignLineDelta.deltaX = deltaX;
|
|
3906
|
-
if (alignLineDelta.deltaX !== 0 && isAspectRatio) {
|
|
3907
|
-
alignLineDelta.deltaY = alignLineDelta.deltaX / (activeRectangle.width / activeRectangle.height);
|
|
3908
|
-
return alignLineDelta;
|
|
3909
|
-
}
|
|
3910
|
-
}
|
|
3911
|
-
}
|
|
3912
|
-
if (drawVertical) {
|
|
3913
|
-
const yAlignAxis = getTripleAlignAxis(activeRectangle, false);
|
|
3914
|
-
const alignY = directionFactors[1] === -1 ? yAlignAxis[0] : yAlignAxis[2];
|
|
3915
|
-
const deltaY = getMinAlignDelta(this.alignRectangles, alignY, false);
|
|
3916
|
-
if (Math.abs(deltaY) < ALIGN_TOLERANCE) {
|
|
3917
|
-
alignLineDelta.deltaY = deltaY;
|
|
3918
|
-
if (alignLineDelta.deltaY !== 0 && isAspectRatio) {
|
|
3919
|
-
alignLineDelta.deltaX = alignLineDelta.deltaY * (activeRectangle.width / activeRectangle.height);
|
|
3920
|
-
return alignLineDelta;
|
|
3921
|
-
}
|
|
3922
|
-
}
|
|
3923
|
-
}
|
|
3924
|
-
return alignLineDelta;
|
|
3925
|
-
}
|
|
3926
|
-
drawAlignLines(activePoints, resizeAlignOptions) {
|
|
3927
|
-
let alignLinePoints = [];
|
|
3928
|
-
const activeRectangle = RectangleClient.getRectangleByPoints(activePoints);
|
|
3929
|
-
const alignAxisX = getTripleAlignAxis(activeRectangle, true);
|
|
3930
|
-
const alignAxisY = getTripleAlignAxis(activeRectangle, false);
|
|
3931
|
-
const alignLineRefs = [
|
|
3932
|
-
{
|
|
3933
|
-
axis: alignAxisX[0],
|
|
3934
|
-
isHorizontal: true,
|
|
3935
|
-
alignRectangles: []
|
|
3936
|
-
},
|
|
3937
|
-
{
|
|
3938
|
-
axis: alignAxisX[2],
|
|
3939
|
-
isHorizontal: true,
|
|
3940
|
-
alignRectangles: []
|
|
3941
|
-
},
|
|
3942
|
-
{
|
|
3943
|
-
axis: alignAxisY[0],
|
|
3944
|
-
isHorizontal: false,
|
|
3945
|
-
alignRectangles: []
|
|
3946
|
-
},
|
|
3947
|
-
{
|
|
3948
|
-
axis: alignAxisY[2],
|
|
3949
|
-
isHorizontal: false,
|
|
3950
|
-
alignRectangles: []
|
|
3951
|
-
}
|
|
3952
|
-
];
|
|
3953
|
-
const setAlignLine = (axis, alignRectangle, isHorizontal) => {
|
|
3954
|
-
const boundingRectangle = RectangleClient.inflate(RectangleClient.getBoundingRectangle([activeRectangle, alignRectangle]), ALIGN_SPACING);
|
|
3955
|
-
if (isHorizontal) {
|
|
3956
|
-
const pointStart = [axis, boundingRectangle.y];
|
|
3957
|
-
const pointEnd = [axis, boundingRectangle.y + boundingRectangle.height];
|
|
3958
|
-
alignLinePoints.push([pointStart, pointEnd]);
|
|
3959
|
-
}
|
|
3960
|
-
else {
|
|
3961
|
-
const pointStart = [boundingRectangle.x, axis];
|
|
3962
|
-
const pointEnd = [boundingRectangle.x + boundingRectangle.width, axis];
|
|
3963
|
-
alignLinePoints.push([pointStart, pointEnd]);
|
|
3964
|
-
}
|
|
3965
|
-
};
|
|
3966
|
-
const { isAspectRatio, directionFactors } = resizeAlignOptions;
|
|
3967
|
-
const drawHorizontal = directionFactors[0] !== 0 || isAspectRatio;
|
|
3968
|
-
const drawVertical = directionFactors[1] !== 0 || isAspectRatio;
|
|
3969
|
-
for (let index = 0; index < this.alignRectangles.length; index++) {
|
|
3970
|
-
const element = this.alignRectangles[index];
|
|
3971
|
-
if (isAlign(alignLineRefs[0].axis, element, alignLineRefs[0].isHorizontal)) {
|
|
3972
|
-
alignLineRefs[0].alignRectangles.push(element);
|
|
3973
|
-
}
|
|
3974
|
-
if (isAlign(alignLineRefs[1].axis, element, alignLineRefs[1].isHorizontal)) {
|
|
3975
|
-
alignLineRefs[1].alignRectangles.push(element);
|
|
3976
|
-
}
|
|
3977
|
-
if (isAlign(alignLineRefs[2].axis, element, alignLineRefs[2].isHorizontal)) {
|
|
3978
|
-
alignLineRefs[2].alignRectangles.push(element);
|
|
3979
|
-
}
|
|
3980
|
-
if (isAlign(alignLineRefs[3].axis, element, alignLineRefs[3].isHorizontal)) {
|
|
3981
|
-
alignLineRefs[3].alignRectangles.push(element);
|
|
3982
|
-
}
|
|
3983
|
-
}
|
|
3984
|
-
if (drawHorizontal && alignLineRefs[0].alignRectangles.length) {
|
|
3985
|
-
const leftRectangle = alignLineRefs[0].alignRectangles.length === 1
|
|
3986
|
-
? alignLineRefs[0].alignRectangles[0]
|
|
3987
|
-
: getNearestAlignRectangle(alignLineRefs[0].alignRectangles, activeRectangle);
|
|
3988
|
-
setAlignLine(alignLineRefs[0].axis, leftRectangle, alignLineRefs[0].isHorizontal);
|
|
3989
|
-
}
|
|
3990
|
-
if (drawHorizontal && alignLineRefs[1].alignRectangles.length) {
|
|
3991
|
-
const rightRectangle = alignLineRefs[1].alignRectangles.length === 1
|
|
3992
|
-
? alignLineRefs[1].alignRectangles[0]
|
|
3993
|
-
: getNearestAlignRectangle(alignLineRefs[1].alignRectangles, activeRectangle);
|
|
3994
|
-
setAlignLine(alignLineRefs[1].axis, rightRectangle, alignLineRefs[1].isHorizontal);
|
|
3995
|
-
}
|
|
3996
|
-
if (drawVertical && alignLineRefs[2].alignRectangles.length) {
|
|
3997
|
-
const topRectangle = alignLineRefs[2].alignRectangles.length === 1
|
|
3998
|
-
? alignLineRefs[2].alignRectangles[0]
|
|
3999
|
-
: getNearestAlignRectangle(alignLineRefs[2].alignRectangles, activeRectangle);
|
|
4000
|
-
setAlignLine(alignLineRefs[2].axis, topRectangle, alignLineRefs[2].isHorizontal);
|
|
4001
|
-
}
|
|
4002
|
-
if (drawVertical && alignLineRefs[3].alignRectangles.length) {
|
|
4003
|
-
const bottomRectangle = alignLineRefs[3].alignRectangles.length === 1
|
|
4004
|
-
? alignLineRefs[3].alignRectangles[0]
|
|
4005
|
-
: getNearestAlignRectangle(alignLineRefs[3].alignRectangles, activeRectangle);
|
|
4006
|
-
setAlignLine(alignLineRefs[3].axis, bottomRectangle, alignLineRefs[3].isHorizontal);
|
|
4007
|
-
}
|
|
4008
|
-
return drawAlignLines(this.board, alignLinePoints);
|
|
4009
|
-
}
|
|
4010
|
-
handleResizeAlign(resizeAlignOptions) {
|
|
4011
|
-
const alignG = createG();
|
|
4012
|
-
let alignLineDelta = this.getEqualLineDelta(resizeAlignOptions);
|
|
4013
|
-
if (alignLineDelta.deltaX === 0 && alignLineDelta.deltaY === 0) {
|
|
4014
|
-
alignLineDelta = this.getAlignLineDelta(resizeAlignOptions);
|
|
4015
|
-
}
|
|
4016
|
-
const equalLineRef = this.getAlignLineRef(alignLineDelta, resizeAlignOptions);
|
|
4017
|
-
const equalLinesG = this.drawEqualLines(equalLineRef.activePoints, resizeAlignOptions);
|
|
4018
|
-
const alignLinesG = this.drawAlignLines(equalLineRef.activePoints, resizeAlignOptions);
|
|
4019
|
-
alignG.append(equalLinesG, alignLinesG);
|
|
4020
|
-
return { ...equalLineRef, alignG };
|
|
4021
|
-
}
|
|
4022
|
-
}
|
|
4023
|
-
function getBarPoint(point, isHorizontal) {
|
|
4024
|
-
return isHorizontal
|
|
4025
|
-
? [
|
|
4026
|
-
[point[0], point[1] - 4],
|
|
4027
|
-
[point[0], point[1] + 4]
|
|
4028
|
-
]
|
|
4029
|
-
: [
|
|
4030
|
-
[point[0] - 4, point[1]],
|
|
4031
|
-
[point[0] + 4, point[1]]
|
|
4032
|
-
];
|
|
4033
|
-
}
|
|
4034
|
-
function getEqualLinePoints(rectangle, isHorizontal) {
|
|
4035
|
-
return isHorizontal
|
|
4036
|
-
? [
|
|
4037
|
-
[rectangle.x, rectangle.y - EQUAL_SPACING],
|
|
4038
|
-
[rectangle.x + rectangle.width, rectangle.y - EQUAL_SPACING]
|
|
4039
|
-
]
|
|
4040
|
-
: [
|
|
4041
|
-
[rectangle.x - EQUAL_SPACING, rectangle.y],
|
|
4042
|
-
[rectangle.x - EQUAL_SPACING, rectangle.y + rectangle.height]
|
|
4043
|
-
];
|
|
4044
|
-
}
|
|
4045
|
-
function drawEqualLines(board, lines) {
|
|
4046
|
-
const g = createG();
|
|
4047
|
-
lines.forEach(line => {
|
|
4048
|
-
if (!line.length)
|
|
4049
|
-
return;
|
|
4050
|
-
const yAlign = PlaitBoard.getRoughSVG(board).line(line[0][0], line[0][1], line[1][0], line[1][1], {
|
|
4051
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
4052
|
-
strokeWidth: 1
|
|
4053
|
-
});
|
|
4054
|
-
g.appendChild(yAlign);
|
|
4055
|
-
line.forEach(point => {
|
|
4056
|
-
const barPoint = getBarPoint(point, !!Point.isHorizontal(line[0], line[1]));
|
|
4057
|
-
const bar = PlaitBoard.getRoughSVG(board).line(barPoint[0][0], barPoint[0][1], barPoint[1][0], barPoint[1][1], {
|
|
4058
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
4059
|
-
strokeWidth: 1
|
|
4060
|
-
});
|
|
4061
|
-
g.appendChild(bar);
|
|
4062
|
-
});
|
|
4063
|
-
});
|
|
4064
|
-
return g;
|
|
4065
|
-
}
|
|
4066
|
-
function drawAlignLines(board, lines) {
|
|
4067
|
-
const g = createG();
|
|
4068
|
-
lines.forEach(points => {
|
|
4069
|
-
if (!points.length)
|
|
4070
|
-
return;
|
|
4071
|
-
const xAlign = PlaitBoard.getRoughSVG(board).line(points[0][0], points[0][1], points[1][0], points[1][1], {
|
|
4072
|
-
stroke: SELECTION_BORDER_COLOR,
|
|
4073
|
-
strokeWidth: 1,
|
|
4074
|
-
strokeLineDash: [4, 4]
|
|
4075
|
-
});
|
|
4076
|
-
g.appendChild(xAlign);
|
|
4077
|
-
});
|
|
4078
|
-
return g;
|
|
4079
|
-
}
|
|
4080
|
-
const getTripleAlignAxis = (rectangle, isHorizontal) => {
|
|
4081
|
-
const axis = isHorizontal ? 'x' : 'y';
|
|
4082
|
-
const side = isHorizontal ? 'width' : 'height';
|
|
4083
|
-
return [rectangle[axis], rectangle[axis] + rectangle[side] / 2, rectangle[axis] + rectangle[side]];
|
|
4084
|
-
};
|
|
4085
|
-
const isAlign = (axis, rectangle, isHorizontal) => {
|
|
4086
|
-
const alignAxis = getTripleAlignAxis(rectangle, isHorizontal);
|
|
4087
|
-
return alignAxis.includes(axis);
|
|
4088
|
-
};
|
|
4089
|
-
const getClosestDelta = (axis, rectangle, isHorizontal) => {
|
|
4090
|
-
const alignAxis = getTripleAlignAxis(rectangle, isHorizontal);
|
|
4091
|
-
const deltas = alignAxis.map(item => item - axis);
|
|
4092
|
-
const absDeltas = deltas.map(item => Math.abs(item));
|
|
4093
|
-
const index = absDeltas.indexOf(Math.min(...absDeltas));
|
|
4094
|
-
return deltas[index];
|
|
4095
|
-
};
|
|
4096
|
-
function getMinAlignDelta(alignRectangles, axis, isHorizontal) {
|
|
4097
|
-
let delta = ALIGN_TOLERANCE;
|
|
4098
|
-
alignRectangles.forEach(item => {
|
|
4099
|
-
const distance = getClosestDelta(axis, item, isHorizontal);
|
|
4100
|
-
if (Math.abs(distance) < Math.abs(delta)) {
|
|
4101
|
-
delta = distance;
|
|
4102
|
-
}
|
|
4103
|
-
});
|
|
4104
|
-
return delta;
|
|
4105
|
-
}
|
|
4106
|
-
function getNearestAlignRectangle(alignRectangles, activeRectangle) {
|
|
4107
|
-
let minDistance = Infinity;
|
|
4108
|
-
let nearestRectangle = alignRectangles[0];
|
|
4109
|
-
alignRectangles.forEach(item => {
|
|
4110
|
-
const distance = Math.sqrt(Math.pow(activeRectangle.x - item.x, 2) + Math.pow(activeRectangle.y - item.y, 2));
|
|
4111
|
-
if (distance < minDistance) {
|
|
4112
|
-
minDistance = distance;
|
|
4113
|
-
nearestRectangle = item;
|
|
4114
|
-
}
|
|
4115
|
-
});
|
|
4116
|
-
return nearestRectangle;
|
|
4117
|
-
}
|
|
4118
|
-
|
|
4119
|
-
function getResizeAlignRef(board, resizeRef, resizeState, resizeOriginPointAndHandlePoint, isAspectRatio, isFromCorner) {
|
|
4120
|
-
const { originPoint, handlePoint } = resizeOriginPointAndHandlePoint;
|
|
4121
|
-
const { xZoom, yZoom } = getResizeZoom(resizeState, originPoint, handlePoint, isFromCorner, isAspectRatio);
|
|
4122
|
-
let activeElements;
|
|
4123
|
-
let resizeOriginPoints = [];
|
|
4124
|
-
if (Array.isArray(resizeRef.element)) {
|
|
4125
|
-
activeElements = resizeRef.element;
|
|
4126
|
-
const rectangle = getRectangleByElements(board, resizeRef.element, false);
|
|
4127
|
-
resizeOriginPoints = RectangleClient.getPoints(rectangle);
|
|
4128
|
-
}
|
|
4129
|
-
else {
|
|
4130
|
-
activeElements = [resizeRef.element];
|
|
4131
|
-
resizeOriginPoints = resizeRef.element.points;
|
|
4132
|
-
}
|
|
4133
|
-
const points = resizeOriginPoints.map(p => {
|
|
4134
|
-
return movePointByZoomAndOriginPoint(p, originPoint, xZoom, yZoom);
|
|
4135
|
-
});
|
|
4136
|
-
const activeRectangle = RectangleClient.getRectangleByPoints(points);
|
|
4137
|
-
const resizeAlignReaction = new ResizeAlignReaction(board, activeElements);
|
|
4138
|
-
const resizeHandlePoint = movePointByZoomAndOriginPoint(handlePoint, originPoint, xZoom, yZoom);
|
|
4139
|
-
const [x, y] = getUnitVectorByPointAndPoint(originPoint, resizeHandlePoint);
|
|
4140
|
-
return resizeAlignReaction.handleResizeAlign({
|
|
4141
|
-
resizeState,
|
|
4142
|
-
resizeOriginPoints,
|
|
4143
|
-
activeRectangle,
|
|
4144
|
-
originPoint,
|
|
4145
|
-
handlePoint,
|
|
4146
|
-
directionFactors: [getDirectionFactorByDirectionComponent(x), getDirectionFactorByDirectionComponent(y)],
|
|
4147
|
-
isAspectRatio,
|
|
4148
|
-
isFromCorner
|
|
4149
|
-
});
|
|
4150
|
-
}
|
|
4151
|
-
|
|
4152
|
-
const debugKey = 'debug:plait:resize-for-rotation';
|
|
4153
|
-
const debugGenerator = createDebugGenerator(debugKey);
|
|
4154
|
-
function withDrawResize(board) {
|
|
4155
|
-
const { afterChange } = board;
|
|
4156
|
-
let alignG;
|
|
4157
|
-
let handleG;
|
|
4158
|
-
const canResize = () => {
|
|
4159
|
-
const elements = getSelectedElements(board);
|
|
4160
|
-
return elements.length > 1 && elements.every(el => PlaitDrawElement.isDrawElement(el));
|
|
4161
|
-
};
|
|
4162
|
-
const options = {
|
|
4163
|
-
key: 'draw-elements',
|
|
4164
|
-
canResize,
|
|
4165
|
-
hitTest: (point) => {
|
|
4166
|
-
const elements = getSelectedElements(board);
|
|
4167
|
-
const boundingRectangle = getRectangleByElements(board, elements, false);
|
|
4168
|
-
const angle = getSelectionAngle(elements);
|
|
4169
|
-
const handleRef = getHitRectangleResizeHandleRef(board, boundingRectangle, point, angle);
|
|
4170
|
-
if (handleRef) {
|
|
4171
|
-
return {
|
|
4172
|
-
element: elements,
|
|
4173
|
-
rectangle: boundingRectangle,
|
|
4174
|
-
handle: handleRef.handle,
|
|
4175
|
-
cursorClass: handleRef.cursorClass
|
|
4176
|
-
};
|
|
4177
|
-
}
|
|
4178
|
-
return null;
|
|
4179
|
-
},
|
|
4180
|
-
onResize: (resizeRef, resizeState) => {
|
|
4181
|
-
alignG?.remove();
|
|
4182
|
-
debugGenerator.isDebug() && debugGenerator.clear();
|
|
4183
|
-
const isFromCorner = isCornerHandle(board, resizeRef.handle);
|
|
4184
|
-
const isAspectRatio = resizeState.isShift || isFromCorner;
|
|
4185
|
-
const centerPoint = RectangleClient.getCenterPoint(resizeRef.rectangle);
|
|
4186
|
-
const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, resizeRef);
|
|
4187
|
-
const angle = getSelectionAngle(resizeRef.element);
|
|
4188
|
-
let bulkRotationRef;
|
|
4189
|
-
if (angle) {
|
|
4190
|
-
bulkRotationRef = {
|
|
4191
|
-
angle: angle,
|
|
4192
|
-
offsetX: 0,
|
|
4193
|
-
offsetY: 0,
|
|
4194
|
-
newCenterPoint: [0, 0]
|
|
4195
|
-
};
|
|
4196
|
-
const [rotatedStartPoint, rotateEndPoint] = rotatePoints([resizeState.startPoint, resizeState.endPoint], centerPoint, -bulkRotationRef.angle);
|
|
4197
|
-
resizeState.startPoint = rotatedStartPoint;
|
|
4198
|
-
resizeState.endPoint = rotateEndPoint;
|
|
4199
|
-
}
|
|
4200
|
-
const resizeAlignRef = getResizeAlignRef(board, resizeRef, resizeState, {
|
|
4201
|
-
originPoint,
|
|
4202
|
-
handlePoint
|
|
4203
|
-
}, isAspectRatio, isFromCorner);
|
|
4204
|
-
alignG = resizeAlignRef.alignG;
|
|
4205
|
-
PlaitBoard.getElementActiveHost(board).append(alignG);
|
|
4206
|
-
if (bulkRotationRef) {
|
|
4207
|
-
const boundingBoxCornerPoints = RectangleClient.getPoints(resizeRef.rectangle);
|
|
4208
|
-
const resizedBoundingBoxCornerPoints = boundingBoxCornerPoints.map(p => {
|
|
4209
|
-
return movePointByZoomAndOriginPoint(p, originPoint, resizeAlignRef.xZoom, resizeAlignRef.yZoom);
|
|
4210
|
-
});
|
|
4211
|
-
const newBoundingBox = RectangleClient.getRectangleByPoints(resizedBoundingBoxCornerPoints);
|
|
4212
|
-
debugGenerator.isDebug() && debugGenerator.drawRectangle(board, newBoundingBox, { stroke: 'blue' });
|
|
4213
|
-
const newBoundingBoxCenter = RectangleClient.getCenterPoint(newBoundingBox);
|
|
4214
|
-
const adjustedNewBoundingBoxPoints = resetPointsAfterResize(RectangleClient.getRectangleByPoints(boundingBoxCornerPoints), RectangleClient.getRectangleByPoints(resizedBoundingBoxCornerPoints), centerPoint, newBoundingBoxCenter, bulkRotationRef.angle);
|
|
4215
|
-
const newCenter = RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(adjustedNewBoundingBoxPoints));
|
|
4216
|
-
bulkRotationRef = Object.assign(bulkRotationRef, {
|
|
4217
|
-
offsetX: newCenter[0] - newBoundingBoxCenter[0],
|
|
4218
|
-
offsetY: newCenter[1] - newBoundingBoxCenter[1],
|
|
4219
|
-
newCenterPoint: newCenter
|
|
4401
|
+
const selectedElements = [...targetDrawElements, ...boundLineElements];
|
|
4402
|
+
const elements = buildClipboardData(board, selectedElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
|
|
4403
|
+
const text = getElementsText(selectedElements);
|
|
4404
|
+
if (!clipboardContext) {
|
|
4405
|
+
clipboardContext = createClipboardContext(WritableClipboardType.elements, elements, text);
|
|
4406
|
+
}
|
|
4407
|
+
else {
|
|
4408
|
+
clipboardContext = addClipboardContext(clipboardContext, {
|
|
4409
|
+
text,
|
|
4410
|
+
type: WritableClipboardType.elements,
|
|
4411
|
+
elements
|
|
4220
4412
|
});
|
|
4221
|
-
debugGenerator.isDebug() && debugGenerator.drawRectangle(board, adjustedNewBoundingBoxPoints);
|
|
4222
4413
|
}
|
|
4223
|
-
resizeRef.element.forEach(target => {
|
|
4224
|
-
const path = PlaitBoard.findPath(board, target);
|
|
4225
|
-
let points;
|
|
4226
|
-
if (bulkRotationRef) {
|
|
4227
|
-
const reversedPoints = rotatedDataPoints(target.points, centerPoint, -bulkRotationRef.angle);
|
|
4228
|
-
points = reversedPoints.map((p) => {
|
|
4229
|
-
return movePointByZoomAndOriginPoint(p, originPoint, resizeAlignRef.xZoom, resizeAlignRef.yZoom);
|
|
4230
|
-
});
|
|
4231
|
-
const adjustTargetPoints = points.map(p => [
|
|
4232
|
-
p[0] + bulkRotationRef.offsetX,
|
|
4233
|
-
p[1] + bulkRotationRef.offsetY
|
|
4234
|
-
]);
|
|
4235
|
-
points = rotatedDataPoints(adjustTargetPoints, bulkRotationRef.newCenterPoint, bulkRotationRef.angle);
|
|
4236
|
-
}
|
|
4237
|
-
else {
|
|
4238
|
-
points = target.points.map(p => {
|
|
4239
|
-
return movePointByZoomAndOriginPoint(p, originPoint, resizeAlignRef.xZoom, resizeAlignRef.yZoom);
|
|
4240
|
-
});
|
|
4241
|
-
}
|
|
4242
|
-
if (PlaitDrawElement.isGeometry(target)) {
|
|
4243
|
-
const { height: textHeight } = getFirstTextManage(target).getSize();
|
|
4244
|
-
DrawTransforms.resizeGeometry(board, points, textHeight, path);
|
|
4245
|
-
}
|
|
4246
|
-
else if (PlaitDrawElement.isLine(target)) {
|
|
4247
|
-
Transforms.setNode(board, { points }, path);
|
|
4248
|
-
}
|
|
4249
|
-
else if (PlaitDrawElement.isImage(target)) {
|
|
4250
|
-
if (isAspectRatio) {
|
|
4251
|
-
Transforms.setNode(board, { points }, path);
|
|
4252
|
-
}
|
|
4253
|
-
else {
|
|
4254
|
-
// The image element does not follow the resize, but moves based on the center point.
|
|
4255
|
-
const targetRectangle = RectangleClient.getRectangleByPoints(target.points);
|
|
4256
|
-
const centerPoint = RectangleClient.getCenterPoint(targetRectangle);
|
|
4257
|
-
const newCenterPoint = movePointByZoomAndOriginPoint(centerPoint, originPoint, resizeAlignRef.xZoom, resizeAlignRef.yZoom);
|
|
4258
|
-
const newTargetRectangle = RectangleClient.getRectangleByCenterPoint(newCenterPoint, targetRectangle.width, targetRectangle.height);
|
|
4259
|
-
Transforms.setNode(board, { points: RectangleClient.getPoints(newTargetRectangle) }, path);
|
|
4260
|
-
}
|
|
4261
|
-
}
|
|
4262
|
-
});
|
|
4263
|
-
},
|
|
4264
|
-
afterResize: (resizeRef) => {
|
|
4265
|
-
alignG?.remove();
|
|
4266
|
-
alignG = null;
|
|
4267
4414
|
}
|
|
4415
|
+
return buildFragment(clipboardContext, rectangle, type);
|
|
4268
4416
|
};
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4417
|
+
board.insertFragment = (clipboardData, targetPoint) => {
|
|
4418
|
+
const selectedElements = getSelectedElements(board);
|
|
4419
|
+
if (clipboardData?.files?.length) {
|
|
4420
|
+
const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
|
|
4421
|
+
const canInsertionImage = !getElementOfFocusedImage(board) && !(selectedElements.length === 1 && board.isImageBindingAllowed(selectedElements[0]));
|
|
4422
|
+
if (acceptImageArray.includes(clipboardData.files[0].type) && canInsertionImage) {
|
|
4423
|
+
const imageFile = clipboardData.files[0];
|
|
4424
|
+
buildImage(board, imageFile, DEFAULT_IMAGE_WIDTH, imageItem => {
|
|
4425
|
+
DrawTransforms.insertImage(board, imageItem, targetPoint);
|
|
4426
|
+
});
|
|
4427
|
+
return;
|
|
4428
|
+
}
|
|
4275
4429
|
}
|
|
4276
|
-
if (
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4430
|
+
if (clipboardData?.elements?.length) {
|
|
4431
|
+
const drawElements = clipboardData.elements?.filter(value => PlaitDrawElement.isDrawElement(value));
|
|
4432
|
+
if (clipboardData.elements && clipboardData.elements.length > 0 && drawElements.length > 0) {
|
|
4433
|
+
insertClipboardData(board, drawElements, targetPoint);
|
|
4434
|
+
}
|
|
4435
|
+
}
|
|
4436
|
+
if (clipboardData?.text) {
|
|
4437
|
+
if (!clipboardData.elements || clipboardData.elements.length === 0) {
|
|
4438
|
+
// (* ̄︶ ̄)
|
|
4439
|
+
const insertAsChildren = selectedElements.length === 1 && selectedElements[0].children;
|
|
4440
|
+
const insertAsFreeText = !insertAsChildren;
|
|
4441
|
+
if (insertAsFreeText) {
|
|
4442
|
+
DrawTransforms.insertText(board, targetPoint, clipboardData.text);
|
|
4443
|
+
return;
|
|
4444
|
+
}
|
|
4285
4445
|
}
|
|
4286
|
-
corners.forEach(corner => {
|
|
4287
|
-
const g = drawHandle(board, corner);
|
|
4288
|
-
handleG && handleG.append(g);
|
|
4289
|
-
});
|
|
4290
|
-
PlaitBoard.getElementActiveHost(board).append(handleG);
|
|
4291
4446
|
}
|
|
4447
|
+
insertFragment(clipboardData, targetPoint);
|
|
4292
4448
|
};
|
|
4293
4449
|
return board;
|
|
4294
|
-
}
|
|
4295
|
-
const getResizeOriginPointAndHandlePoint = (board, resizeRef) => {
|
|
4296
|
-
const handleIndex = getIndexByResizeHandle(resizeRef.handle);
|
|
4297
|
-
const symmetricHandleIndex = getSymmetricHandleIndex(board, handleIndex);
|
|
4298
|
-
const originPoint = getResizeHandlePointByIndex(resizeRef.rectangle, symmetricHandleIndex);
|
|
4299
|
-
const handlePoint = getResizeHandlePointByIndex(resizeRef.rectangle, handleIndex);
|
|
4300
|
-
return {
|
|
4301
|
-
originPoint,
|
|
4302
|
-
handlePoint
|
|
4303
|
-
};
|
|
4304
4450
|
};
|
|
4305
|
-
const
|
|
4306
|
-
const
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4451
|
+
const getBoundedLineElements = (board, plaitShapes) => {
|
|
4452
|
+
const lines = getLines(board);
|
|
4453
|
+
return lines.filter(line => plaitShapes.find(shape => PlaitLine.isBoundElementOfSource(line, shape) || PlaitLine.isBoundElementOfTarget(line, shape)));
|
|
4454
|
+
};
|
|
4455
|
+
|
|
4456
|
+
const withLineCreateByDraw = (board) => {
|
|
4457
|
+
const { pointerDown, pointerMove, globalPointerUp } = board;
|
|
4458
|
+
let start = null;
|
|
4459
|
+
let sourceElement;
|
|
4460
|
+
let lineShapeG = null;
|
|
4461
|
+
let temporaryElement = null;
|
|
4462
|
+
board.pointerDown = (event) => {
|
|
4463
|
+
const linePointers = getLinePointers();
|
|
4464
|
+
const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
|
|
4465
|
+
if (!PlaitBoard.isReadonly(board) && isLinePointer && isDrawingMode(board)) {
|
|
4466
|
+
const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
4467
|
+
start = point;
|
|
4468
|
+
const hitElement = getSnappingGeometry(board, point);
|
|
4469
|
+
if (hitElement) {
|
|
4470
|
+
sourceElement = hitElement;
|
|
4471
|
+
}
|
|
4472
|
+
preventTouchMove(board, event, true);
|
|
4321
4473
|
}
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
if (
|
|
4329
|
-
|
|
4330
|
-
|
|
4474
|
+
pointerDown(event);
|
|
4475
|
+
};
|
|
4476
|
+
board.pointerMove = (event) => {
|
|
4477
|
+
lineShapeG?.remove();
|
|
4478
|
+
lineShapeG = createG();
|
|
4479
|
+
let movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
4480
|
+
if (start) {
|
|
4481
|
+
const lineShape = PlaitBoard.getPointer(board);
|
|
4482
|
+
temporaryElement = handleLineCreating(board, lineShape, start, movingPoint, sourceElement, lineShapeG);
|
|
4331
4483
|
}
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4484
|
+
pointerMove(event);
|
|
4485
|
+
};
|
|
4486
|
+
board.globalPointerUp = (event) => {
|
|
4487
|
+
if (temporaryElement) {
|
|
4488
|
+
Transforms.insertNode(board, temporaryElement, [board.children.length]);
|
|
4489
|
+
clearSelectedElement(board);
|
|
4490
|
+
addSelectedElement(board, temporaryElement);
|
|
4491
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
4339
4492
|
}
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4493
|
+
lineShapeG?.remove();
|
|
4494
|
+
lineShapeG = null;
|
|
4495
|
+
sourceElement = null;
|
|
4496
|
+
start = null;
|
|
4497
|
+
temporaryElement = null;
|
|
4498
|
+
preventTouchMove(board, event, false);
|
|
4499
|
+
globalPointerUp(event);
|
|
4500
|
+
};
|
|
4501
|
+
return board;
|
|
4347
4502
|
};
|
|
4348
4503
|
|
|
4349
4504
|
const withGeometryResize = (board) => {
|
|
4350
|
-
let
|
|
4505
|
+
let snapG;
|
|
4351
4506
|
const options = {
|
|
4352
4507
|
key: 'draw-geometry',
|
|
4353
4508
|
canResize: () => {
|
|
@@ -4375,27 +4530,21 @@ const withGeometryResize = (board) => {
|
|
|
4375
4530
|
return null;
|
|
4376
4531
|
},
|
|
4377
4532
|
onResize: (resizeRef, resizeState) => {
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
const [rotatedStartPoint, rotateEndPoint] = rotatePoints([resizeState.startPoint, resizeState.endPoint], centerPoint, -resizeRef.element.angle);
|
|
4382
|
-
resizeState.startPoint = rotatedStartPoint;
|
|
4383
|
-
resizeState.endPoint = rotateEndPoint;
|
|
4384
|
-
}
|
|
4385
|
-
alignG?.remove();
|
|
4533
|
+
resizeState.startPoint = rotateAntiPointsByElement(resizeState.startPoint, resizeRef.element) || resizeState.startPoint;
|
|
4534
|
+
resizeState.endPoint = rotateAntiPointsByElement(resizeState.endPoint, resizeRef.element) || resizeState.endPoint;
|
|
4535
|
+
snapG?.remove();
|
|
4386
4536
|
const isFromCorner = isCornerHandle(board, resizeRef.handle);
|
|
4387
4537
|
const isAspectRatio = resizeState.isShift || PlaitDrawElement.isImage(resizeRef.element);
|
|
4388
|
-
const
|
|
4389
|
-
const
|
|
4538
|
+
const handleIndex = getIndexByResizeHandle(resizeRef.handle);
|
|
4539
|
+
const { originPoint, handlePoint } = getResizeOriginPointAndHandlePoint(board, handleIndex, resizeRef.rectangle);
|
|
4540
|
+
const resizeSnapRefOptions = getSnapResizingRefOptions(board, resizeRef, resizeState, {
|
|
4390
4541
|
originPoint,
|
|
4391
4542
|
handlePoint
|
|
4392
4543
|
}, isAspectRatio, isFromCorner);
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
points = resetPointsAfterResize(resizeRef.rectangle, RectangleClient.getRectangleByPoints(points), centerPoint, RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(points)), angle);
|
|
4398
|
-
}
|
|
4544
|
+
const resizeSnapRef = getSnapResizingRef(board, [resizeRef.element], resizeSnapRefOptions);
|
|
4545
|
+
snapG = resizeSnapRef.snapG;
|
|
4546
|
+
PlaitBoard.getElementActiveHost(board).append(snapG);
|
|
4547
|
+
let points = resizeSnapRef.activePoints;
|
|
4399
4548
|
if (PlaitDrawElement.isGeometry(resizeRef.element)) {
|
|
4400
4549
|
const { height: textHeight } = getFirstTextManage(resizeRef.element).getSize();
|
|
4401
4550
|
DrawTransforms.resizeGeometry(board, points, textHeight, resizeRef.path);
|
|
@@ -4406,8 +4555,8 @@ const withGeometryResize = (board) => {
|
|
|
4406
4555
|
}
|
|
4407
4556
|
},
|
|
4408
4557
|
afterResize: (resizeRef) => {
|
|
4409
|
-
|
|
4410
|
-
|
|
4558
|
+
snapG?.remove();
|
|
4559
|
+
snapG = null;
|
|
4411
4560
|
}
|
|
4412
4561
|
};
|
|
4413
4562
|
withResize(board, options);
|
|
@@ -4448,8 +4597,7 @@ const withLineResize = (board) => {
|
|
|
4448
4597
|
resizeRef.handle !== LineResizeHandle.source &&
|
|
4449
4598
|
resizeRef.handle !== LineResizeHandle.target) {
|
|
4450
4599
|
const params = getElbowLineRouteOptions(board, resizeRef.element);
|
|
4451
|
-
|
|
4452
|
-
if (isIntersect) {
|
|
4600
|
+
if (isUseDefaultOrthogonalRoute(resizeRef.element, params)) {
|
|
4453
4601
|
return;
|
|
4454
4602
|
}
|
|
4455
4603
|
const points = [...resizeRef.element.points];
|
|
@@ -4468,12 +4616,12 @@ const withLineResize = (board) => {
|
|
|
4468
4616
|
let source = { ...resizeRef.element.source };
|
|
4469
4617
|
let target = { ...resizeRef.element.target };
|
|
4470
4618
|
let handleIndex = resizeRef.handleIndex;
|
|
4471
|
-
const hitElement =
|
|
4619
|
+
const hitElement = getSnappingGeometry(board, resizeState.endPoint);
|
|
4472
4620
|
if (resizeRef.handle === LineResizeHandle.source || resizeRef.handle === LineResizeHandle.target) {
|
|
4473
4621
|
const object = resizeRef.handle === LineResizeHandle.source ? source : target;
|
|
4474
4622
|
points[handleIndex] = resizeState.endPoint;
|
|
4475
4623
|
if (hitElement) {
|
|
4476
|
-
object.connection =
|
|
4624
|
+
object.connection = getHitConnection(board, resizeState.endPoint, hitElement);
|
|
4477
4625
|
object.boundId = hitElement.id;
|
|
4478
4626
|
}
|
|
4479
4627
|
else {
|
|
@@ -4515,7 +4663,8 @@ const withLineResize = (board) => {
|
|
|
4515
4663
|
const newPoints = [...points];
|
|
4516
4664
|
newPoints[0] = drawPoints[0];
|
|
4517
4665
|
newPoints[newPoints.length - 1] = drawPoints[drawPoints.length - 1];
|
|
4518
|
-
if (resizeRef.element.shape !== LineShape.elbow
|
|
4666
|
+
if (resizeRef.element.shape !== LineShape.elbow ||
|
|
4667
|
+
(resizeRef.element.shape === LineShape.elbow && newPoints.length === 2)) {
|
|
4519
4668
|
newPoints.forEach((point, index) => {
|
|
4520
4669
|
if (index === handleIndex)
|
|
4521
4670
|
return;
|
|
@@ -4579,25 +4728,24 @@ const withLineBoundReaction = (board) => {
|
|
|
4579
4728
|
return PlaitDrawElement.isLine(element) && isSourceOrTarget;
|
|
4580
4729
|
});
|
|
4581
4730
|
if (isLinePointer || isLineResizing) {
|
|
4582
|
-
const hitElement =
|
|
4731
|
+
const hitElement = getHitGeometry(board, movingPoint);
|
|
4583
4732
|
if (hitElement) {
|
|
4584
|
-
const
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
}
|
|
4596
|
-
boundShapeG.appendChild(circleG);
|
|
4597
|
-
PlaitBoard.getElementActiveHost(board).append(boundShapeG);
|
|
4733
|
+
const ref = getSnappingRef(board, hitElement, movingPoint);
|
|
4734
|
+
const isSnapping = ref.isHitEdge || ref.isHitConnector;
|
|
4735
|
+
boundShapeG = drawBoundReaction(board, hitElement, { hasMask: isSnapping, hasConnector: true });
|
|
4736
|
+
if (isSnapping) {
|
|
4737
|
+
const circleG = drawCircle(PlaitBoard.getRoughSVG(board), ref.connectorPoint || ref.edgePoint, 6, {
|
|
4738
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
4739
|
+
strokeWidth: SNAPPING_STROKE_WIDTH,
|
|
4740
|
+
fill: SELECTION_BORDER_COLOR,
|
|
4741
|
+
fillStyle: 'solid'
|
|
4742
|
+
});
|
|
4743
|
+
boundShapeG.appendChild(circleG);
|
|
4744
|
+
}
|
|
4598
4745
|
if (hasValidAngle(hitElement)) {
|
|
4599
|
-
setAngleForG(boundShapeG, RectangleClient.
|
|
4746
|
+
setAngleForG(boundShapeG, RectangleClient.getCenterPointByPoints(hitElement.points), hitElement.angle);
|
|
4600
4747
|
}
|
|
4748
|
+
PlaitBoard.getElementActiveHost(board).append(boundShapeG);
|
|
4601
4749
|
}
|
|
4602
4750
|
}
|
|
4603
4751
|
pointerMove(event);
|
|
@@ -4664,9 +4812,8 @@ class ImageComponent extends CommonPluginElement {
|
|
|
4664
4812
|
get activeGenerator() {
|
|
4665
4813
|
return this.imageGenerator.componentRef.instance.activeGenerator;
|
|
4666
4814
|
}
|
|
4667
|
-
constructor(
|
|
4815
|
+
constructor(cdr) {
|
|
4668
4816
|
super(cdr);
|
|
4669
|
-
this.viewContainerRef = viewContainerRef;
|
|
4670
4817
|
this.cdr = cdr;
|
|
4671
4818
|
this.destroy$ = new Subject();
|
|
4672
4819
|
}
|
|
@@ -4693,14 +4840,14 @@ class ImageComponent extends CommonPluginElement {
|
|
|
4693
4840
|
ngOnInit() {
|
|
4694
4841
|
super.ngOnInit();
|
|
4695
4842
|
this.initializeGenerator();
|
|
4696
|
-
this.imageGenerator.processDrawing(this.element, this.
|
|
4843
|
+
this.imageGenerator.processDrawing(this.element, this.getElementG(), this.viewContainerRef);
|
|
4697
4844
|
this.lineAutoCompleteGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
|
|
4698
4845
|
selected: this.selected
|
|
4699
4846
|
});
|
|
4700
4847
|
}
|
|
4701
4848
|
onContextChanged(value, previous) {
|
|
4702
4849
|
if (value.element !== previous.element) {
|
|
4703
|
-
this.imageGenerator.updateImage(this.
|
|
4850
|
+
this.imageGenerator.updateImage(this.getElementG(), previous.element, value.element);
|
|
4704
4851
|
this.imageGenerator.componentRef.instance.isFocus = this.selected;
|
|
4705
4852
|
this.lineAutoCompleteGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
|
|
4706
4853
|
selected: this.selected
|
|
@@ -4724,7 +4871,7 @@ class ImageComponent extends CommonPluginElement {
|
|
|
4724
4871
|
this.imageGenerator.destroy();
|
|
4725
4872
|
this.lineAutoCompleteGenerator.destroy();
|
|
4726
4873
|
}
|
|
4727
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ImageComponent, deps: [{ token: i0.
|
|
4874
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ImageComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4728
4875
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: ImageComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4729
4876
|
}
|
|
4730
4877
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ImageComponent, decorators: [{
|
|
@@ -4735,7 +4882,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
4735
4882
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4736
4883
|
standalone: true
|
|
4737
4884
|
}]
|
|
4738
|
-
}], ctorParameters: () => [{ type: i0.
|
|
4885
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
|
|
4739
4886
|
|
|
4740
4887
|
const withLineAutoCompleteReaction = (board) => {
|
|
4741
4888
|
const { pointerMove } = board;
|
|
@@ -4746,7 +4893,7 @@ const withLineAutoCompleteReaction = (board) => {
|
|
|
4746
4893
|
const selectedElements = getSelectedDrawElements(board);
|
|
4747
4894
|
const targetElement = selectedElements.length === 1 && selectedElements[0];
|
|
4748
4895
|
const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
4749
|
-
if (!PlaitBoard.isReadonly(board) && !isSelectionMoving(board) && targetElement && PlaitDrawElement.
|
|
4896
|
+
if (!PlaitBoard.isReadonly(board) && !isSelectionMoving(board) && targetElement && PlaitDrawElement.isShapeElement(targetElement)) {
|
|
4750
4897
|
const points = getAutoCompletePoints(targetElement);
|
|
4751
4898
|
const hitIndex = getHitIndexOfAutoCompletePoint(rotateAntiPointsByElement(movingPoint, targetElement) || movingPoint, points);
|
|
4752
4899
|
const hitPoint = points[hitIndex];
|
|
@@ -4774,7 +4921,7 @@ const withLineAutoCompleteReaction = (board) => {
|
|
|
4774
4921
|
const WithLineAutoCompletePluginKey = 'plait-line-auto-complete-plugin-key';
|
|
4775
4922
|
const withLineAutoComplete = (board) => {
|
|
4776
4923
|
const { pointerDown, pointerMove, globalPointerUp } = board;
|
|
4777
|
-
let
|
|
4924
|
+
let autoCompletePoint = null;
|
|
4778
4925
|
let lineShapeG = null;
|
|
4779
4926
|
let sourceElement;
|
|
4780
4927
|
let temporaryElement;
|
|
@@ -4782,13 +4929,13 @@ const withLineAutoComplete = (board) => {
|
|
|
4782
4929
|
const selectedElements = getSelectedDrawElements(board);
|
|
4783
4930
|
const targetElement = selectedElements.length === 1 && selectedElements[0];
|
|
4784
4931
|
const clickPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
4785
|
-
if (!PlaitBoard.isReadonly(board) && targetElement && PlaitDrawElement.
|
|
4932
|
+
if (!PlaitBoard.isReadonly(board) && targetElement && PlaitDrawElement.isShapeElement(targetElement)) {
|
|
4786
4933
|
const points = getAutoCompletePoints(targetElement);
|
|
4787
4934
|
const index = getHitIndexOfAutoCompletePoint(rotateAntiPointsByElement(clickPoint, targetElement) || clickPoint, points);
|
|
4788
4935
|
const hitPoint = points[index];
|
|
4789
4936
|
if (hitPoint) {
|
|
4790
4937
|
temporaryDisableSelection(board);
|
|
4791
|
-
|
|
4938
|
+
autoCompletePoint = hitPoint;
|
|
4792
4939
|
sourceElement = targetElement;
|
|
4793
4940
|
BoardTransforms.updatePointerType(board, LineShape.elbow);
|
|
4794
4941
|
}
|
|
@@ -4799,18 +4946,20 @@ const withLineAutoComplete = (board) => {
|
|
|
4799
4946
|
lineShapeG?.remove();
|
|
4800
4947
|
lineShapeG = createG();
|
|
4801
4948
|
let movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
4802
|
-
if (
|
|
4803
|
-
const distance = distanceBetweenPointAndPoint(...
|
|
4949
|
+
if (autoCompletePoint && sourceElement) {
|
|
4950
|
+
const distance = distanceBetweenPointAndPoint(...(rotateAntiPointsByElement(movingPoint, sourceElement) || movingPoint), ...autoCompletePoint);
|
|
4804
4951
|
if (distance > PRESS_AND_MOVE_BUFFER) {
|
|
4805
4952
|
const rectangle = RectangleClient.getRectangleByPoints(sourceElement.points);
|
|
4806
|
-
const shape =
|
|
4953
|
+
const shape = getElementShape(sourceElement);
|
|
4807
4954
|
const engine = getEngine(shape);
|
|
4808
|
-
let sourcePoint =
|
|
4955
|
+
let sourcePoint = autoCompletePoint;
|
|
4809
4956
|
if (engine.getNearestCrossingPoint) {
|
|
4810
|
-
const crossingPoint = engine.getNearestCrossingPoint(rectangle,
|
|
4957
|
+
const crossingPoint = engine.getNearestCrossingPoint(rectangle, autoCompletePoint);
|
|
4811
4958
|
sourcePoint = crossingPoint;
|
|
4812
4959
|
}
|
|
4813
|
-
|
|
4960
|
+
// source point must be click point
|
|
4961
|
+
const rotatedSourcePoint = rotatePointsByElement(sourcePoint, sourceElement) || sourcePoint;
|
|
4962
|
+
temporaryElement = handleLineCreating(board, LineShape.elbow, rotatedSourcePoint, movingPoint, sourceElement, lineShapeG);
|
|
4814
4963
|
}
|
|
4815
4964
|
}
|
|
4816
4965
|
pointerMove(event);
|
|
@@ -4824,9 +4973,9 @@ const withLineAutoComplete = (board) => {
|
|
|
4824
4973
|
?.afterComplete;
|
|
4825
4974
|
afterComplete && afterComplete(temporaryElement);
|
|
4826
4975
|
}
|
|
4827
|
-
if (
|
|
4976
|
+
if (autoCompletePoint) {
|
|
4828
4977
|
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
4829
|
-
|
|
4978
|
+
autoCompletePoint = null;
|
|
4830
4979
|
}
|
|
4831
4980
|
lineShapeG?.remove();
|
|
4832
4981
|
lineShapeG = null;
|
|
@@ -4884,6 +5033,129 @@ const withLineTextMove = (board) => {
|
|
|
4884
5033
|
return board;
|
|
4885
5034
|
};
|
|
4886
5035
|
|
|
5036
|
+
const withDrawRotate = (board) => {
|
|
5037
|
+
const { pointerDown, pointerMove, globalPointerUp, afterChange, drawActiveRectangle } = board;
|
|
5038
|
+
let rotateRef = null;
|
|
5039
|
+
let rotateHandleG;
|
|
5040
|
+
let needCustomActiveRectangle = false;
|
|
5041
|
+
const canRotate = () => {
|
|
5042
|
+
const elements = getSelectedElements(board);
|
|
5043
|
+
return elements.length > 0 && elements.every(el => PlaitDrawElement.isGeometry(el) || PlaitDrawElement.isImage(el));
|
|
5044
|
+
};
|
|
5045
|
+
board.pointerDown = (event) => {
|
|
5046
|
+
if (!canRotate() || PlaitBoard.isReadonly(board) || PlaitBoard.hasBeenTextEditing(board) || !isMainPointer(event)) {
|
|
5047
|
+
pointerDown(event);
|
|
5048
|
+
return;
|
|
5049
|
+
}
|
|
5050
|
+
const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
5051
|
+
const elements = getSelectedElements(board);
|
|
5052
|
+
const boundingRectangle = getRectangleByElements(board, elements, false);
|
|
5053
|
+
const handleRectangle = getRotateHandleRectangle(boundingRectangle);
|
|
5054
|
+
const angle = getSelectionAngle(elements);
|
|
5055
|
+
const rotatedPoint = angle ? rotatePoints(point, RectangleClient.getCenterPoint(boundingRectangle), -angle) : point;
|
|
5056
|
+
if (handleRectangle && RectangleClient.isHit(RectangleClient.getRectangleByPoints([rotatedPoint, rotatedPoint]), handleRectangle)) {
|
|
5057
|
+
rotateRef = {
|
|
5058
|
+
elements: elements,
|
|
5059
|
+
startPoint: point
|
|
5060
|
+
};
|
|
5061
|
+
}
|
|
5062
|
+
pointerDown(event);
|
|
5063
|
+
};
|
|
5064
|
+
board.pointerMove = (event) => {
|
|
5065
|
+
if (rotateRef) {
|
|
5066
|
+
event.preventDefault();
|
|
5067
|
+
const isShift = !!event.shiftKey;
|
|
5068
|
+
addRotating(board, rotateRef);
|
|
5069
|
+
const endPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
5070
|
+
const selectionRectangle = getRectangleByElements(board, rotateRef.elements, false);
|
|
5071
|
+
const selectionCenterPoint = RectangleClient.getCenterPoint(selectionRectangle);
|
|
5072
|
+
if (!getSelectionAngle(rotateRef.elements) && rotateRef.elements.length > 1) {
|
|
5073
|
+
needCustomActiveRectangle = true;
|
|
5074
|
+
}
|
|
5075
|
+
throttleRAF(board, 'with-common-rotate', () => {
|
|
5076
|
+
if (rotateRef && rotateRef.startPoint) {
|
|
5077
|
+
let angle = getAngleBetweenPoints(rotateRef.startPoint, endPoint, selectionCenterPoint);
|
|
5078
|
+
if (isShift) {
|
|
5079
|
+
angle += Math.PI / 12 / 2;
|
|
5080
|
+
angle -= angle % (Math.PI / 12);
|
|
5081
|
+
}
|
|
5082
|
+
const selectionAngle = getSelectionAngle(rotateRef.elements);
|
|
5083
|
+
let remainder = (selectionAngle + angle) % (Math.PI / 2);
|
|
5084
|
+
if (Math.PI / 2 - remainder <= degreesToRadians(5)) {
|
|
5085
|
+
const snapAngle = Math.PI / 2 - remainder;
|
|
5086
|
+
angle += snapAngle;
|
|
5087
|
+
}
|
|
5088
|
+
if (remainder <= degreesToRadians(5)) {
|
|
5089
|
+
const snapAngle = -remainder;
|
|
5090
|
+
angle += snapAngle;
|
|
5091
|
+
}
|
|
5092
|
+
rotateRef.angle = normalizeAngle(angle);
|
|
5093
|
+
if (rotateRef.angle) {
|
|
5094
|
+
rotateElements(board, rotateRef.elements, rotateRef.angle);
|
|
5095
|
+
}
|
|
5096
|
+
PlaitBoard.getBoardContainer(board).classList.add('element-rotating');
|
|
5097
|
+
}
|
|
5098
|
+
});
|
|
5099
|
+
return;
|
|
5100
|
+
}
|
|
5101
|
+
pointerMove(event);
|
|
5102
|
+
};
|
|
5103
|
+
board.globalPointerUp = (event) => {
|
|
5104
|
+
globalPointerUp(event);
|
|
5105
|
+
if (needCustomActiveRectangle) {
|
|
5106
|
+
needCustomActiveRectangle = false;
|
|
5107
|
+
const selectedElements = getSelectedElements(board);
|
|
5108
|
+
Transforms.addSelectionWithTemporaryElements(board, selectedElements);
|
|
5109
|
+
}
|
|
5110
|
+
PlaitBoard.getBoardContainer(board).classList.remove('element-rotating');
|
|
5111
|
+
removeRotating(board);
|
|
5112
|
+
rotateRef = null;
|
|
5113
|
+
MERGING.set(board, false);
|
|
5114
|
+
preventTouchMove(board, event, false);
|
|
5115
|
+
};
|
|
5116
|
+
board.afterChange = () => {
|
|
5117
|
+
afterChange();
|
|
5118
|
+
if (rotateHandleG) {
|
|
5119
|
+
rotateHandleG.remove();
|
|
5120
|
+
rotateHandleG = null;
|
|
5121
|
+
}
|
|
5122
|
+
if (canRotate() && !isSelectionMoving(board)) {
|
|
5123
|
+
if (needCustomActiveRectangle && rotateRef) {
|
|
5124
|
+
const boundingRectangle = getRectangleByElements(board, rotateRef.elements, false);
|
|
5125
|
+
rotateHandleG = drawRotateHandle(board, boundingRectangle);
|
|
5126
|
+
rotateHandleG.classList.add(ROTATE_HANDLE_CLASS_NAME);
|
|
5127
|
+
if (rotateRef.angle) {
|
|
5128
|
+
setAngleForG(rotateHandleG, RectangleClient.getCenterPoint(boundingRectangle), rotateRef.angle);
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
else {
|
|
5132
|
+
const elements = getSelectedElements(board);
|
|
5133
|
+
const boundingRectangle = getRectangleByElements(board, elements, false);
|
|
5134
|
+
rotateHandleG = drawRotateHandle(board, boundingRectangle);
|
|
5135
|
+
rotateHandleG.classList.add(ROTATE_HANDLE_CLASS_NAME);
|
|
5136
|
+
setAngleForG(rotateHandleG, RectangleClient.getCenterPoint(boundingRectangle), getSelectionAngle(elements));
|
|
5137
|
+
}
|
|
5138
|
+
PlaitBoard.getElementActiveHost(board).append(rotateHandleG);
|
|
5139
|
+
}
|
|
5140
|
+
};
|
|
5141
|
+
board.drawActiveRectangle = () => {
|
|
5142
|
+
if (needCustomActiveRectangle && rotateRef) {
|
|
5143
|
+
const rectangle = getRectangleByElements(board, rotateRef.elements, false);
|
|
5144
|
+
const rectangleG = drawRectangle(board, RectangleClient.inflate(rectangle, ACTIVE_STROKE_WIDTH), {
|
|
5145
|
+
stroke: SELECTION_BORDER_COLOR,
|
|
5146
|
+
strokeWidth: ACTIVE_STROKE_WIDTH
|
|
5147
|
+
});
|
|
5148
|
+
rectangleG.classList.add(SELECTION_RECTANGLE_CLASS_NAME);
|
|
5149
|
+
if (rotateRef.angle) {
|
|
5150
|
+
setAngleForG(rectangleG, RectangleClient.getCenterPoint(rectangle), rotateRef.angle);
|
|
5151
|
+
}
|
|
5152
|
+
return rectangleG;
|
|
5153
|
+
}
|
|
5154
|
+
return drawActiveRectangle();
|
|
5155
|
+
};
|
|
5156
|
+
return board;
|
|
5157
|
+
};
|
|
5158
|
+
|
|
4887
5159
|
const withDraw = (board) => {
|
|
4888
5160
|
const { drawElement, getRectangle, isRectangleHit, isHit, isInsidePoint, isMovable, isAlign, getRelatedFragment } = board;
|
|
4889
5161
|
board.drawElement = (context) => {
|
|
@@ -4968,8 +5240,8 @@ const withDraw = (board) => {
|
|
|
4968
5240
|
}
|
|
4969
5241
|
return isAlign(element);
|
|
4970
5242
|
};
|
|
4971
|
-
board.getRelatedFragment = (elements) => {
|
|
4972
|
-
const selectedElements = getSelectedElements(board);
|
|
5243
|
+
board.getRelatedFragment = (elements, originData) => {
|
|
5244
|
+
const selectedElements = originData || getSelectedElements(board);
|
|
4973
5245
|
const lineElements = board.children.filter(element => PlaitDrawElement.isLine(element));
|
|
4974
5246
|
const activeLines = lineElements.filter(line => {
|
|
4975
5247
|
const source = selectedElements.find(element => element.id === line.source.boundId);
|
|
@@ -4977,14 +5249,14 @@ const withDraw = (board) => {
|
|
|
4977
5249
|
const isSelected = selectedElements.includes(line);
|
|
4978
5250
|
return source && target && !isSelected;
|
|
4979
5251
|
});
|
|
4980
|
-
return getRelatedFragment([...elements, ...activeLines]);
|
|
5252
|
+
return getRelatedFragment([...elements, ...activeLines], originData);
|
|
4981
5253
|
};
|
|
4982
|
-
return withDrawResize(withLineTextMove(withLineAutoCompleteReaction(withLineText(withLineBoundReaction(withLineResize(withGeometryResize(withLineCreateByDraw(withLineAutoComplete(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board)))))))))))));
|
|
5254
|
+
return withDrawResize(withLineTextMove(withLineAutoCompleteReaction(withLineText(withLineBoundReaction(withLineResize(withGeometryResize(withDrawRotate(withLineCreateByDraw(withLineAutoComplete(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board))))))))))))));
|
|
4983
5255
|
};
|
|
4984
5256
|
|
|
4985
5257
|
/**
|
|
4986
5258
|
* Generated bundle index. Do not edit.
|
|
4987
5259
|
*/
|
|
4988
5260
|
|
|
4989
|
-
export { BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultBasicShapeProperty, DefaultConnectorProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultGeometryActiveStyle, DefaultGeometryStyle, DefaultManualInputProperty, DefaultMergeProperty, DefaultTextProperty, DrawThemeColors, DrawTransforms, FlowchartSymbols, GeometryComponent, GeometryThreshold, LineComponent, LineHandleKey, LineMarkerType, LineShape, MemorizeKey, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C,
|
|
5261
|
+
export { BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultBasicShapeProperty, DefaultCloudShapeProperty, DefaultConnectorProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultGeometryActiveStyle, DefaultGeometryStyle, DefaultManualInputProperty, DefaultMergeProperty, DefaultTextProperty, DrawThemeColors, DrawTransforms, FlowchartSymbols, GeometryComponent, GeometryThreshold, LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER, LINE_SNAPPING_CONNECTOR_BUFFER, LineComponent, LineHandleKey, LineMarkerType, LineShape, MemorizeKey, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, StrokeStyle, WithLineAutoCompletePluginKey, alignElbowSegment, alignPoints, createDefaultFlowchart, createDefaultGeometry, createGeometryElement, createLineElement, createTextElement, drawBoundReaction, drawGeometry, drawLine, drawLineArrow, getAutoCompletePoints, getBasicPointers, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultFlowchartProperty, getDefaultGeometryPoints, getDefaultGeometryProperty, getDefaultTextPoints, getDrawDefaultStrokeColor, getElbowLineRouteOptions, getElbowPoints, getFillByElement, getFlowchartDefaultFill, getFlowchartPointers, getGeometryPointers, getHitConnection, getHitConnectorPoint, getHitIndexOfAutoCompletePoint, getIndexAndDeleteCountByKeyPoint, getLineDashByElement, getLineHandleRefPair, getLineMemorizedLatest, getLinePointers, getLinePoints, getLineTextRectangle, getLines, getMemorizeKey, getMemorizedLatestByPointer, getMemorizedLatestShape, getMidKeyPoints, getMiddlePoints, getMirrorDataPoints, getNearestPoint, getNextRenderPoints, getNextSourceAndTargetPoints, getResizedPreviousAndNextPoint, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedLineElements, getSourceAndTargetRectangle, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTextRectangle, getTextShapeProperty, getVectorByConnection, handleLineCreating, hasIllegalElbowPoint, insertElement, isHitDrawElement, isHitEdgeOfShape, isHitElementInside, isHitLine, isHitLineText, isHitPolyLine, isInsideOfShape, isRectangleHitDrawElement, isSelfLoop, isTextExceedingBounds, isUpdatedHandleIndex, isUseDefaultOrthogonalRoute, memorizeLatestShape, memorizeLatestText, withDraw, withLineAutoComplete };
|
|
4990
5262
|
//# sourceMappingURL=plait-draw.mjs.map
|