@plait/draw 0.1.0-next.9 → 0.28.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/image.d.ts +1 -0
- package/constants/index.d.ts +1 -0
- package/constants/pointer.d.ts +4 -10
- package/engines/comment.d.ts +4 -0
- package/engines/cross.d.ts +4 -0
- package/{utils/engine → engines}/diamond.d.ts +1 -1
- package/{utils/engine → engines}/ellipse.d.ts +1 -1
- package/engines/hexagon.d.ts +4 -0
- package/{utils/engine → engines}/index.d.ts +1 -1
- package/engines/left-arrow.d.ts +4 -0
- package/engines/octagon.d.ts +4 -0
- package/engines/parallelogram.d.ts +4 -0
- package/engines/pentagon-arrow.d.ts +4 -0
- package/engines/pentagon.d.ts +4 -0
- package/engines/process-arrow.d.ts +4 -0
- package/{utils/engine → engines}/rectangle.d.ts +1 -1
- package/engines/right-arrow.d.ts +4 -0
- package/engines/round-comment.d.ts +4 -0
- package/{utils/engine → engines}/round-rectangle.d.ts +1 -1
- package/engines/star.d.ts +4 -0
- package/engines/trapezoid.d.ts +4 -0
- package/engines/triangle.d.ts +4 -0
- package/engines/two-way-arrow.d.ts +4 -0
- package/esm2022/constants/geometry.mjs +3 -3
- package/esm2022/constants/image.mjs +2 -0
- package/esm2022/constants/index.mjs +2 -1
- package/esm2022/constants/pointer.mjs +8 -19
- package/esm2022/engines/comment.mjs +57 -0
- package/esm2022/engines/cross.mjs +46 -0
- package/esm2022/engines/diamond.mjs +30 -0
- package/esm2022/engines/ellipse.mjs +92 -0
- package/esm2022/engines/hexagon.mjs +40 -0
- package/esm2022/engines/index.mjs +46 -0
- package/esm2022/engines/left-arrow.mjs +45 -0
- package/esm2022/engines/octagon.mjs +42 -0
- package/esm2022/engines/parallelogram.mjs +39 -0
- package/esm2022/engines/pentagon-arrow.mjs +39 -0
- package/esm2022/engines/pentagon.mjs +39 -0
- package/esm2022/engines/process-arrow.mjs +41 -0
- package/esm2022/engines/rectangle.mjs +26 -0
- package/esm2022/engines/right-arrow.mjs +45 -0
- package/esm2022/engines/round-comment.mjs +81 -0
- package/esm2022/engines/round-rectangle.mjs +59 -0
- package/esm2022/engines/star.mjs +45 -0
- package/esm2022/engines/trapezoid.mjs +40 -0
- package/esm2022/engines/triangle.mjs +40 -0
- package/esm2022/engines/two-way-arrow.mjs +48 -0
- package/esm2022/generators/geometry-shape.generator.mjs +7 -2
- package/esm2022/generators/line-active.generator.mjs +71 -22
- package/esm2022/generators/line.generator.mjs +2 -11
- package/esm2022/geometry.component.mjs +13 -7
- package/esm2022/image.component.mjs +70 -0
- package/esm2022/interfaces/geometry.mjs +15 -1
- package/esm2022/interfaces/image.mjs +2 -0
- package/esm2022/interfaces/index.mjs +8 -2
- package/esm2022/interfaces/line.mjs +27 -4
- package/esm2022/line.component.mjs +15 -6
- package/esm2022/plugins/with-draw-fragment.mjs +37 -7
- package/esm2022/plugins/with-draw.mjs +38 -10
- package/esm2022/plugins/with-geometry-create.mjs +15 -12
- package/esm2022/plugins/with-geometry-resize.mjs +28 -20
- package/esm2022/plugins/with-line-bound-reaction.mjs +10 -5
- package/esm2022/plugins/with-line-create.mjs +7 -5
- package/esm2022/plugins/with-line-resize.mjs +12 -4
- package/esm2022/transforms/geometry-text.mjs +1 -1
- package/esm2022/transforms/image.mjs +23 -0
- package/esm2022/transforms/index.mjs +4 -2
- package/esm2022/utils/clipboard.mjs +4 -3
- package/esm2022/utils/geometry.mjs +20 -6
- package/esm2022/utils/index.mjs +1 -1
- package/esm2022/utils/line-arrow.mjs +43 -18
- package/esm2022/utils/line.mjs +202 -51
- package/esm2022/utils/position/geometry.mjs +5 -4
- package/esm2022/utils/position/line.mjs +32 -22
- package/esm2022/utils/selected.mjs +5 -1
- package/esm2022/utils/shape.mjs +8 -0
- package/fesm2022/plait-draw.mjs +1439 -280
- package/fesm2022/plait-draw.mjs.map +1 -1
- package/generators/line-active.generator.d.ts +3 -0
- package/generators/line.generator.d.ts +1 -1
- package/geometry.component.d.ts +1 -1
- package/image.component.d.ts +20 -0
- package/interfaces/geometry.d.ts +20 -2
- package/interfaces/image.d.ts +7 -0
- package/interfaces/index.d.ts +5 -1
- package/interfaces/line.d.ts +19 -5
- package/line.component.d.ts +2 -1
- package/package.json +3 -2
- package/plugins/with-draw-fragment.d.ts +2 -0
- package/plugins/with-geometry-create.d.ts +1 -1
- package/styles/styles.scss +2 -2
- package/transforms/image.d.ts +3 -0
- package/transforms/index.d.ts +1 -0
- package/utils/geometry.d.ts +1 -0
- package/utils/line.d.ts +14 -6
- package/utils/position/geometry.d.ts +2 -1
- package/utils/position/line.d.ts +7 -3
- package/utils/selected.d.ts +2 -0
- package/utils/shape.d.ts +2 -0
- package/esm2022/utils/engine/diamond.mjs +0 -22
- package/esm2022/utils/engine/ellipse.mjs +0 -55
- package/esm2022/utils/engine/index.mjs +0 -18
- package/esm2022/utils/engine/parallelogram.mjs +0 -32
- package/esm2022/utils/engine/rectangle.mjs +0 -18
- package/esm2022/utils/engine/round-rectangle.mjs +0 -49
- package/utils/engine/parallelogram.d.ts +0 -4
package/fesm2022/plait-draw.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { PlaitElement, ACTIVE_STROKE_WIDTH,
|
|
1
|
+
import { PlaitElement, ACTIVE_STROKE_WIDTH, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, idCreator, createG, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, distanceBetweenPointAndSegment, arrowPoints, createPath, drawLinearPath, rotate, getElementById, distanceBetweenPointAndPoint, distanceBetweenPointAndSegments, createMask, createRect, findElements, getSelectedElements, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Point, BOARD_TO_HOST, transformPoint, toPoint, isSelectionMoving, PlaitPluginElementComponent, BoardTransforms, PlaitPointerType, preventTouchMove, createForeignObject, setClipboardData, getDataFromClipboard, depthFirstRecursion, getIsRecursionFunc, getHitElements, isPolylineHitRectangle } from '@plait/core';
|
|
2
|
+
import { getRectangleByPoints, getFactorByPoints, getDirectionByVector, getOppositeDirection, getDirectionFactor, getPoints, getPointByVector, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90, Generator, normalizeShapePoints, CommonPluginElement, ActiveGenerator, WithTextPluginKey, RESIZE_HANDLE_DIAMETER, PRIMARY_COLOR, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, acceptImageTypes, buildImage, getRectangleResizeHandleRefs, ResizeHandle, withResize, isResizingByCondition, getRatioByPoint, ImageGenerator } from '@plait/common';
|
|
3
|
+
import { Alignment, buildText, AlignEditor, TextManage, DEFAULT_FONT_SIZE, getTextFromClipboard, getTextSize } from '@plait/text';
|
|
4
|
+
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
2
5
|
import * as i0 from '@angular/core';
|
|
3
6
|
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
4
7
|
import { Subject } from 'rxjs';
|
|
5
|
-
import { getRectangleByPoints, getFactorByPoints, Direction, getDirectionByPoint, getPoints, getPointOnPolyline, getDirectionFactor, Generator, normalizeShapePoints, CommonPluginElement, ActiveGenerator, WithTextPluginKey, RESIZE_HANDLE_DIAMETER, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, getRectangleResizeHandleRefs, ResizeHandle, withResize, isResizingByCondition, getRatioByPoint } from '@plait/common';
|
|
6
|
-
import { Alignment, buildText, AlignEditor, TextManage, DEFAULT_FONT_SIZE, getTextFromClipboard, getTextSize } from '@plait/text';
|
|
7
8
|
import { isKeyHotkey } from 'is-hotkey';
|
|
8
9
|
import { Node } from 'slate';
|
|
9
10
|
|
|
@@ -15,6 +16,20 @@ var GeometryShape;
|
|
|
15
16
|
GeometryShape["roundRectangle"] = "roundRectangle";
|
|
16
17
|
GeometryShape["parallelogram"] = "parallelogram";
|
|
17
18
|
GeometryShape["text"] = "text";
|
|
19
|
+
GeometryShape["triangle"] = "triangle";
|
|
20
|
+
GeometryShape["leftArrow"] = "leftArrow";
|
|
21
|
+
GeometryShape["trapezoid"] = "trapezoid";
|
|
22
|
+
GeometryShape["rightArrow"] = "rightArrow";
|
|
23
|
+
GeometryShape["cross"] = "cross";
|
|
24
|
+
GeometryShape["star"] = "star";
|
|
25
|
+
GeometryShape["pentagon"] = "pentagon";
|
|
26
|
+
GeometryShape["hexagon"] = "hexagon";
|
|
27
|
+
GeometryShape["octagon"] = "octagon";
|
|
28
|
+
GeometryShape["pentagonArrow"] = "pentagonArrow";
|
|
29
|
+
GeometryShape["processArrow"] = "processArrow";
|
|
30
|
+
GeometryShape["twoWayArrow"] = "twoWayArrow";
|
|
31
|
+
GeometryShape["comment"] = "comment";
|
|
32
|
+
GeometryShape["roundComment"] = "roundComment";
|
|
18
33
|
})(GeometryShape || (GeometryShape = {}));
|
|
19
34
|
const PlaitGeometry = {
|
|
20
35
|
getTextEditor(element) {
|
|
@@ -29,79 +44,6 @@ const PlaitGeometry = {
|
|
|
29
44
|
}
|
|
30
45
|
};
|
|
31
46
|
|
|
32
|
-
var LineMarkerType;
|
|
33
|
-
(function (LineMarkerType) {
|
|
34
|
-
LineMarkerType["arrow"] = "arrow";
|
|
35
|
-
LineMarkerType["none"] = "none";
|
|
36
|
-
LineMarkerType["openTriangle"] = "open-triangle";
|
|
37
|
-
LineMarkerType["solidTriangle"] = "solid-triangle";
|
|
38
|
-
LineMarkerType["sharpArrow"] = "sharp-arrow";
|
|
39
|
-
})(LineMarkerType || (LineMarkerType = {}));
|
|
40
|
-
var LineShape;
|
|
41
|
-
(function (LineShape) {
|
|
42
|
-
LineShape["straight"] = "straight";
|
|
43
|
-
LineShape["curve"] = "curve";
|
|
44
|
-
LineShape["elbow"] = "elbow";
|
|
45
|
-
})(LineShape || (LineShape = {}));
|
|
46
|
-
var LineHandleKey;
|
|
47
|
-
(function (LineHandleKey) {
|
|
48
|
-
LineHandleKey["source"] = "source";
|
|
49
|
-
LineHandleKey["target"] = "target";
|
|
50
|
-
})(LineHandleKey || (LineHandleKey = {}));
|
|
51
|
-
const PlaitLine = {
|
|
52
|
-
getTextEditors(element) {
|
|
53
|
-
const component = PlaitElement.getComponent(element);
|
|
54
|
-
if (component) {
|
|
55
|
-
const manage = component.textManages.find(manage => manage.isEditing);
|
|
56
|
-
if (manage) {
|
|
57
|
-
return [manage.componentRef.instance.editor];
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
return component.textManages.map(manage => manage.componentRef.instance.editor);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
throw new Error('can not get correctly component in get text editor');
|
|
64
|
-
},
|
|
65
|
-
isSourceMark(line, markType) {
|
|
66
|
-
return line.source.marker === markType;
|
|
67
|
-
},
|
|
68
|
-
isTargetMark(line, markType) {
|
|
69
|
-
return line.target.marker === markType;
|
|
70
|
-
},
|
|
71
|
-
isBoundElementOfSource(line, element) {
|
|
72
|
-
return line.source.boundId === element.id;
|
|
73
|
-
},
|
|
74
|
-
isBoundElementOfTarget(line, element) {
|
|
75
|
-
return line.target.boundId === element.id;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
var StrokeStyle;
|
|
80
|
-
(function (StrokeStyle) {
|
|
81
|
-
StrokeStyle["solid"] = "solid";
|
|
82
|
-
StrokeStyle["dashed"] = "dashed";
|
|
83
|
-
})(StrokeStyle || (StrokeStyle = {}));
|
|
84
|
-
|
|
85
|
-
const PlaitDrawElement = {
|
|
86
|
-
isGeometry: (value) => {
|
|
87
|
-
return value.type === 'geometry';
|
|
88
|
-
},
|
|
89
|
-
isLine: (value) => {
|
|
90
|
-
return value.type === 'line';
|
|
91
|
-
},
|
|
92
|
-
isText: (value) => {
|
|
93
|
-
return value.type === 'geometry' && value.shape === GeometryShape.text;
|
|
94
|
-
},
|
|
95
|
-
isDrawElement: (value) => {
|
|
96
|
-
if (PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isLine(value)) {
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
47
|
const ShapeDefaultSpace = {
|
|
106
48
|
rectangleAndText: 4
|
|
107
49
|
};
|
|
@@ -127,27 +69,17 @@ const DefaultTextProperty = {
|
|
|
127
69
|
text: '文本'
|
|
128
70
|
};
|
|
129
71
|
const GeometryThreshold = {
|
|
130
|
-
defaultTextMaxWidth: 34 * 14
|
|
72
|
+
defaultTextMaxWidth: 34 * 14
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const getGeometryPointers = () => {
|
|
76
|
+
return Object.keys(GeometryShape);
|
|
77
|
+
};
|
|
78
|
+
const getLinePointers = () => {
|
|
79
|
+
return Object.keys(LineShape);
|
|
131
80
|
};
|
|
132
81
|
|
|
133
|
-
|
|
134
|
-
(function (DrawPointerType) {
|
|
135
|
-
DrawPointerType["text"] = "text";
|
|
136
|
-
DrawPointerType["rectangle"] = "rectangle";
|
|
137
|
-
DrawPointerType["line"] = "line";
|
|
138
|
-
DrawPointerType["diamond"] = "diamond";
|
|
139
|
-
DrawPointerType["roundRectangle"] = "roundRectangle";
|
|
140
|
-
DrawPointerType["parallelogram"] = "parallelogram";
|
|
141
|
-
DrawPointerType["ellipse"] = "ellipse";
|
|
142
|
-
})(DrawPointerType || (DrawPointerType = {}));
|
|
143
|
-
const GeometryPointer = [
|
|
144
|
-
DrawPointerType.rectangle,
|
|
145
|
-
DrawPointerType.text,
|
|
146
|
-
DrawPointerType.diamond,
|
|
147
|
-
DrawPointerType.ellipse,
|
|
148
|
-
DrawPointerType.parallelogram,
|
|
149
|
-
DrawPointerType.roundRectangle
|
|
150
|
-
];
|
|
82
|
+
const DEFAULT_IMAGE_WIDTH = 1000;
|
|
151
83
|
|
|
152
84
|
const getStrokeWidthByElement = (element) => {
|
|
153
85
|
if (PlaitDrawElement.isText(element)) {
|
|
@@ -171,6 +103,102 @@ const getStrokeStyleByElement = (element) => {
|
|
|
171
103
|
return element.strokeStyle || StrokeStyle.solid;
|
|
172
104
|
};
|
|
173
105
|
|
|
106
|
+
const heightRatio$1 = 3 / 4;
|
|
107
|
+
const CommentEngine = {
|
|
108
|
+
draw(board, rectangle, options) {
|
|
109
|
+
const points = getCommentPoints(rectangle);
|
|
110
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
111
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
112
|
+
setStrokeLinecap(polygon, 'round');
|
|
113
|
+
return polygon;
|
|
114
|
+
},
|
|
115
|
+
isHit(rectangle, point) {
|
|
116
|
+
const parallelogramPoints = getCommentPoints(rectangle);
|
|
117
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
118
|
+
},
|
|
119
|
+
getCornerPoints(rectangle) {
|
|
120
|
+
return getCommentPoints(rectangle);
|
|
121
|
+
},
|
|
122
|
+
getNearestPoint(rectangle, point) {
|
|
123
|
+
return getNearestPointBetweenPointAndSegments(point, getCommentPoints(rectangle));
|
|
124
|
+
},
|
|
125
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
126
|
+
const corners = getCommentPoints(rectangle);
|
|
127
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
128
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
129
|
+
},
|
|
130
|
+
getConnectorPoints(rectangle) {
|
|
131
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
132
|
+
},
|
|
133
|
+
getTextRectangle(element) {
|
|
134
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
135
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
136
|
+
const height = element.textHeight;
|
|
137
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
138
|
+
return {
|
|
139
|
+
height,
|
|
140
|
+
width: width > 0 ? width : 0,
|
|
141
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
142
|
+
y: elementRectangle.y + (elementRectangle.height * heightRatio$1 - height) / 2
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const getCommentPoints = (rectangle) => {
|
|
147
|
+
return [
|
|
148
|
+
[rectangle.x, rectangle.y],
|
|
149
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
150
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * heightRatio$1],
|
|
151
|
+
[rectangle.x + (rectangle.width * 3) / 5, rectangle.y + rectangle.height * heightRatio$1],
|
|
152
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height],
|
|
153
|
+
[rectangle.x + (rectangle.width * 2) / 5, rectangle.y + rectangle.height * heightRatio$1],
|
|
154
|
+
[rectangle.x, rectangle.y + rectangle.height * heightRatio$1]
|
|
155
|
+
];
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const CrossEngine = {
|
|
159
|
+
draw(board, rectangle, options) {
|
|
160
|
+
const points = getCrossPoints(rectangle);
|
|
161
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
162
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
163
|
+
setStrokeLinecap(polygon, 'round');
|
|
164
|
+
return polygon;
|
|
165
|
+
},
|
|
166
|
+
isHit(rectangle, point) {
|
|
167
|
+
const parallelogramPoints = getCrossPoints(rectangle);
|
|
168
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
169
|
+
},
|
|
170
|
+
getCornerPoints(rectangle) {
|
|
171
|
+
return getCrossPoints(rectangle);
|
|
172
|
+
},
|
|
173
|
+
getNearestPoint(rectangle, point) {
|
|
174
|
+
return getNearestPointBetweenPointAndSegments(point, getCrossPoints(rectangle));
|
|
175
|
+
},
|
|
176
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
177
|
+
const corners = getCrossPoints(rectangle);
|
|
178
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
179
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
180
|
+
},
|
|
181
|
+
getConnectorPoints(rectangle) {
|
|
182
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
const getCrossPoints = (rectangle) => {
|
|
186
|
+
return [
|
|
187
|
+
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
188
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y],
|
|
189
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height / 4],
|
|
190
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 4],
|
|
191
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 3) / 4],
|
|
192
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + (rectangle.height * 3) / 4],
|
|
193
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height],
|
|
194
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
195
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + (rectangle.height * 3) / 4],
|
|
196
|
+
[rectangle.x, rectangle.y + (rectangle.height * 3) / 4],
|
|
197
|
+
[rectangle.x, rectangle.y + rectangle.height / 4],
|
|
198
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height / 4]
|
|
199
|
+
];
|
|
200
|
+
};
|
|
201
|
+
|
|
174
202
|
const DiamondEngine = {
|
|
175
203
|
draw(board, rectangle, options) {
|
|
176
204
|
const points = RectangleClient.getEdgeCenterPoints(rectangle);
|
|
@@ -183,9 +211,16 @@ const DiamondEngine = {
|
|
|
183
211
|
const controlPoints = RectangleClient.getEdgeCenterPoints(rectangle);
|
|
184
212
|
return isPointInPolygon(point, controlPoints);
|
|
185
213
|
},
|
|
214
|
+
getCornerPoints(rectangle) {
|
|
215
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
216
|
+
},
|
|
186
217
|
getNearestPoint(rectangle, point) {
|
|
187
|
-
|
|
188
|
-
|
|
218
|
+
return getNearestPointBetweenPointAndSegments(point, DiamondEngine.getCornerPoints(rectangle));
|
|
219
|
+
},
|
|
220
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
221
|
+
const corners = DiamondEngine.getCornerPoints(rectangle);
|
|
222
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
223
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
189
224
|
},
|
|
190
225
|
getConnectorPoints(rectangle) {
|
|
191
226
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
@@ -202,10 +237,22 @@ const EllipseEngine = {
|
|
|
202
237
|
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
203
238
|
return isPointInEllipse(point, centerPoint, rectangle.width / 2, rectangle.height / 2);
|
|
204
239
|
},
|
|
240
|
+
getCornerPoints(rectangle) {
|
|
241
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
242
|
+
},
|
|
205
243
|
getNearestPoint(rectangle, point) {
|
|
206
244
|
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
207
245
|
return getNearestPointBetweenPointAndEllipse(point, centerPoint, rectangle.width / 2, rectangle.height / 2);
|
|
208
246
|
},
|
|
247
|
+
getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
|
|
248
|
+
const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
249
|
+
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
250
|
+
const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
|
|
251
|
+
const a = rectangle.width / 2;
|
|
252
|
+
const b = rectangle.height / 2;
|
|
253
|
+
const slope = getTangentSlope(point[0], point[1], a, b);
|
|
254
|
+
return getVectorBySlope(point[0], point[1], slope);
|
|
255
|
+
},
|
|
209
256
|
getConnectorPoints(rectangle) {
|
|
210
257
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
211
258
|
}
|
|
@@ -245,29 +292,182 @@ function getNearestPointBetweenPointAndEllipse(point, center, rx, ry, rotation =
|
|
|
245
292
|
const signY = point[1] > center[1] ? 1 : -1;
|
|
246
293
|
return [center[0] + a * tx * signX, center[1] + b * ty * signY];
|
|
247
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* the result of slope is based on Cartesian coordinate system
|
|
297
|
+
* x, y are based on the position in the Cartesian coordinate system
|
|
298
|
+
*/
|
|
299
|
+
function getTangentSlope(x, y, a, b) {
|
|
300
|
+
const k = (-b * b * x) / (a * a * y);
|
|
301
|
+
return k;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* x, y are based on the position in the Cartesian coordinate system
|
|
305
|
+
*/
|
|
306
|
+
function getVectorBySlope(x, y, slope) {
|
|
307
|
+
const deltaX = 30;
|
|
308
|
+
const deltaY = -slope * deltaX;
|
|
309
|
+
let start = [0 - deltaX, 0 - deltaY];
|
|
310
|
+
let end = [0 + deltaX, 0 + deltaY];
|
|
311
|
+
// y < 0 acts on the lower half of the x-axis, with the starting point at the top and the end point at the bottom.
|
|
312
|
+
if (y < 0) {
|
|
313
|
+
const temp = start;
|
|
314
|
+
start = end;
|
|
315
|
+
end = temp;
|
|
316
|
+
}
|
|
317
|
+
const vector = [end[0] - start[0], end[1] - start[1]];
|
|
318
|
+
return vector;
|
|
319
|
+
}
|
|
248
320
|
|
|
249
|
-
const
|
|
321
|
+
const HexagonEngine = {
|
|
250
322
|
draw(board, rectangle, options) {
|
|
251
|
-
const points =
|
|
323
|
+
const points = getHexagonPoints(rectangle);
|
|
252
324
|
const rs = PlaitBoard.getRoughSVG(board);
|
|
253
325
|
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
254
326
|
setStrokeLinecap(polygon, 'round');
|
|
255
327
|
return polygon;
|
|
256
328
|
},
|
|
257
329
|
isHit(rectangle, point) {
|
|
258
|
-
const parallelogramPoints =
|
|
330
|
+
const parallelogramPoints = getHexagonPoints(rectangle);
|
|
259
331
|
return isPointInPolygon(point, parallelogramPoints);
|
|
260
332
|
},
|
|
333
|
+
getCornerPoints(rectangle) {
|
|
334
|
+
return getHexagonPoints(rectangle);
|
|
335
|
+
},
|
|
336
|
+
getNearestPoint(rectangle, point) {
|
|
337
|
+
return getNearestPointBetweenPointAndSegments(point, getHexagonPoints(rectangle));
|
|
338
|
+
},
|
|
339
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
340
|
+
const corners = getHexagonPoints(rectangle);
|
|
341
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
342
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
343
|
+
},
|
|
344
|
+
getConnectorPoints(rectangle) {
|
|
345
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
const getHexagonPoints = (rectangle) => {
|
|
349
|
+
return [
|
|
350
|
+
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
351
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y],
|
|
352
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
353
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height],
|
|
354
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
355
|
+
[rectangle.x, rectangle.y + rectangle.height / 2]
|
|
356
|
+
];
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const LeftArrowEngine = {
|
|
360
|
+
draw(board, rectangle, options) {
|
|
361
|
+
const points = getLeftArrowPoints(rectangle);
|
|
362
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
363
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
364
|
+
setStrokeLinecap(polygon, 'round');
|
|
365
|
+
return polygon;
|
|
366
|
+
},
|
|
367
|
+
getCornerPoints(rectangle) {
|
|
368
|
+
return getLeftArrowPoints(rectangle);
|
|
369
|
+
},
|
|
370
|
+
isHit(rectangle, point) {
|
|
371
|
+
const points = getLeftArrowPoints(rectangle);
|
|
372
|
+
return isPointInPolygon(point, points);
|
|
373
|
+
},
|
|
261
374
|
getNearestPoint(rectangle, point) {
|
|
262
|
-
const cornerPoints =
|
|
375
|
+
const cornerPoints = getLeftArrowPoints(rectangle);
|
|
263
376
|
return getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
264
377
|
},
|
|
378
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
379
|
+
const corners = getLeftArrowPoints(rectangle);
|
|
380
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
381
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
382
|
+
},
|
|
383
|
+
getConnectorPoints(rectangle) {
|
|
384
|
+
return [
|
|
385
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
386
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2]
|
|
387
|
+
];
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
const getLeftArrowPoints = (rectangle) => {
|
|
391
|
+
return [
|
|
392
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
393
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y],
|
|
394
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y + rectangle.height * 0.2],
|
|
395
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * 0.2],
|
|
396
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * 0.8],
|
|
397
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y + rectangle.height * 0.8],
|
|
398
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y + rectangle.height]
|
|
399
|
+
];
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const OctagonEngine = {
|
|
403
|
+
draw(board, rectangle, options) {
|
|
404
|
+
const points = getOctagonPoints(rectangle);
|
|
405
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
406
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
407
|
+
setStrokeLinecap(polygon, 'round');
|
|
408
|
+
return polygon;
|
|
409
|
+
},
|
|
410
|
+
isHit(rectangle, point) {
|
|
411
|
+
const parallelogramPoints = getOctagonPoints(rectangle);
|
|
412
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
413
|
+
},
|
|
414
|
+
getCornerPoints(rectangle) {
|
|
415
|
+
return getOctagonPoints(rectangle);
|
|
416
|
+
},
|
|
417
|
+
getNearestPoint(rectangle, point) {
|
|
418
|
+
return getNearestPointBetweenPointAndSegments(point, getOctagonPoints(rectangle));
|
|
419
|
+
},
|
|
420
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
421
|
+
const corners = getOctagonPoints(rectangle);
|
|
422
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
423
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
424
|
+
},
|
|
425
|
+
getConnectorPoints(rectangle) {
|
|
426
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const getOctagonPoints = (rectangle) => {
|
|
430
|
+
return [
|
|
431
|
+
[rectangle.x + (rectangle.width * 3) / 10, rectangle.y],
|
|
432
|
+
[rectangle.x + (rectangle.width * 7) / 10, rectangle.y],
|
|
433
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 3) / 10],
|
|
434
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 7) / 10],
|
|
435
|
+
[rectangle.x + (rectangle.width * 7) / 10, rectangle.y + rectangle.height],
|
|
436
|
+
[rectangle.x + (rectangle.width * 3) / 10, rectangle.y + rectangle.height],
|
|
437
|
+
[rectangle.x, rectangle.y + (rectangle.height * 7) / 10],
|
|
438
|
+
[rectangle.x, rectangle.y + (rectangle.height * 3) / 10]
|
|
439
|
+
];
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const ParallelogramEngine = {
|
|
443
|
+
draw(board, rectangle, options) {
|
|
444
|
+
const points = getParallelogramCornerPoints(rectangle);
|
|
445
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
446
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
447
|
+
setStrokeLinecap(polygon, 'round');
|
|
448
|
+
return polygon;
|
|
449
|
+
},
|
|
450
|
+
isHit(rectangle, point) {
|
|
451
|
+
const parallelogramPoints = getParallelogramCornerPoints(rectangle);
|
|
452
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
453
|
+
},
|
|
454
|
+
getCornerPoints(rectangle) {
|
|
455
|
+
return getParallelogramCornerPoints(rectangle);
|
|
456
|
+
},
|
|
457
|
+
getNearestPoint(rectangle, point) {
|
|
458
|
+
return getNearestPointBetweenPointAndSegments(point, ParallelogramEngine.getCornerPoints(rectangle));
|
|
459
|
+
},
|
|
460
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
461
|
+
const corners = getParallelogramCornerPoints(rectangle);
|
|
462
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
463
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
464
|
+
},
|
|
265
465
|
getConnectorPoints(rectangle) {
|
|
266
|
-
const cornerPoints =
|
|
466
|
+
const cornerPoints = getParallelogramCornerPoints(rectangle);
|
|
267
467
|
return getCenterPointsOnPolygon(cornerPoints);
|
|
268
468
|
}
|
|
269
469
|
};
|
|
270
|
-
const
|
|
470
|
+
const getParallelogramCornerPoints = (rectangle) => {
|
|
271
471
|
return [
|
|
272
472
|
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
273
473
|
[rectangle.x + rectangle.width, rectangle.y],
|
|
@@ -276,6 +476,119 @@ const getParallelogramPoints = (rectangle) => {
|
|
|
276
476
|
];
|
|
277
477
|
};
|
|
278
478
|
|
|
479
|
+
const PentagonEngine = {
|
|
480
|
+
draw(board, rectangle, options) {
|
|
481
|
+
const points = getPentagonPoints(rectangle);
|
|
482
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
483
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
484
|
+
setStrokeLinecap(polygon, 'round');
|
|
485
|
+
return polygon;
|
|
486
|
+
},
|
|
487
|
+
isHit(rectangle, point) {
|
|
488
|
+
const parallelogramPoints = getPentagonPoints(rectangle);
|
|
489
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
490
|
+
},
|
|
491
|
+
getCornerPoints(rectangle) {
|
|
492
|
+
return getPentagonPoints(rectangle);
|
|
493
|
+
},
|
|
494
|
+
getNearestPoint(rectangle, point) {
|
|
495
|
+
return getNearestPointBetweenPointAndSegments(point, getPentagonPoints(rectangle));
|
|
496
|
+
},
|
|
497
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
498
|
+
const corners = getPentagonPoints(rectangle);
|
|
499
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
500
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
501
|
+
},
|
|
502
|
+
getConnectorPoints(rectangle) {
|
|
503
|
+
return getPentagonPoints(rectangle);
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
const getPentagonPoints = (rectangle) => {
|
|
507
|
+
return [
|
|
508
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
509
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 2) / 5],
|
|
510
|
+
[rectangle.x + (rectangle.width * 4) / 5, rectangle.y + rectangle.height],
|
|
511
|
+
[rectangle.x + rectangle.width / 5, rectangle.y + rectangle.height],
|
|
512
|
+
[rectangle.x, rectangle.y + (rectangle.height * 2) / 5]
|
|
513
|
+
];
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const PentagonArrowEngine = {
|
|
517
|
+
draw(board, rectangle, options) {
|
|
518
|
+
const points = getPentagonArrowPoints(rectangle);
|
|
519
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
520
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
521
|
+
setStrokeLinecap(polygon, 'round');
|
|
522
|
+
return polygon;
|
|
523
|
+
},
|
|
524
|
+
isHit(rectangle, point) {
|
|
525
|
+
const parallelogramPoints = getPentagonArrowPoints(rectangle);
|
|
526
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
527
|
+
},
|
|
528
|
+
getCornerPoints(rectangle) {
|
|
529
|
+
return getPentagonArrowPoints(rectangle);
|
|
530
|
+
},
|
|
531
|
+
getNearestPoint(rectangle, point) {
|
|
532
|
+
return getNearestPointBetweenPointAndSegments(point, getPentagonArrowPoints(rectangle));
|
|
533
|
+
},
|
|
534
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
535
|
+
const corners = getPentagonArrowPoints(rectangle);
|
|
536
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
537
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
538
|
+
},
|
|
539
|
+
getConnectorPoints(rectangle) {
|
|
540
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
const getPentagonArrowPoints = (rectangle) => {
|
|
544
|
+
return [
|
|
545
|
+
[rectangle.x, rectangle.y],
|
|
546
|
+
[rectangle.x + (rectangle.width * 3) / 5, rectangle.y],
|
|
547
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
548
|
+
[rectangle.x + (rectangle.width * 3) / 5, rectangle.y + rectangle.height],
|
|
549
|
+
[rectangle.x, rectangle.y + rectangle.height]
|
|
550
|
+
];
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
const ProcessArrowEngine = {
|
|
554
|
+
draw(board, rectangle, options) {
|
|
555
|
+
const points = getProcessArrowPoints(rectangle);
|
|
556
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
557
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
558
|
+
setStrokeLinecap(polygon, 'round');
|
|
559
|
+
return polygon;
|
|
560
|
+
},
|
|
561
|
+
isHit(rectangle, point) {
|
|
562
|
+
const parallelogramPoints = getProcessArrowPoints(rectangle);
|
|
563
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
564
|
+
},
|
|
565
|
+
getCornerPoints(rectangle) {
|
|
566
|
+
return getProcessArrowPoints(rectangle);
|
|
567
|
+
},
|
|
568
|
+
getNearestPoint(rectangle, point) {
|
|
569
|
+
return getNearestPointBetweenPointAndSegments(point, getProcessArrowPoints(rectangle));
|
|
570
|
+
},
|
|
571
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
572
|
+
const corners = getProcessArrowPoints(rectangle);
|
|
573
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
574
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
575
|
+
},
|
|
576
|
+
getConnectorPoints(rectangle) {
|
|
577
|
+
return getProcessArrowPoints(rectangle);
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
const getProcessArrowPoints = (rectangle) => {
|
|
581
|
+
const wider = rectangle.width > rectangle.height / 2;
|
|
582
|
+
return [
|
|
583
|
+
[rectangle.x, rectangle.y],
|
|
584
|
+
[rectangle.x + (wider ? rectangle.width - rectangle.height / 2 : 0), rectangle.y],
|
|
585
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
586
|
+
[rectangle.x + (wider ? rectangle.width - rectangle.height / 2 : 0), rectangle.y + rectangle.height],
|
|
587
|
+
[rectangle.x, rectangle.y + rectangle.height],
|
|
588
|
+
[rectangle.x + (wider ? rectangle.height / 2 : rectangle.width), rectangle.y + rectangle.height / 2]
|
|
589
|
+
];
|
|
590
|
+
};
|
|
591
|
+
|
|
279
592
|
const RectangleEngine = {
|
|
280
593
|
draw(board, rectangle, options) {
|
|
281
594
|
return drawRectangle(board, rectangle, { ...options, fillStyle: 'solid' });
|
|
@@ -284,15 +597,65 @@ const RectangleEngine = {
|
|
|
284
597
|
const rangeRectangle = RectangleClient.toRectangleClient([point, point]);
|
|
285
598
|
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
286
599
|
},
|
|
600
|
+
getCornerPoints(rectangle) {
|
|
601
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
602
|
+
},
|
|
287
603
|
getNearestPoint(rectangle, point) {
|
|
288
|
-
|
|
289
|
-
|
|
604
|
+
return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
605
|
+
},
|
|
606
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
607
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
608
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
609
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
290
610
|
},
|
|
291
611
|
getConnectorPoints(rectangle) {
|
|
292
612
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
293
613
|
}
|
|
294
614
|
};
|
|
295
615
|
|
|
616
|
+
const RightArrowEngine = {
|
|
617
|
+
draw(board, rectangle, options) {
|
|
618
|
+
const points = getRightArrowPoints(rectangle);
|
|
619
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
620
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
621
|
+
setStrokeLinecap(polygon, 'round');
|
|
622
|
+
return polygon;
|
|
623
|
+
},
|
|
624
|
+
getCornerPoints(rectangle) {
|
|
625
|
+
return getRightArrowPoints(rectangle);
|
|
626
|
+
},
|
|
627
|
+
isHit(rectangle, point) {
|
|
628
|
+
const points = getRightArrowPoints(rectangle);
|
|
629
|
+
return isPointInPolygon(point, points);
|
|
630
|
+
},
|
|
631
|
+
getNearestPoint(rectangle, point) {
|
|
632
|
+
const cornerPoints = getRightArrowPoints(rectangle);
|
|
633
|
+
return getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
634
|
+
},
|
|
635
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
636
|
+
const corners = getRightArrowPoints(rectangle);
|
|
637
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
638
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
639
|
+
},
|
|
640
|
+
getConnectorPoints(rectangle) {
|
|
641
|
+
return [
|
|
642
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
643
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2]
|
|
644
|
+
];
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
const getRightArrowPoints = (rectangle) => {
|
|
648
|
+
return [
|
|
649
|
+
[rectangle.x, rectangle.y + rectangle.height * 0.2],
|
|
650
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y + rectangle.height * 0.2],
|
|
651
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y],
|
|
652
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
653
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y + rectangle.height],
|
|
654
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y + rectangle.height * 0.8],
|
|
655
|
+
[rectangle.x, rectangle.y + rectangle.height * 0.8]
|
|
656
|
+
];
|
|
657
|
+
};
|
|
658
|
+
|
|
296
659
|
const RoundRectangleEngine = {
|
|
297
660
|
draw(board, rectangle, options) {
|
|
298
661
|
return drawRoundRectangle(PlaitBoard.getRoughSVG(board), rectangle.x, rectangle.y, rectangle.x + rectangle.width, rectangle.y + rectangle.height, { ...options, fillStyle: 'solid' }, false, getRoundRectangleRadius(rectangle));
|
|
@@ -300,9 +663,17 @@ const RoundRectangleEngine = {
|
|
|
300
663
|
isHit(rectangle, point) {
|
|
301
664
|
return isPointInRoundRectangle(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
302
665
|
},
|
|
666
|
+
getCornerPoints(rectangle) {
|
|
667
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
668
|
+
},
|
|
303
669
|
getNearestPoint(rectangle, point) {
|
|
304
670
|
return getNearestPointBetweenPointAndRoundRectangle(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
305
671
|
},
|
|
672
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
673
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
674
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
675
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
676
|
+
},
|
|
306
677
|
getConnectorPoints(rectangle) {
|
|
307
678
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
308
679
|
}
|
|
@@ -340,18 +711,279 @@ function getNearestPointBetweenPointAndRoundRectangle(point, rectangle, radius)
|
|
|
340
711
|
return result;
|
|
341
712
|
}
|
|
342
713
|
|
|
714
|
+
const heightRatio = 3 / 4;
|
|
715
|
+
const RoundCommentEngine = {
|
|
716
|
+
draw(board, rectangle, options) {
|
|
717
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
718
|
+
const x1 = rectangle.x;
|
|
719
|
+
const y1 = rectangle.y;
|
|
720
|
+
const x2 = rectangle.x + rectangle.width;
|
|
721
|
+
const y2 = rectangle.y + rectangle.height * heightRatio;
|
|
722
|
+
const radius = getRoundRectangleRadius(rectangle);
|
|
723
|
+
const point1 = [x1 + radius, y1];
|
|
724
|
+
const point2 = [x2 - radius, y1];
|
|
725
|
+
const point3 = [x2, y1 + radius];
|
|
726
|
+
const point4 = [x2, y2 - radius];
|
|
727
|
+
const point5 = [x2 - radius, y2];
|
|
728
|
+
const point6 = [x1 + radius, y2];
|
|
729
|
+
const point7 = [x1, y2 - radius];
|
|
730
|
+
const point8 = [x1, y1 + radius];
|
|
731
|
+
const point9 = [x1 + rectangle.width / 4, y2];
|
|
732
|
+
const point10 = [x1 + rectangle.width / 4, rectangle.y + rectangle.height];
|
|
733
|
+
const point11 = [x1 + rectangle.width / 2, y2];
|
|
734
|
+
return rs.path(`M${point2[0]} ${point2[1]} A ${radius} ${radius}, 0, 0, 1, ${point3[0]} ${point3[1]} L ${point4[0]} ${point4[1]} A ${radius} ${radius}, 0, 0, 1, ${point5[0]} ${point5[1]} L ${point11[0]} ${point11[1]} ${point10[0]} ${point10[1]} ${point9[0]} ${point9[1]} ${point6[0]} ${point6[1]} A ${radius} ${radius}, 0, 0, 1, ${point7[0]} ${point7[1]} L ${point8[0]} ${point8[1]} A ${radius} ${radius}, 0, 0, 1, ${point1[0]} ${point1[1]} Z`, options);
|
|
735
|
+
},
|
|
736
|
+
isHit(rectangle, point) {
|
|
737
|
+
const points = [
|
|
738
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + (rectangle.height * 3) / 4],
|
|
739
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
740
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + (rectangle.height * 3) / 4]
|
|
741
|
+
];
|
|
742
|
+
rectangle.height = (rectangle.height * 3) / 4;
|
|
743
|
+
return isPointInPolygon(point, points) || isPointInRoundRectangle(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
744
|
+
},
|
|
745
|
+
getCornerPoints(rectangle) {
|
|
746
|
+
return getRoundCommentPoints(rectangle);
|
|
747
|
+
},
|
|
748
|
+
getNearestPoint(rectangle, point) {
|
|
749
|
+
return getNearestPointBetweenPointAndSegments(point, getRoundCommentPoints(rectangle));
|
|
750
|
+
},
|
|
751
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
752
|
+
const corners = getRoundCommentPoints(rectangle);
|
|
753
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
754
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
755
|
+
},
|
|
756
|
+
getConnectorPoints(rectangle) {
|
|
757
|
+
return [
|
|
758
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
759
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
760
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height * heightRatio],
|
|
761
|
+
[rectangle.x, rectangle.y + rectangle.height / 2]
|
|
762
|
+
];
|
|
763
|
+
},
|
|
764
|
+
getTextRectangle(element) {
|
|
765
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
766
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
767
|
+
const height = element.textHeight;
|
|
768
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
769
|
+
return {
|
|
770
|
+
height,
|
|
771
|
+
width: width > 0 ? width : 0,
|
|
772
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
773
|
+
y: elementRectangle.y + (elementRectangle.height * heightRatio - height) / 2
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
const getRoundCommentPoints = (rectangle) => {
|
|
778
|
+
return [
|
|
779
|
+
[rectangle.x, rectangle.y],
|
|
780
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
781
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * heightRatio],
|
|
782
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height * heightRatio],
|
|
783
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
784
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height * heightRatio],
|
|
785
|
+
[rectangle.x, rectangle.y + rectangle.height * heightRatio]
|
|
786
|
+
];
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
const StarEngine = {
|
|
790
|
+
draw(board, rectangle, options) {
|
|
791
|
+
const points = getStarPoints(rectangle);
|
|
792
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
793
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
794
|
+
setStrokeLinecap(polygon, 'round');
|
|
795
|
+
return polygon;
|
|
796
|
+
},
|
|
797
|
+
isHit(rectangle, point) {
|
|
798
|
+
const parallelogramPoints = getStarPoints(rectangle);
|
|
799
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
800
|
+
},
|
|
801
|
+
getCornerPoints(rectangle) {
|
|
802
|
+
return getStarPoints(rectangle);
|
|
803
|
+
},
|
|
804
|
+
getNearestPoint(rectangle, point) {
|
|
805
|
+
return getNearestPointBetweenPointAndSegments(point, getStarPoints(rectangle));
|
|
806
|
+
},
|
|
807
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
808
|
+
const corners = getStarPoints(rectangle);
|
|
809
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
810
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
811
|
+
},
|
|
812
|
+
getConnectorPoints(rectangle) {
|
|
813
|
+
const points = getStarPoints(rectangle);
|
|
814
|
+
return [points[1], points[3], points[5], points[7], points[9]];
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
const getStarPoints = (rectangle) => {
|
|
818
|
+
return [
|
|
819
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + (rectangle.height * 75) / 91],
|
|
820
|
+
[rectangle.x + (rectangle.width * 18.61) / 96, rectangle.y + rectangle.height],
|
|
821
|
+
[rectangle.x + (rectangle.width * 24.2235871) / 96, rectangle.y + (rectangle.height * 57.7254249) / 91],
|
|
822
|
+
[rectangle.x, rectangle.y + (rectangle.height * 34.5491503) / 91],
|
|
823
|
+
[rectangle.x + (rectangle.width * 33.3053687) / 96, rectangle.y + (rectangle.height * 29.7745751) / 91],
|
|
824
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
825
|
+
[rectangle.x + (rectangle.width * 62.6946313) / 96, rectangle.y + (rectangle.height * 29.7745751) / 91],
|
|
826
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 34.5491503) / 91],
|
|
827
|
+
[rectangle.x + (rectangle.width * 71.7764129) / 96, rectangle.y + (rectangle.height * 57.7254249) / 91],
|
|
828
|
+
[rectangle.x + (rectangle.width * 77.3892626) / 96, rectangle.y + rectangle.height]
|
|
829
|
+
];
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
const TrapezoidEngine = {
|
|
833
|
+
draw(board, rectangle, options) {
|
|
834
|
+
const points = getTrapezoidPoints(rectangle);
|
|
835
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
836
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
837
|
+
setStrokeLinecap(polygon, 'round');
|
|
838
|
+
return polygon;
|
|
839
|
+
},
|
|
840
|
+
isHit(rectangle, point) {
|
|
841
|
+
const points = getTrapezoidPoints(rectangle);
|
|
842
|
+
return isPointInPolygon(point, points);
|
|
843
|
+
},
|
|
844
|
+
getNearestPoint(rectangle, point) {
|
|
845
|
+
const cornerPoints = getTrapezoidPoints(rectangle);
|
|
846
|
+
return getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
847
|
+
},
|
|
848
|
+
getConnectorPoints(rectangle) {
|
|
849
|
+
const points = getTrapezoidPoints(rectangle);
|
|
850
|
+
return getCenterPointsOnPolygon(points);
|
|
851
|
+
},
|
|
852
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
853
|
+
const corners = getTrapezoidPoints(rectangle);
|
|
854
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
855
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
856
|
+
},
|
|
857
|
+
getCornerPoints(rectangle) {
|
|
858
|
+
return getTrapezoidPoints(rectangle);
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
const getTrapezoidPoints = (rectangle) => {
|
|
862
|
+
return [
|
|
863
|
+
[rectangle.x + rectangle.width * 0.15, rectangle.y],
|
|
864
|
+
[rectangle.x + rectangle.width * 0.85, rectangle.y],
|
|
865
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
|
|
866
|
+
[rectangle.x, rectangle.y + rectangle.height]
|
|
867
|
+
];
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
const TriangleEngine = {
|
|
871
|
+
draw(board, rectangle, options) {
|
|
872
|
+
const points = getTrianglePoints(rectangle);
|
|
873
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
874
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
875
|
+
setStrokeLinecap(polygon, 'round');
|
|
876
|
+
return polygon;
|
|
877
|
+
},
|
|
878
|
+
isHit(rectangle, point) {
|
|
879
|
+
const points = getTrianglePoints(rectangle);
|
|
880
|
+
return isPointInPolygon(point, points);
|
|
881
|
+
},
|
|
882
|
+
getNearestPoint(rectangle, point) {
|
|
883
|
+
const cornerPoints = getTrianglePoints(rectangle);
|
|
884
|
+
return getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
885
|
+
},
|
|
886
|
+
getConnectorPoints(rectangle) {
|
|
887
|
+
const cornerPoints = getTrianglePoints(rectangle);
|
|
888
|
+
const lineCenterPoints = getCenterPointsOnPolygon(cornerPoints);
|
|
889
|
+
return [...lineCenterPoints, ...cornerPoints];
|
|
890
|
+
},
|
|
891
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
892
|
+
const corners = getTrianglePoints(rectangle);
|
|
893
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
894
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
895
|
+
},
|
|
896
|
+
getCornerPoints(rectangle) {
|
|
897
|
+
return getTrianglePoints(rectangle);
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
const getTrianglePoints = (rectangle) => {
|
|
901
|
+
return [
|
|
902
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
903
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
|
|
904
|
+
[rectangle.x, rectangle.y + rectangle.height]
|
|
905
|
+
];
|
|
906
|
+
};
|
|
907
|
+
|
|
908
|
+
const TwoWayArrowEngine = {
|
|
909
|
+
draw(board, rectangle, options) {
|
|
910
|
+
const points = getTwoWayArrowPoints(rectangle);
|
|
911
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
912
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
913
|
+
setStrokeLinecap(polygon, 'round');
|
|
914
|
+
return polygon;
|
|
915
|
+
},
|
|
916
|
+
getCornerPoints(rectangle) {
|
|
917
|
+
return getTwoWayArrowPoints(rectangle);
|
|
918
|
+
},
|
|
919
|
+
isHit(rectangle, point) {
|
|
920
|
+
const points = getTwoWayArrowPoints(rectangle);
|
|
921
|
+
return isPointInPolygon(point, points);
|
|
922
|
+
},
|
|
923
|
+
getNearestPoint(rectangle, point) {
|
|
924
|
+
const cornerPoints = getTwoWayArrowPoints(rectangle);
|
|
925
|
+
return getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
926
|
+
},
|
|
927
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
928
|
+
const corners = getTwoWayArrowPoints(rectangle);
|
|
929
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
930
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
931
|
+
},
|
|
932
|
+
getConnectorPoints(rectangle) {
|
|
933
|
+
return [
|
|
934
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
935
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2]
|
|
936
|
+
];
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
const getTwoWayArrowPoints = (rectangle) => {
|
|
940
|
+
return [
|
|
941
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
942
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y],
|
|
943
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y + rectangle.height / 5],
|
|
944
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y + rectangle.height / 5],
|
|
945
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y],
|
|
946
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
947
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y + rectangle.height],
|
|
948
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y + (rectangle.height * 4) / 5],
|
|
949
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y + (rectangle.height * 4) / 5],
|
|
950
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y + rectangle.height]
|
|
951
|
+
];
|
|
952
|
+
};
|
|
953
|
+
|
|
343
954
|
const ShapeEngineMap = {
|
|
344
955
|
[GeometryShape.rectangle]: RectangleEngine,
|
|
345
956
|
[GeometryShape.diamond]: DiamondEngine,
|
|
346
957
|
[GeometryShape.ellipse]: EllipseEngine,
|
|
347
958
|
[GeometryShape.parallelogram]: ParallelogramEngine,
|
|
348
959
|
[GeometryShape.roundRectangle]: RoundRectangleEngine,
|
|
349
|
-
[GeometryShape.text]: RectangleEngine
|
|
960
|
+
[GeometryShape.text]: RectangleEngine,
|
|
961
|
+
[GeometryShape.triangle]: TriangleEngine,
|
|
962
|
+
[GeometryShape.leftArrow]: LeftArrowEngine,
|
|
963
|
+
[GeometryShape.trapezoid]: TrapezoidEngine,
|
|
964
|
+
[GeometryShape.rightArrow]: RightArrowEngine,
|
|
965
|
+
[GeometryShape.cross]: CrossEngine,
|
|
966
|
+
[GeometryShape.star]: StarEngine,
|
|
967
|
+
[GeometryShape.pentagon]: PentagonEngine,
|
|
968
|
+
[GeometryShape.hexagon]: HexagonEngine,
|
|
969
|
+
[GeometryShape.octagon]: OctagonEngine,
|
|
970
|
+
[GeometryShape.pentagonArrow]: PentagonArrowEngine,
|
|
971
|
+
[GeometryShape.processArrow]: ProcessArrowEngine,
|
|
972
|
+
[GeometryShape.twoWayArrow]: TwoWayArrowEngine,
|
|
973
|
+
[GeometryShape.comment]: CommentEngine,
|
|
974
|
+
[GeometryShape.roundComment]: RoundCommentEngine
|
|
350
975
|
};
|
|
351
976
|
const getEngine = (shape) => {
|
|
352
977
|
return ShapeEngineMap[shape];
|
|
353
978
|
};
|
|
354
979
|
|
|
980
|
+
const getShape = (value) => {
|
|
981
|
+
if (PlaitDrawElement.isImage(value)) {
|
|
982
|
+
return GeometryShape.rectangle;
|
|
983
|
+
}
|
|
984
|
+
return value.shape;
|
|
985
|
+
};
|
|
986
|
+
|
|
355
987
|
const createGeometryElement = (shape, points, text, options) => {
|
|
356
988
|
let textOptions = {};
|
|
357
989
|
let alignment = Alignment.center;
|
|
@@ -393,14 +1025,15 @@ const drawBoundMask = (board, element) => {
|
|
|
393
1025
|
const G = createG();
|
|
394
1026
|
const rectangle = getRectangleByPoints(element.points);
|
|
395
1027
|
const activeRectangle = RectangleClient.inflate(rectangle, ACTIVE_STROKE_WIDTH);
|
|
396
|
-
const
|
|
1028
|
+
const shape = getShape(element);
|
|
1029
|
+
const maskG = drawGeometry(board, activeRectangle, shape, {
|
|
397
1030
|
stroke: SELECTION_BORDER_COLOR,
|
|
398
1031
|
strokeWidth: 1,
|
|
399
1032
|
fill: SELECTION_FILL_COLOR,
|
|
400
1033
|
fillStyle: 'solid'
|
|
401
1034
|
});
|
|
402
1035
|
G.appendChild(maskG);
|
|
403
|
-
const connectorPoints = getEngine(
|
|
1036
|
+
const connectorPoints = getEngine(shape).getConnectorPoints(activeRectangle);
|
|
404
1037
|
connectorPoints.forEach(point => {
|
|
405
1038
|
const circleG = drawCircle(PlaitBoard.getRoughSVG(board), point, 6, {
|
|
406
1039
|
stroke: '#999999',
|
|
@@ -418,7 +1051,8 @@ const drawGeometry = (board, outerRectangle, shape, options) => {
|
|
|
418
1051
|
const getNearestPoint = (element, point, inflateDelta = 0) => {
|
|
419
1052
|
const rectangle = getRectangleByPoints(element.points);
|
|
420
1053
|
const activeRectangle = RectangleClient.inflate(rectangle, inflateDelta);
|
|
421
|
-
|
|
1054
|
+
const shape = getShape(element);
|
|
1055
|
+
return getEngine(shape).getNearestPoint(activeRectangle, point);
|
|
422
1056
|
};
|
|
423
1057
|
const getCenterPointsOnPolygon = (points) => {
|
|
424
1058
|
const centerPoint = [];
|
|
@@ -428,6 +1062,17 @@ const getCenterPointsOnPolygon = (points) => {
|
|
|
428
1062
|
}
|
|
429
1063
|
return centerPoint;
|
|
430
1064
|
};
|
|
1065
|
+
const getEdgeOnPolygonByPoint = (corners, point) => {
|
|
1066
|
+
for (let index = 1; index <= corners.length; index++) {
|
|
1067
|
+
let start = corners[index - 1];
|
|
1068
|
+
let end = index === corners.length ? corners[0] : corners[index];
|
|
1069
|
+
const distance = distanceBetweenPointAndSegment(point[0], point[1], start[0], start[1], end[0], end[1]);
|
|
1070
|
+
if (distance < 1) {
|
|
1071
|
+
return [start, end];
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
return null;
|
|
1075
|
+
};
|
|
431
1076
|
|
|
432
1077
|
const drawLineArrow = (element, points, options) => {
|
|
433
1078
|
const arrowG = createG();
|
|
@@ -435,16 +1080,19 @@ const drawLineArrow = (element, points, options) => {
|
|
|
435
1080
|
return null;
|
|
436
1081
|
}
|
|
437
1082
|
if (!PlaitLine.isSourceMark(element, LineMarkerType.none)) {
|
|
438
|
-
const
|
|
1083
|
+
const source = getExtendPoint(points[0], points[1], 24);
|
|
1084
|
+
const sourceArrow = getArrow(element, { marker: element.source.marker, source, target: points[0], isSource: true }, options);
|
|
439
1085
|
sourceArrow && arrowG.appendChild(sourceArrow);
|
|
440
1086
|
}
|
|
441
1087
|
if (!PlaitLine.isTargetMark(element, LineMarkerType.none)) {
|
|
442
|
-
const
|
|
1088
|
+
const source = getExtendPoint(points[points.length - 1], points[points.length - 2], 24);
|
|
1089
|
+
const arrow = getArrow(element, { marker: element.target.marker, source, target: points[points.length - 1], isSource: false }, options);
|
|
443
1090
|
arrow && arrowG.appendChild(arrow);
|
|
444
1091
|
}
|
|
445
1092
|
return arrowG;
|
|
446
1093
|
};
|
|
447
|
-
const getArrow = (element,
|
|
1094
|
+
const getArrow = (element, arrowOptions, options) => {
|
|
1095
|
+
const { marker, source, target, isSource } = arrowOptions;
|
|
448
1096
|
let targetArrow;
|
|
449
1097
|
switch (marker) {
|
|
450
1098
|
case LineMarkerType.openTriangle: {
|
|
@@ -459,20 +1107,31 @@ const getArrow = (element, marker, source, target, options) => {
|
|
|
459
1107
|
targetArrow = drawArrow(element, source, target, options);
|
|
460
1108
|
break;
|
|
461
1109
|
}
|
|
462
|
-
case LineMarkerType.sharpArrow: {
|
|
463
|
-
targetArrow = drawSharpArrow(source, target, options);
|
|
1110
|
+
case LineMarkerType.sharpArrow: {
|
|
1111
|
+
targetArrow = drawSharpArrow(source, target, options);
|
|
1112
|
+
break;
|
|
1113
|
+
}
|
|
1114
|
+
case LineMarkerType.oneSideUp: {
|
|
1115
|
+
targetArrow = drawOneSideArrow(source, target, 'up', options);
|
|
1116
|
+
break;
|
|
1117
|
+
}
|
|
1118
|
+
case LineMarkerType.oneSideDown: {
|
|
1119
|
+
targetArrow = drawOneSideArrow(source, target, 'down', options);
|
|
1120
|
+
break;
|
|
1121
|
+
}
|
|
1122
|
+
case LineMarkerType.hollowTriangle: {
|
|
1123
|
+
targetArrow = drawHollowTriangleArrow(source, target, options);
|
|
1124
|
+
break;
|
|
1125
|
+
}
|
|
1126
|
+
case LineMarkerType.singleSlash: {
|
|
1127
|
+
targetArrow = drawSingleSlash(source, target, isSource, options);
|
|
464
1128
|
break;
|
|
465
1129
|
}
|
|
466
1130
|
}
|
|
467
1131
|
return targetArrow;
|
|
468
1132
|
};
|
|
469
1133
|
const drawSharpArrow = (source, target, options) => {
|
|
470
|
-
const directionFactor = getFactorByPoints(source, target);
|
|
471
1134
|
const startPoint = target;
|
|
472
|
-
// const startPoint: Point = [
|
|
473
|
-
// target[0],
|
|
474
|
-
// target[1]
|
|
475
|
-
// ];
|
|
476
1135
|
const { pointLeft, pointRight } = arrowPoints(source, target, 12, 20);
|
|
477
1136
|
const g = createG();
|
|
478
1137
|
const path = createPath();
|
|
@@ -487,10 +1146,7 @@ const drawSharpArrow = (source, target, options) => {
|
|
|
487
1146
|
const drawArrow = (element, source, target, options) => {
|
|
488
1147
|
const directionFactor = getFactorByPoints(source, target);
|
|
489
1148
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
490
|
-
const endPoint = [
|
|
491
|
-
target[0] + strokeWidth * directionFactor.x / 2,
|
|
492
|
-
target[1] + strokeWidth * directionFactor.y / 2
|
|
493
|
-
];
|
|
1149
|
+
const endPoint = [target[0] + (strokeWidth * directionFactor.x) / 2, target[1] + (strokeWidth * directionFactor.y) / 2];
|
|
494
1150
|
const middlePoint = [endPoint[0] - 8 * directionFactor.x, endPoint[1] - 8 * directionFactor.y];
|
|
495
1151
|
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 12, 30);
|
|
496
1152
|
const arrowG = drawLinearPath([pointLeft, endPoint, pointRight, middlePoint], { ...options, fill: options.stroke }, true);
|
|
@@ -506,13 +1162,26 @@ const drawSolidTriangle = (source, target, options) => {
|
|
|
506
1162
|
const drawOpenTriangle = (element, source, target, options) => {
|
|
507
1163
|
const directionFactor = getFactorByPoints(source, target);
|
|
508
1164
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
509
|
-
const endPoint = [
|
|
510
|
-
target[0] + strokeWidth * directionFactor.x / 2,
|
|
511
|
-
target[1] + strokeWidth * directionFactor.y / 2
|
|
512
|
-
];
|
|
1165
|
+
const endPoint = [target[0] + (strokeWidth * directionFactor.x) / 2, target[1] + (strokeWidth * directionFactor.y) / 2];
|
|
513
1166
|
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 12, 40);
|
|
514
1167
|
return drawLinearPath([pointLeft, endPoint, pointRight], options);
|
|
515
1168
|
};
|
|
1169
|
+
const drawOneSideArrow = (source, target, side, options) => {
|
|
1170
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 12, 40);
|
|
1171
|
+
return drawLinearPath([side === 'up' ? pointRight : pointLeft, target], options);
|
|
1172
|
+
};
|
|
1173
|
+
const drawSingleSlash = (source, target, isSource, options) => {
|
|
1174
|
+
source = getExtendPoint(target, source, 12);
|
|
1175
|
+
const middlePoint = getExtendPoint(target, source, 6);
|
|
1176
|
+
const angle = isSource ? 120 : 60;
|
|
1177
|
+
const start = rotate(...source, ...middlePoint, (angle * Math.PI) / 180);
|
|
1178
|
+
const end = rotate(...target, ...middlePoint, (angle * Math.PI) / 180);
|
|
1179
|
+
return drawLinearPath([start, end], options);
|
|
1180
|
+
};
|
|
1181
|
+
const drawHollowTriangleArrow = (source, target, options) => {
|
|
1182
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 12, 30);
|
|
1183
|
+
return drawLinearPath([pointLeft, pointRight, target], { ...options, fill: 'white' }, true);
|
|
1184
|
+
};
|
|
516
1185
|
|
|
517
1186
|
const createLineElement = (shape, points, source, target, options) => {
|
|
518
1187
|
return {
|
|
@@ -528,28 +1197,127 @@ const createLineElement = (shape, points, source, target, options) => {
|
|
|
528
1197
|
};
|
|
529
1198
|
};
|
|
530
1199
|
const getLinePoints = (board, element) => {
|
|
531
|
-
|
|
1200
|
+
switch (element.shape) {
|
|
1201
|
+
case LineShape.elbow: {
|
|
1202
|
+
return getElbowPoints(board, element);
|
|
1203
|
+
}
|
|
1204
|
+
case LineShape.curve: {
|
|
1205
|
+
return getCurvePoints(board, element);
|
|
1206
|
+
}
|
|
1207
|
+
default: {
|
|
1208
|
+
return PlaitLine.getPoints(board, element);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
532
1211
|
};
|
|
533
|
-
const
|
|
534
|
-
|
|
1212
|
+
const getLineHandleRefPair = (board, element) => {
|
|
1213
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1214
|
+
const sourceBoundElement = element.source.boundId ? getElementById(board, element.source.boundId) : undefined;
|
|
1215
|
+
const targetBoundElement = element.target.boundId ? getElementById(board, element.target.boundId) : undefined;
|
|
1216
|
+
let sourcePoint = sourceBoundElement ? getConnectionPoint(sourceBoundElement, element.source.connection) : element.points[0];
|
|
1217
|
+
let targetPoint = targetBoundElement
|
|
1218
|
+
? getConnectionPoint(targetBoundElement, element.target.connection)
|
|
1219
|
+
: element.points[element.points.length - 1];
|
|
1220
|
+
let sourceDirection = getDirectionByVector([targetPoint[0] - sourcePoint[0], targetPoint[1] - sourcePoint[1]]);
|
|
1221
|
+
let targetDirection = getOppositeDirection(sourceDirection);
|
|
1222
|
+
const sourceFactor = getDirectionFactor(sourceDirection);
|
|
1223
|
+
const targetFactor = getDirectionFactor(targetDirection);
|
|
1224
|
+
const sourceHandleRef = {
|
|
1225
|
+
key: LineHandleKey.source,
|
|
1226
|
+
point: sourcePoint,
|
|
1227
|
+
direction: sourceDirection,
|
|
1228
|
+
vector: [sourceFactor.x, sourceFactor.y]
|
|
1229
|
+
};
|
|
1230
|
+
const targetHandleRef = {
|
|
1231
|
+
key: LineHandleKey.target,
|
|
1232
|
+
point: targetPoint,
|
|
1233
|
+
direction: targetDirection,
|
|
1234
|
+
vector: [targetFactor.x, targetFactor.y]
|
|
1235
|
+
};
|
|
1236
|
+
if (sourceBoundElement) {
|
|
1237
|
+
const connectionOffset = PlaitLine.isSourceMarkOrTargetMark(element, LineMarkerType.none, LineHandleKey.source) ? 0 : strokeWidth;
|
|
1238
|
+
const sourceVector = getVectorByConnection(sourceBoundElement, element.source.connection);
|
|
1239
|
+
const direction = getDirectionByVector(sourceVector);
|
|
1240
|
+
sourceDirection = direction ? direction : sourceDirection;
|
|
1241
|
+
sourcePoint = getConnectionPoint(sourceBoundElement, element.source.connection, sourceDirection, connectionOffset);
|
|
1242
|
+
sourceHandleRef.boundElement = sourceBoundElement;
|
|
1243
|
+
sourceHandleRef.direction = sourceDirection;
|
|
1244
|
+
sourceHandleRef.point = sourcePoint;
|
|
1245
|
+
sourceHandleRef.vector = sourceVector;
|
|
1246
|
+
}
|
|
1247
|
+
if (targetBoundElement) {
|
|
1248
|
+
const connectionOffset = PlaitLine.isSourceMarkOrTargetMark(element, LineMarkerType.none, LineHandleKey.target) ? 0 : strokeWidth;
|
|
1249
|
+
const targetVector = getVectorByConnection(targetBoundElement, element.target.connection);
|
|
1250
|
+
const direction = getDirectionByVector(targetVector);
|
|
1251
|
+
targetDirection = direction ? direction : targetDirection;
|
|
1252
|
+
targetPoint = getConnectionPoint(targetBoundElement, element.target.connection, targetDirection, connectionOffset);
|
|
1253
|
+
targetHandleRef.boundElement = targetBoundElement;
|
|
1254
|
+
targetHandleRef.direction = targetDirection;
|
|
1255
|
+
targetHandleRef.point = targetPoint;
|
|
1256
|
+
targetHandleRef.vector = targetVector;
|
|
1257
|
+
}
|
|
1258
|
+
return { source: sourceHandleRef, target: targetHandleRef };
|
|
535
1259
|
};
|
|
536
1260
|
const getElbowPoints = (board, element) => {
|
|
537
1261
|
if (element.points.length === 2) {
|
|
538
|
-
const
|
|
539
|
-
const
|
|
540
|
-
let
|
|
541
|
-
|
|
542
|
-
if (element.source.connection) {
|
|
543
|
-
sourceDirection = getDirectionByPoint(element.source.connection, sourceDirection);
|
|
544
|
-
}
|
|
545
|
-
if (element.target.connection) {
|
|
546
|
-
targetDirection = getDirectionByPoint(element.target.connection, targetDirection);
|
|
547
|
-
}
|
|
548
|
-
const points = getPoints(source, sourceDirection, target, targetDirection, 30);
|
|
1262
|
+
const handleRefPair = getLineHandleRefPair(board, element);
|
|
1263
|
+
const offset = element.source.boundId || element.target.boundId ? 30 : 0;
|
|
1264
|
+
let points = getPoints(handleRefPair.source.point, handleRefPair.source.direction, handleRefPair.target.point, handleRefPair.target.direction, offset);
|
|
1265
|
+
points = removeDuplicatePoints(points);
|
|
549
1266
|
return points;
|
|
550
1267
|
}
|
|
551
1268
|
return element.points;
|
|
552
1269
|
};
|
|
1270
|
+
const getCurvePoints = (board, element) => {
|
|
1271
|
+
if (element.points.length === 2) {
|
|
1272
|
+
const handleRefPair = getLineHandleRefPair(board, element);
|
|
1273
|
+
const { source, target } = handleRefPair;
|
|
1274
|
+
const sourceBoundElement = handleRefPair.source.boundElement;
|
|
1275
|
+
const targetBoundElement = handleRefPair.target.boundElement;
|
|
1276
|
+
let curvePoints = [source.point];
|
|
1277
|
+
const sumDistance = distanceBetweenPointAndPoint(...source.point, ...target.point);
|
|
1278
|
+
const offset = 12 + sumDistance / 3;
|
|
1279
|
+
if (sourceBoundElement) {
|
|
1280
|
+
curvePoints.push(getPointByVector(source.point, source.vector, offset));
|
|
1281
|
+
}
|
|
1282
|
+
if (targetBoundElement) {
|
|
1283
|
+
curvePoints.push(getPointByVector(target.point, target.vector, offset));
|
|
1284
|
+
}
|
|
1285
|
+
const isSingleBound = (sourceBoundElement && !targetBoundElement) || (!sourceBoundElement && targetBoundElement);
|
|
1286
|
+
if (isSingleBound) {
|
|
1287
|
+
curvePoints.push(target.point);
|
|
1288
|
+
const points = Q2C(curvePoints);
|
|
1289
|
+
return pointsOnBezierCurves(points);
|
|
1290
|
+
}
|
|
1291
|
+
if (!sourceBoundElement && !targetBoundElement) {
|
|
1292
|
+
curvePoints.push(getPointByVector(source.point, source.vector, offset));
|
|
1293
|
+
curvePoints.push(getPointByVector(target.point, target.vector, offset));
|
|
1294
|
+
}
|
|
1295
|
+
curvePoints.push(target.point);
|
|
1296
|
+
return pointsOnBezierCurves(curvePoints);
|
|
1297
|
+
}
|
|
1298
|
+
else {
|
|
1299
|
+
//TODO 直接获取贝塞尔曲线上高密度点
|
|
1300
|
+
const points = PlaitLine.getPoints(board, element);
|
|
1301
|
+
const draw = PlaitBoard.getRoughSVG(board).generator.curve(points);
|
|
1302
|
+
let bezierPoints = transformOpsToPoints(draw.sets[0].ops);
|
|
1303
|
+
bezierPoints = removeDuplicatePoints(bezierPoints);
|
|
1304
|
+
return pointsOnBezierCurves(bezierPoints);
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
const transformOpsToPoints = (ops) => {
|
|
1308
|
+
const result = [];
|
|
1309
|
+
for (let item of ops) {
|
|
1310
|
+
if (item.op === 'move') {
|
|
1311
|
+
result.push([item.data[0], item.data[1]]);
|
|
1312
|
+
}
|
|
1313
|
+
else {
|
|
1314
|
+
result.push([item.data[0], item.data[1]]);
|
|
1315
|
+
result.push([item.data[2], item.data[3]]);
|
|
1316
|
+
result.push([item.data[4], item.data[5]]);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
return result;
|
|
1320
|
+
};
|
|
553
1321
|
const isHitPolyLine = (pathPoints, point, strokeWidth, expand = 0) => {
|
|
554
1322
|
const distance = distanceBetweenPointAndSegments(pathPoints, point);
|
|
555
1323
|
return distance <= strokeWidth + expand;
|
|
@@ -579,20 +1347,28 @@ const drawLine = (board, element) => {
|
|
|
579
1347
|
const strokeLineDash = getLineDashByElement(element);
|
|
580
1348
|
const options = { stroke: strokeColor, strokeWidth, strokeLineDash };
|
|
581
1349
|
const lineG = createG();
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
1350
|
+
let points = getLinePoints(board, element);
|
|
1351
|
+
let line;
|
|
1352
|
+
if (element.shape === LineShape.curve) {
|
|
1353
|
+
//TODO element.points 应为曲线拐点
|
|
1354
|
+
line = PlaitBoard.getRoughSVG(board).curve(points, options);
|
|
1355
|
+
}
|
|
1356
|
+
else {
|
|
1357
|
+
line = drawLinearPath(points, options);
|
|
1358
|
+
}
|
|
1359
|
+
const id = idCreator();
|
|
1360
|
+
line.setAttribute('mask', `url(#${id})`);
|
|
585
1361
|
lineG.appendChild(line);
|
|
586
|
-
const { mask, maskTargetFillRect } = drawMask(board, element);
|
|
1362
|
+
const { mask, maskTargetFillRect } = drawMask(board, element, id);
|
|
587
1363
|
lineG.appendChild(mask);
|
|
588
1364
|
line.appendChild(maskTargetFillRect);
|
|
589
1365
|
const arrow = drawLineArrow(element, points, { stroke: strokeColor, strokeWidth });
|
|
590
1366
|
arrow && lineG.appendChild(arrow);
|
|
591
1367
|
return lineG;
|
|
592
1368
|
};
|
|
593
|
-
function drawMask(board, element) {
|
|
1369
|
+
function drawMask(board, element, id) {
|
|
594
1370
|
const mask = createMask();
|
|
595
|
-
mask.setAttribute('id',
|
|
1371
|
+
mask.setAttribute('id', id);
|
|
596
1372
|
const points = getLinePoints(board, element);
|
|
597
1373
|
let rectangle = getRectangleByPoints(points);
|
|
598
1374
|
rectangle = RectangleClient.getOutlineRectangle(rectangle, -30);
|
|
@@ -613,33 +1389,16 @@ function drawMask(board, element) {
|
|
|
613
1389
|
maskTargetFillRect.setAttribute('opacity', '0');
|
|
614
1390
|
return { mask, maskTargetFillRect };
|
|
615
1391
|
}
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const
|
|
620
|
-
const
|
|
621
|
-
return
|
|
1392
|
+
const getConnectionPoint = (geometry, connection, direction, delta) => {
|
|
1393
|
+
const rectangle = getRectangleByPoints(geometry.points);
|
|
1394
|
+
if (direction && delta) {
|
|
1395
|
+
const directionFactor = getDirectionFactor(direction);
|
|
1396
|
+
const point = RectangleClient.getConnectionPoint(rectangle, connection);
|
|
1397
|
+
return [point[0] + directionFactor.x * delta, point[1] + directionFactor.y * delta];
|
|
622
1398
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
const getTargetPoint = (board, element) => {
|
|
626
|
-
if (element.target.boundId) {
|
|
627
|
-
const strokeWidth = getStrokeWidthByElement(element);
|
|
628
|
-
const connectionOffset = PlaitLine.isTargetMark(element, LineMarkerType.none) ? 0 : strokeWidth;
|
|
629
|
-
const boundElement = getElementById(board, element.target.boundId);
|
|
630
|
-
return boundElement
|
|
631
|
-
? getConnectionPoint(boundElement, element.target.connection, connectionOffset)
|
|
632
|
-
: element.points[element.points.length - 1];
|
|
1399
|
+
else {
|
|
1400
|
+
return RectangleClient.getConnectionPoint(rectangle, connection);
|
|
633
1401
|
}
|
|
634
|
-
return element.points[element.points.length - 1];
|
|
635
|
-
};
|
|
636
|
-
const getConnectionPoint = (geometry, connection, offset) => {
|
|
637
|
-
const rectangle = getRectangleByPoints(geometry.points);
|
|
638
|
-
const directionFactor = getDirectionFactor(getDirectionByPoint(connection, Direction.bottom));
|
|
639
|
-
return [
|
|
640
|
-
rectangle.x + rectangle.width * connection[0] + directionFactor.x * offset,
|
|
641
|
-
rectangle.y + rectangle.height * connection[1] + directionFactor.y * offset
|
|
642
|
-
];
|
|
643
1402
|
};
|
|
644
1403
|
const transformPointToConnection = (board, point, hitElement) => {
|
|
645
1404
|
let rectangle = getRectangleByPoints(hitElement.points);
|
|
@@ -650,7 +1409,8 @@ const transformPointToConnection = (board, point, hitElement) => {
|
|
|
650
1409
|
return [(nearestPoint[0] - rectangle.x) / rectangle.width, (nearestPoint[1] - rectangle.y) / rectangle.height];
|
|
651
1410
|
};
|
|
652
1411
|
const getHitConnectorPoint = (movingPoint, hitElement, rectangle) => {
|
|
653
|
-
const
|
|
1412
|
+
const shape = getShape(hitElement);
|
|
1413
|
+
const connector = getEngine(shape).getConnectorPoints(rectangle);
|
|
654
1414
|
const points = getPointsByCenterPoint(movingPoint, 5, 5);
|
|
655
1415
|
const pointRectangle = getRectangleByPoints(points);
|
|
656
1416
|
return connector.find(point => {
|
|
@@ -674,6 +1434,64 @@ const getBoardLines = (board) => {
|
|
|
674
1434
|
recursion: (element) => PlaitDrawElement.isDrawElement(element)
|
|
675
1435
|
});
|
|
676
1436
|
};
|
|
1437
|
+
const removeDuplicatePoints = (points) => {
|
|
1438
|
+
const newArray = [];
|
|
1439
|
+
points.forEach(point => {
|
|
1440
|
+
const index = newArray.findIndex(otherPoint => {
|
|
1441
|
+
return point[0] === otherPoint[0] && point[1] === otherPoint[1];
|
|
1442
|
+
});
|
|
1443
|
+
if (index === -1)
|
|
1444
|
+
newArray.push(point);
|
|
1445
|
+
});
|
|
1446
|
+
return newArray;
|
|
1447
|
+
};
|
|
1448
|
+
const getExtendPoint = (source, target, extendDistance) => {
|
|
1449
|
+
const distance = distanceBetweenPointAndPoint(...source, ...target);
|
|
1450
|
+
const sin = (target[1] - source[1]) / distance;
|
|
1451
|
+
const cos = (target[0] - source[0]) / distance;
|
|
1452
|
+
return [source[0] + extendDistance * cos, source[1] + extendDistance * sin];
|
|
1453
|
+
};
|
|
1454
|
+
// quadratic Bezier to cubic Bezier
|
|
1455
|
+
const Q2C = (points) => {
|
|
1456
|
+
const result = [];
|
|
1457
|
+
const numSegments = points.length / 3;
|
|
1458
|
+
for (let i = 0; i < numSegments; i++) {
|
|
1459
|
+
const start = points[i];
|
|
1460
|
+
const qControl = points[i + 1];
|
|
1461
|
+
const end = points[i + 2];
|
|
1462
|
+
const startDistance = distanceBetweenPointAndPoint(...start, ...qControl);
|
|
1463
|
+
const endDistance = distanceBetweenPointAndPoint(...end, ...qControl);
|
|
1464
|
+
const cControl1 = getExtendPoint(start, qControl, (startDistance * 2) / 3);
|
|
1465
|
+
const cControl2 = getExtendPoint(end, qControl, (endDistance * 2) / 3);
|
|
1466
|
+
result.push(start, cControl1, cControl2, end);
|
|
1467
|
+
}
|
|
1468
|
+
return result;
|
|
1469
|
+
};
|
|
1470
|
+
const getVectorByConnection = (boundElement, connection) => {
|
|
1471
|
+
const rectangle = getRectangleByPoints(boundElement.points);
|
|
1472
|
+
const shape = getShape(boundElement);
|
|
1473
|
+
const engine = getEngine(shape);
|
|
1474
|
+
let vector = [0, 0];
|
|
1475
|
+
const direction = getDirectionByPointOfRectangle(connection);
|
|
1476
|
+
if (direction) {
|
|
1477
|
+
const factor = getDirectionFactor(direction);
|
|
1478
|
+
return [factor.x, factor.y];
|
|
1479
|
+
}
|
|
1480
|
+
if (engine.getEdgeByConnectionPoint) {
|
|
1481
|
+
const edge = engine.getEdgeByConnectionPoint(rectangle, connection);
|
|
1482
|
+
if (edge) {
|
|
1483
|
+
const lineVector = [edge[1][0] - edge[0][0], edge[1][1] - edge[0][1]];
|
|
1484
|
+
return rotateVectorAnti90(lineVector);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
if (engine.getTangentVectorByConnectionPoint) {
|
|
1488
|
+
const lineVector = engine.getTangentVectorByConnectionPoint(rectangle, connection);
|
|
1489
|
+
if (lineVector) {
|
|
1490
|
+
return rotateVectorAnti90(lineVector);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
return vector;
|
|
1494
|
+
};
|
|
677
1495
|
|
|
678
1496
|
const getSelectedDrawElements = (board) => {
|
|
679
1497
|
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isDrawElement(value));
|
|
@@ -687,6 +1505,111 @@ const getSelectedLineElements = (board) => {
|
|
|
687
1505
|
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isLine(value));
|
|
688
1506
|
return selectedElements;
|
|
689
1507
|
};
|
|
1508
|
+
const getSelectedImageElements = (board) => {
|
|
1509
|
+
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isImage(value));
|
|
1510
|
+
return selectedElements;
|
|
1511
|
+
};
|
|
1512
|
+
|
|
1513
|
+
var LineMarkerType;
|
|
1514
|
+
(function (LineMarkerType) {
|
|
1515
|
+
LineMarkerType["arrow"] = "arrow";
|
|
1516
|
+
LineMarkerType["none"] = "none";
|
|
1517
|
+
LineMarkerType["openTriangle"] = "open-triangle";
|
|
1518
|
+
LineMarkerType["solidTriangle"] = "solid-triangle";
|
|
1519
|
+
LineMarkerType["sharpArrow"] = "sharp-arrow";
|
|
1520
|
+
LineMarkerType["oneSideUp"] = "one-side-up";
|
|
1521
|
+
LineMarkerType["oneSideDown"] = "one-side-down";
|
|
1522
|
+
LineMarkerType["hollowTriangle"] = "hollow-triangle";
|
|
1523
|
+
LineMarkerType["singleSlash"] = "single-slash";
|
|
1524
|
+
})(LineMarkerType || (LineMarkerType = {}));
|
|
1525
|
+
var LineShape;
|
|
1526
|
+
(function (LineShape) {
|
|
1527
|
+
LineShape["straight"] = "straight";
|
|
1528
|
+
LineShape["curve"] = "curve";
|
|
1529
|
+
LineShape["elbow"] = "elbow";
|
|
1530
|
+
})(LineShape || (LineShape = {}));
|
|
1531
|
+
var LineHandleKey;
|
|
1532
|
+
(function (LineHandleKey) {
|
|
1533
|
+
LineHandleKey["source"] = "source";
|
|
1534
|
+
LineHandleKey["target"] = "target";
|
|
1535
|
+
})(LineHandleKey || (LineHandleKey = {}));
|
|
1536
|
+
const PlaitLine = {
|
|
1537
|
+
getTextEditors(element) {
|
|
1538
|
+
const component = PlaitElement.getComponent(element);
|
|
1539
|
+
if (component) {
|
|
1540
|
+
const manage = component.textManages.find(manage => manage.isEditing);
|
|
1541
|
+
if (manage) {
|
|
1542
|
+
return [manage.componentRef.instance.editor];
|
|
1543
|
+
}
|
|
1544
|
+
else {
|
|
1545
|
+
return component.textManages.map(manage => manage.componentRef.instance.editor);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
throw new Error('can not get correctly component in get text editor');
|
|
1549
|
+
},
|
|
1550
|
+
isSourceMarkOrTargetMark(line, markType, handleKey) {
|
|
1551
|
+
if (handleKey === LineHandleKey.source) {
|
|
1552
|
+
return line.source.marker === markType;
|
|
1553
|
+
}
|
|
1554
|
+
else {
|
|
1555
|
+
return line.target.marker === markType;
|
|
1556
|
+
}
|
|
1557
|
+
},
|
|
1558
|
+
isSourceMark(line, markType) {
|
|
1559
|
+
return PlaitLine.isSourceMarkOrTargetMark(line, markType, LineHandleKey.source);
|
|
1560
|
+
},
|
|
1561
|
+
isTargetMark(line, markType) {
|
|
1562
|
+
return PlaitLine.isSourceMarkOrTargetMark(line, markType, LineHandleKey.target);
|
|
1563
|
+
},
|
|
1564
|
+
isBoundElementOfSource(line, element) {
|
|
1565
|
+
return line.source.boundId === element.id;
|
|
1566
|
+
},
|
|
1567
|
+
isBoundElementOfTarget(line, element) {
|
|
1568
|
+
return line.target.boundId === element.id;
|
|
1569
|
+
},
|
|
1570
|
+
getPoints(board, line) {
|
|
1571
|
+
let sourcePoint = line.source.boundId
|
|
1572
|
+
? getConnectionPoint(getElementById(board, line.source.boundId), line.source.connection)
|
|
1573
|
+
: line.points[0];
|
|
1574
|
+
let targetPoint = line.target.boundId
|
|
1575
|
+
? getConnectionPoint(getElementById(board, line.target.boundId), line.target.connection)
|
|
1576
|
+
: line.points[line.points.length - 1];
|
|
1577
|
+
const restPoints = line.points.length > 2 ? line.points.slice(1, line.points.length - 1) : [];
|
|
1578
|
+
return [sourcePoint, ...restPoints, targetPoint];
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
|
|
1582
|
+
var StrokeStyle;
|
|
1583
|
+
(function (StrokeStyle) {
|
|
1584
|
+
StrokeStyle["solid"] = "solid";
|
|
1585
|
+
StrokeStyle["dashed"] = "dashed";
|
|
1586
|
+
})(StrokeStyle || (StrokeStyle = {}));
|
|
1587
|
+
|
|
1588
|
+
const PlaitDrawElement = {
|
|
1589
|
+
isGeometry: (value) => {
|
|
1590
|
+
return value.type === 'geometry';
|
|
1591
|
+
},
|
|
1592
|
+
isLine: (value) => {
|
|
1593
|
+
return value.type === 'line';
|
|
1594
|
+
},
|
|
1595
|
+
isText: (value) => {
|
|
1596
|
+
return value.type === 'geometry' && value.shape === GeometryShape.text;
|
|
1597
|
+
},
|
|
1598
|
+
isImage: (value) => {
|
|
1599
|
+
return value.type === 'image';
|
|
1600
|
+
},
|
|
1601
|
+
isDrawElement: (value) => {
|
|
1602
|
+
if (PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isLine(value) || PlaitDrawElement.isImage(value)) {
|
|
1603
|
+
return true;
|
|
1604
|
+
}
|
|
1605
|
+
else {
|
|
1606
|
+
return false;
|
|
1607
|
+
}
|
|
1608
|
+
},
|
|
1609
|
+
isShape: (value) => {
|
|
1610
|
+
return PlaitDrawElement.isImage(value) || PlaitDrawElement.isGeometry(value);
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
690
1613
|
|
|
691
1614
|
class GeometryShapeGenerator extends Generator {
|
|
692
1615
|
canDraw(element, data) {
|
|
@@ -702,7 +1625,12 @@ class GeometryShapeGenerator extends Generator {
|
|
|
702
1625
|
const strokeColor = getStrokeColorByElement(element);
|
|
703
1626
|
const fill = getFillByElement(element);
|
|
704
1627
|
const strokeLineDash = getLineDashByElement(element);
|
|
705
|
-
return drawGeometry(this.board, RectangleClient.inflate(rectangle, -strokeWidth), shape, {
|
|
1628
|
+
return drawGeometry(this.board, RectangleClient.inflate(rectangle, -strokeWidth), shape, {
|
|
1629
|
+
stroke: strokeColor,
|
|
1630
|
+
strokeWidth,
|
|
1631
|
+
fill,
|
|
1632
|
+
strokeLineDash
|
|
1633
|
+
});
|
|
706
1634
|
}
|
|
707
1635
|
}
|
|
708
1636
|
|
|
@@ -782,6 +1710,28 @@ const setTextSize = (board, element, textWidth, textHeight) => {
|
|
|
782
1710
|
}
|
|
783
1711
|
};
|
|
784
1712
|
|
|
1713
|
+
const insertImage = (board, imageItem, startPoint) => {
|
|
1714
|
+
const { width, height, url } = imageItem;
|
|
1715
|
+
const host = BOARD_TO_HOST.get(board);
|
|
1716
|
+
const viewportWidth = PlaitBoard.getComponent(board).nativeElement.clientWidth;
|
|
1717
|
+
const viewportHeight = PlaitBoard.getComponent(board).nativeElement.clientHeight;
|
|
1718
|
+
const point = transformPoint(board, toPoint(viewportWidth / 2, viewportHeight / 2, host));
|
|
1719
|
+
const points = startPoint
|
|
1720
|
+
? [startPoint, [startPoint[0] + width, startPoint[1] + height]]
|
|
1721
|
+
: [
|
|
1722
|
+
[point[0] - width / 2, point[1] - height / 2],
|
|
1723
|
+
[point[0] + width / 2, point[1] + height / 2]
|
|
1724
|
+
];
|
|
1725
|
+
const imageElement = {
|
|
1726
|
+
id: idCreator(),
|
|
1727
|
+
type: 'image',
|
|
1728
|
+
points,
|
|
1729
|
+
url
|
|
1730
|
+
};
|
|
1731
|
+
Transforms.insertNode(board, imageElement, [board.children.length]);
|
|
1732
|
+
Transforms.addSelectionWithTemporaryElements(board, [imageElement]);
|
|
1733
|
+
};
|
|
1734
|
+
|
|
785
1735
|
const resizeLine = (board, options, path) => {
|
|
786
1736
|
Transforms.setNode(board, options, path);
|
|
787
1737
|
};
|
|
@@ -812,7 +1762,8 @@ const DrawTransforms = {
|
|
|
812
1762
|
resizeLine,
|
|
813
1763
|
setLineTexts,
|
|
814
1764
|
removeLineText,
|
|
815
|
-
setLineMark
|
|
1765
|
+
setLineMark,
|
|
1766
|
+
insertImage
|
|
816
1767
|
};
|
|
817
1768
|
|
|
818
1769
|
class GeometryComponent extends CommonPluginElement {
|
|
@@ -830,10 +1781,10 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
830
1781
|
getStrokeWidth: () => {
|
|
831
1782
|
const selectedElements = getSelectedElements(this.board);
|
|
832
1783
|
if (selectedElements.length === 1 && !isSelectionMoving(this.board)) {
|
|
833
|
-
return
|
|
1784
|
+
return ACTIVE_STROKE_WIDTH;
|
|
834
1785
|
}
|
|
835
1786
|
else {
|
|
836
|
-
return
|
|
1787
|
+
return ACTIVE_STROKE_WIDTH;
|
|
837
1788
|
}
|
|
838
1789
|
},
|
|
839
1790
|
getStrokeOpacity: () => {
|
|
@@ -896,6 +1847,10 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
896
1847
|
const plugins = this.board.getPluginOptions(WithTextPluginKey).textPlugins;
|
|
897
1848
|
const manage = new TextManage(this.board, this.viewContainerRef, {
|
|
898
1849
|
getRectangle: () => {
|
|
1850
|
+
const getRectangle = getEngine(this.element.shape).getTextRectangle;
|
|
1851
|
+
if (getRectangle) {
|
|
1852
|
+
return getRectangle(this.element);
|
|
1853
|
+
}
|
|
899
1854
|
return getTextRectangle(this.element);
|
|
900
1855
|
},
|
|
901
1856
|
onValueChangeHandle: (textManageRef) => {
|
|
@@ -923,14 +1878,15 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
923
1878
|
this.destroy$.complete();
|
|
924
1879
|
}
|
|
925
1880
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: GeometryComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
926
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.3", type: GeometryComponent, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1881
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.3", type: GeometryComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
927
1882
|
}
|
|
928
1883
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: GeometryComponent, decorators: [{
|
|
929
1884
|
type: Component,
|
|
930
1885
|
args: [{
|
|
931
1886
|
selector: 'plait-draw-geometry',
|
|
932
1887
|
template: ``,
|
|
933
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
1888
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1889
|
+
standalone: true
|
|
934
1890
|
}]
|
|
935
1891
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
936
1892
|
|
|
@@ -939,21 +1895,17 @@ class LineShapeGenerator extends Generator {
|
|
|
939
1895
|
return true;
|
|
940
1896
|
}
|
|
941
1897
|
baseDraw(element, data) {
|
|
942
|
-
const shape = element.shape;
|
|
943
1898
|
let lineG;
|
|
944
|
-
|
|
945
|
-
case LineShape.elbow:
|
|
946
|
-
case LineShape.straight:
|
|
947
|
-
lineG = drawLine(this.board, element);
|
|
948
|
-
break;
|
|
949
|
-
default:
|
|
950
|
-
break;
|
|
951
|
-
}
|
|
1899
|
+
lineG = drawLine(this.board, element);
|
|
952
1900
|
return lineG;
|
|
953
1901
|
}
|
|
954
1902
|
}
|
|
955
1903
|
|
|
956
1904
|
class LineActiveGenerator extends Generator {
|
|
1905
|
+
constructor() {
|
|
1906
|
+
super(...arguments);
|
|
1907
|
+
this.hasResizeHandle = false;
|
|
1908
|
+
}
|
|
957
1909
|
canDraw(element, data) {
|
|
958
1910
|
if (data.selected) {
|
|
959
1911
|
return true;
|
|
@@ -964,27 +1916,70 @@ class LineActiveGenerator extends Generator {
|
|
|
964
1916
|
}
|
|
965
1917
|
baseDraw(element, data) {
|
|
966
1918
|
const activeG = createG();
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1919
|
+
if (this.hasResizeHandle) {
|
|
1920
|
+
activeG.classList.add('active');
|
|
1921
|
+
activeG.classList.add('line-handle');
|
|
1922
|
+
const points = PlaitLine.getPoints(this.board, element);
|
|
1923
|
+
points.forEach(point => {
|
|
1924
|
+
const circle = drawCircle(PlaitBoard.getRoughSVG(this.board), point, RESIZE_HANDLE_DIAMETER, {
|
|
1925
|
+
stroke: '#999999',
|
|
1926
|
+
strokeWidth: 1,
|
|
1927
|
+
fill: '#FFF',
|
|
1928
|
+
fillStyle: 'solid'
|
|
1929
|
+
});
|
|
1930
|
+
activeG.appendChild(circle);
|
|
1931
|
+
});
|
|
1932
|
+
getMiddlePoints(this.board, element).forEach(point => {
|
|
1933
|
+
const circle = drawCircle(PlaitBoard.getRoughSVG(this.board), point, RESIZE_HANDLE_DIAMETER, {
|
|
1934
|
+
stroke: '#FFFFFF80',
|
|
1935
|
+
strokeWidth: 1,
|
|
1936
|
+
fill: `${PRIMARY_COLOR}80`,
|
|
1937
|
+
fillStyle: 'solid'
|
|
1938
|
+
});
|
|
1939
|
+
activeG.appendChild(circle);
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
else {
|
|
1943
|
+
const points = getLinePoints(this.board, element);
|
|
1944
|
+
const activeRectangle = getRectangleByPoints(points);
|
|
1945
|
+
const strokeG = drawRectangle(this.board, activeRectangle, {
|
|
1946
|
+
stroke: PRIMARY_COLOR,
|
|
1947
|
+
strokeWidth: DefaultGeometryActiveStyle.selectionStrokeWidth
|
|
1948
|
+
});
|
|
1949
|
+
activeG.appendChild(strokeG);
|
|
1950
|
+
}
|
|
985
1951
|
return activeG;
|
|
986
1952
|
}
|
|
987
1953
|
}
|
|
1954
|
+
function getMiddlePoints(board, element) {
|
|
1955
|
+
const result = [];
|
|
1956
|
+
const shape = element.shape;
|
|
1957
|
+
if (shape === LineShape.straight) {
|
|
1958
|
+
const points = PlaitLine.getPoints(board, element);
|
|
1959
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
1960
|
+
result.push([(points[i][0] + points[i + 1][0]) / 2, (points[i][1] + points[i + 1][1]) / 2]);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
if (shape === LineShape.curve) {
|
|
1964
|
+
const points = PlaitLine.getPoints(board, element);
|
|
1965
|
+
const pointsOnBezier = getCurvePoints(board, element);
|
|
1966
|
+
if (points.length === 2) {
|
|
1967
|
+
const start = 0;
|
|
1968
|
+
const endIndex = pointsOnBezier.length - 1;
|
|
1969
|
+
const middleIndex = Math.round((start + endIndex) / 2);
|
|
1970
|
+
result.push(pointsOnBezier[middleIndex]);
|
|
1971
|
+
}
|
|
1972
|
+
else {
|
|
1973
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
1974
|
+
const startIndex = pointsOnBezier.findIndex(point => point[0] === points[i][0] && point[1] === points[i][1]);
|
|
1975
|
+
const endIndex = pointsOnBezier.findIndex(point => point[0] === points[i + 1][0] && point[1] === points[i + 1][1]);
|
|
1976
|
+
const middleIndex = Math.round((startIndex + endIndex) / 2);
|
|
1977
|
+
result.push(pointsOnBezier[middleIndex]);
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
return result;
|
|
1982
|
+
}
|
|
988
1983
|
|
|
989
1984
|
class LineComponent extends PlaitPluginElementComponent {
|
|
990
1985
|
constructor(viewContainerRef, cdr) {
|
|
@@ -1040,11 +2035,18 @@ class LineComponent extends PlaitPluginElementComponent {
|
|
|
1040
2035
|
this.updateTextRectangle();
|
|
1041
2036
|
return;
|
|
1042
2037
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
2038
|
+
if (!isSelectionMoving(this.board)) {
|
|
2039
|
+
this.activeGenerator.hasResizeHandle = this.hasResizeHandle();
|
|
1045
2040
|
this.activeGenerator.draw(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
1046
2041
|
}
|
|
1047
2042
|
}
|
|
2043
|
+
hasResizeHandle() {
|
|
2044
|
+
const selectedElements = getSelectedElements(this.board);
|
|
2045
|
+
if (PlaitBoard.hasBeenTextEditing(this.board) && PlaitDrawElement.isText(this.element)) {
|
|
2046
|
+
return false;
|
|
2047
|
+
}
|
|
2048
|
+
return selectedElements.length === 1 && !isSelectionMoving(this.board);
|
|
2049
|
+
}
|
|
1048
2050
|
initializeTextManages() {
|
|
1049
2051
|
if (this.element.texts?.length) {
|
|
1050
2052
|
this.element.texts.forEach((text, index) => {
|
|
@@ -1117,14 +2119,15 @@ class LineComponent extends PlaitPluginElementComponent {
|
|
|
1117
2119
|
this.destroy$.complete();
|
|
1118
2120
|
}
|
|
1119
2121
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: LineComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1120
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.3", type: LineComponent, selector: "plait-draw-line", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2122
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.3", type: LineComponent, isStandalone: true, selector: "plait-draw-line", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1121
2123
|
}
|
|
1122
2124
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: LineComponent, decorators: [{
|
|
1123
2125
|
type: Component,
|
|
1124
2126
|
args: [{
|
|
1125
2127
|
selector: 'plait-draw-line',
|
|
1126
2128
|
template: ``,
|
|
1127
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
2129
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2130
|
+
standalone: true
|
|
1128
2131
|
}]
|
|
1129
2132
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
1130
2133
|
|
|
@@ -1164,13 +2167,14 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
1164
2167
|
geometryShapeG?.remove();
|
|
1165
2168
|
geometryShapeG = createG();
|
|
1166
2169
|
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
1167
|
-
const
|
|
2170
|
+
const geometryPointers = getGeometryPointers();
|
|
2171
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1168
2172
|
const dragMode = isGeometryPointer && isDndMode(board);
|
|
1169
2173
|
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1170
2174
|
const pointer = PlaitBoard.getPointer(board);
|
|
1171
2175
|
if (dragMode) {
|
|
1172
2176
|
const points = getDefaultGeometryPoints(pointer, movingPoint);
|
|
1173
|
-
if (pointer ===
|
|
2177
|
+
if (pointer === GeometryShape.text) {
|
|
1174
2178
|
const textG = getTemporaryTextG(movingPoint);
|
|
1175
2179
|
geometryShapeG.appendChild(textG);
|
|
1176
2180
|
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
@@ -1188,12 +2192,13 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
1188
2192
|
};
|
|
1189
2193
|
board.pointerUp = (event) => {
|
|
1190
2194
|
const pointer = PlaitBoard.getPointer(board);
|
|
1191
|
-
const
|
|
2195
|
+
const geometryPointers = getGeometryPointers();
|
|
2196
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1192
2197
|
const dragMode = isGeometryPointer && isDndMode(board);
|
|
1193
2198
|
if (dragMode) {
|
|
1194
2199
|
const targetPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1195
2200
|
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
1196
|
-
if (pointer ===
|
|
2201
|
+
if (pointer === GeometryShape.text) {
|
|
1197
2202
|
DrawTransforms.insertText(board, points);
|
|
1198
2203
|
}
|
|
1199
2204
|
else {
|
|
@@ -1208,7 +2213,7 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
1208
2213
|
};
|
|
1209
2214
|
return board;
|
|
1210
2215
|
};
|
|
1211
|
-
const
|
|
2216
|
+
const withGeometryCreateByDrawing = (board) => {
|
|
1212
2217
|
const { pointerDown, pointerMove, pointerUp, keydown, keyup } = board;
|
|
1213
2218
|
let start = null;
|
|
1214
2219
|
let geometryShapeG = null;
|
|
@@ -1223,13 +2228,14 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1223
2228
|
keyup(event);
|
|
1224
2229
|
};
|
|
1225
2230
|
board.pointerDown = (event) => {
|
|
1226
|
-
const
|
|
2231
|
+
const geometryPointers = getGeometryPointers();
|
|
2232
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1227
2233
|
if (isGeometryPointer && isDrawingMode(board)) {
|
|
1228
2234
|
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1229
2235
|
start = point;
|
|
1230
2236
|
const pointer = PlaitBoard.getPointer(board);
|
|
1231
2237
|
preventTouchMove(board, event, true);
|
|
1232
|
-
if (pointer ===
|
|
2238
|
+
if (pointer === GeometryShape.text) {
|
|
1233
2239
|
const points = getDefaultGeometryPoints(pointer, point);
|
|
1234
2240
|
const textElement = createGeometryElement(GeometryShape.text, points, DefaultTextProperty.text);
|
|
1235
2241
|
Transforms.insertNode(board, textElement, [board.children.length]);
|
|
@@ -1248,7 +2254,7 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1248
2254
|
const drawMode = !!start;
|
|
1249
2255
|
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1250
2256
|
const pointer = PlaitBoard.getPointer(board);
|
|
1251
|
-
if (drawMode && pointer !==
|
|
2257
|
+
if (drawMode && pointer !== GeometryShape.text) {
|
|
1252
2258
|
const points = normalizeShapePoints([start, movingPoint], isShift);
|
|
1253
2259
|
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1254
2260
|
strokeColor: DefaultGeometryProperty.strokeColor,
|
|
@@ -1267,7 +2273,7 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1267
2273
|
if (Math.hypot(width, height) === 0) {
|
|
1268
2274
|
const pointer = PlaitBoard.getPointer(board);
|
|
1269
2275
|
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
1270
|
-
if (pointer !==
|
|
2276
|
+
if (pointer !== GeometryShape.text) {
|
|
1271
2277
|
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1272
2278
|
strokeColor: DefaultGeometryProperty.strokeColor,
|
|
1273
2279
|
strokeWidth: DefaultGeometryProperty.strokeWidth
|
|
@@ -1291,7 +2297,7 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1291
2297
|
return board;
|
|
1292
2298
|
};
|
|
1293
2299
|
const getDefaultGeometryPoints = (pointer, targetPoint) => {
|
|
1294
|
-
return pointer ===
|
|
2300
|
+
return pointer === GeometryShape.text
|
|
1295
2301
|
? getPointsByCenterPoint(targetPoint, DefaultTextProperty.width, DefaultTextProperty.height)
|
|
1296
2302
|
: getPointsByCenterPoint(targetPoint, DefaultGeometryProperty.width, DefaultGeometryProperty.height);
|
|
1297
2303
|
};
|
|
@@ -1310,7 +2316,7 @@ const getTemporaryTextG = (movingPoint) => {
|
|
|
1310
2316
|
|
|
1311
2317
|
const buildClipboardData = (board, elements, startPoint) => {
|
|
1312
2318
|
return elements.map(element => {
|
|
1313
|
-
if (PlaitDrawElement.isGeometry(element)) {
|
|
2319
|
+
if (PlaitDrawElement.isGeometry(element) || PlaitDrawElement.isImage(element)) {
|
|
1314
2320
|
const points = element.points.map(point => [point[0] - startPoint[0], point[1] - startPoint[1]]);
|
|
1315
2321
|
return { ...element, points };
|
|
1316
2322
|
}
|
|
@@ -1333,7 +2339,7 @@ const buildClipboardData = (board, elements, startPoint) => {
|
|
|
1333
2339
|
};
|
|
1334
2340
|
const insertClipboardData = (board, elements, startPoint) => {
|
|
1335
2341
|
const lines = elements.filter(value => PlaitDrawElement.isLine(value));
|
|
1336
|
-
const geometries = elements.filter(value => PlaitDrawElement.isGeometry(value));
|
|
2342
|
+
const geometries = elements.filter(value => PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isImage(value));
|
|
1337
2343
|
geometries.forEach(element => {
|
|
1338
2344
|
const sourceLines = [];
|
|
1339
2345
|
const targetLines = [];
|
|
@@ -1357,6 +2363,7 @@ const insertClipboardData = (board, elements, startPoint) => {
|
|
|
1357
2363
|
element.points = element.points.map(point => [startPoint[0] + point[0], startPoint[1] + point[1]]);
|
|
1358
2364
|
Transforms.insertNode(board, element, [board.children.length]);
|
|
1359
2365
|
});
|
|
2366
|
+
Transforms.addSelectionWithTemporaryElements(board, elements);
|
|
1360
2367
|
};
|
|
1361
2368
|
|
|
1362
2369
|
const withDrawFragment = (baseBoard) => {
|
|
@@ -1365,21 +2372,35 @@ const withDrawFragment = (baseBoard) => {
|
|
|
1365
2372
|
board.getDeletedFragment = (data) => {
|
|
1366
2373
|
const drawElements = getSelectedDrawElements(board);
|
|
1367
2374
|
if (drawElements.length) {
|
|
1368
|
-
const lines = getBoardLines(board);
|
|
1369
2375
|
const geometryElements = drawElements.filter(value => PlaitDrawElement.isGeometry(value));
|
|
1370
2376
|
const lineElements = drawElements.filter(value => PlaitDrawElement.isLine(value));
|
|
1371
|
-
const
|
|
1372
|
-
|
|
2377
|
+
const imageElements = drawElements.filter(value => PlaitDrawElement.isImage(value));
|
|
2378
|
+
const boundLineElements = [
|
|
2379
|
+
...getBoundedLineElements(board, geometryElements),
|
|
2380
|
+
...getBoundedLineElements(board, imageElements)
|
|
2381
|
+
].filter(line => !lineElements.includes(line));
|
|
2382
|
+
data.push(...[
|
|
2383
|
+
...geometryElements,
|
|
2384
|
+
...lineElements,
|
|
2385
|
+
...imageElements,
|
|
2386
|
+
...boundLineElements.filter(line => !lineElements.includes(line))
|
|
2387
|
+
]);
|
|
1373
2388
|
}
|
|
1374
2389
|
return getDeletedFragment(data);
|
|
1375
2390
|
};
|
|
1376
|
-
board.setFragment = (data, rectangle) => {
|
|
2391
|
+
board.setFragment = (data, rectangle, type) => {
|
|
1377
2392
|
const targetDrawElements = getSelectedDrawElements(board);
|
|
2393
|
+
let boundLineElements = [];
|
|
1378
2394
|
if (targetDrawElements.length) {
|
|
1379
|
-
|
|
2395
|
+
if (type === 'cut') {
|
|
2396
|
+
const geometryElements = targetDrawElements.filter(value => PlaitDrawElement.isGeometry(value));
|
|
2397
|
+
const lineElements = targetDrawElements.filter(value => PlaitDrawElement.isLine(value));
|
|
2398
|
+
boundLineElements = getBoundedLineElements(board, geometryElements).filter(line => !lineElements.includes(line));
|
|
2399
|
+
}
|
|
2400
|
+
const elements = buildClipboardData(board, [...targetDrawElements, ...boundLineElements], rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
|
|
1380
2401
|
setClipboardData(data, elements);
|
|
1381
2402
|
}
|
|
1382
|
-
setFragment(data, rectangle);
|
|
2403
|
+
setFragment(data, rectangle, type);
|
|
1383
2404
|
};
|
|
1384
2405
|
board.insertFragment = (data, targetPoint) => {
|
|
1385
2406
|
const elements = getDataFromClipboard(data);
|
|
@@ -1399,10 +2420,24 @@ const withDrawFragment = (baseBoard) => {
|
|
|
1399
2420
|
return;
|
|
1400
2421
|
}
|
|
1401
2422
|
}
|
|
2423
|
+
if (data?.files.length) {
|
|
2424
|
+
const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
|
|
2425
|
+
if (acceptImageArray.includes(data?.files[0].type)) {
|
|
2426
|
+
const imageFile = data.files[0];
|
|
2427
|
+
buildImage(board, imageFile, DEFAULT_IMAGE_WIDTH, imageItem => {
|
|
2428
|
+
DrawTransforms.insertImage(board, imageItem, targetPoint);
|
|
2429
|
+
});
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
1402
2433
|
insertFragment(data, targetPoint);
|
|
1403
2434
|
};
|
|
1404
2435
|
return board;
|
|
1405
2436
|
};
|
|
2437
|
+
const getBoundedLineElements = (board, plaitShapes) => {
|
|
2438
|
+
const lines = getBoardLines(board);
|
|
2439
|
+
return lines.filter(line => plaitShapes.find(shape => PlaitLine.isBoundElementOfSource(line, shape) || PlaitLine.isBoundElementOfTarget(line, shape)));
|
|
2440
|
+
};
|
|
1406
2441
|
|
|
1407
2442
|
const DefaultLineStyle = {
|
|
1408
2443
|
strokeWidth: 2,
|
|
@@ -1420,10 +2455,10 @@ const getHitGeometryResizeHandleRef = (board, element, point) => {
|
|
|
1420
2455
|
const getHitOutlineGeometry = (board, point, offset = 0) => {
|
|
1421
2456
|
let geometry = null;
|
|
1422
2457
|
depthFirstRecursion(board, node => {
|
|
1423
|
-
if (PlaitDrawElement.isGeometry(node)) {
|
|
1424
|
-
const shape = node.shape;
|
|
2458
|
+
if (PlaitDrawElement.isGeometry(node) || PlaitDrawElement.isImage(node)) {
|
|
1425
2459
|
let client = getRectangleByPoints(node.points);
|
|
1426
2460
|
client = RectangleClient.getOutlineRectangle(client, offset);
|
|
2461
|
+
const shape = getShape(node);
|
|
1427
2462
|
const isHit = getEngine(shape).isHit(client, point);
|
|
1428
2463
|
if (isHit) {
|
|
1429
2464
|
geometry = node;
|
|
@@ -1441,7 +2476,8 @@ const withLineCreateByDraw = (board) => {
|
|
|
1441
2476
|
let lineShapeG = null;
|
|
1442
2477
|
let temporaryElement = null;
|
|
1443
2478
|
board.pointerDown = (event) => {
|
|
1444
|
-
const
|
|
2479
|
+
const linePointers = getLinePointers();
|
|
2480
|
+
const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
|
|
1445
2481
|
if (isLinePointer && isDrawingMode(board)) {
|
|
1446
2482
|
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1447
2483
|
start = point;
|
|
@@ -1463,7 +2499,8 @@ const withLineCreateByDraw = (board) => {
|
|
|
1463
2499
|
targetRef.connection = hitElement ? transformPointToConnection(board, movingPoint, hitElement) : undefined;
|
|
1464
2500
|
targetRef.boundId = hitElement ? hitElement.id : undefined;
|
|
1465
2501
|
const lineGenerator = new LineShapeGenerator(board);
|
|
1466
|
-
|
|
2502
|
+
const lineShape = PlaitBoard.getPointer(board);
|
|
2503
|
+
temporaryElement = createLineElement(lineShape, [start, movingPoint], { marker: LineMarkerType.none, connection: sourceRef.connection, boundId: sourceRef?.boundId }, { marker: LineMarkerType.arrow, connection: targetRef.connection, boundId: targetRef?.boundId }, {
|
|
1467
2504
|
strokeColor: DefaultLineStyle.strokeColor,
|
|
1468
2505
|
strokeWidth: DefaultLineStyle.strokeWidth
|
|
1469
2506
|
});
|
|
@@ -1508,12 +2545,12 @@ const withGeometryResize = (board) => {
|
|
|
1508
2545
|
return true;
|
|
1509
2546
|
},
|
|
1510
2547
|
detect: (point) => {
|
|
1511
|
-
const
|
|
1512
|
-
if (
|
|
2548
|
+
const selectedElements = [...getSelectedGeometryElements(board), ...getSelectedImageElements(board)];
|
|
2549
|
+
if (selectedElements.length !== 1 || getSelectedElements(board).length !== 1) {
|
|
1513
2550
|
return null;
|
|
1514
2551
|
}
|
|
1515
|
-
const target =
|
|
1516
|
-
const targetComponent = PlaitElement.getComponent(
|
|
2552
|
+
const target = selectedElements[0];
|
|
2553
|
+
const targetComponent = PlaitElement.getComponent(selectedElements[0]);
|
|
1517
2554
|
if (targetComponent.activeGenerator.hasResizeHandle) {
|
|
1518
2555
|
const handleRef = getHitGeometryResizeHandleRef(board, target, point);
|
|
1519
2556
|
if (handleRef) {
|
|
@@ -1528,27 +2565,34 @@ const withGeometryResize = (board) => {
|
|
|
1528
2565
|
},
|
|
1529
2566
|
onResize: (resizeRef, resizeState) => {
|
|
1530
2567
|
let points = [...resizeRef.element.points];
|
|
2568
|
+
const rectangle = getRectangleByPoints(resizeRef.element.points);
|
|
2569
|
+
const ratio = rectangle.height / rectangle.width;
|
|
1531
2570
|
if (resizeRef.handle === ResizeHandle.nw) {
|
|
1532
2571
|
points = [resizeState.endTransformPoint, resizeRef.element.points[1]];
|
|
1533
2572
|
}
|
|
1534
2573
|
if (resizeRef.handle === ResizeHandle.ne) {
|
|
1535
|
-
points = [
|
|
1536
|
-
[resizeRef.element.points[0][0], resizeState.endTransformPoint[1]],
|
|
1537
|
-
[resizeState.endTransformPoint[0], resizeRef.element.points[1][1]]
|
|
1538
|
-
];
|
|
2574
|
+
points = [resizeState.endTransformPoint, [resizeRef.element.points[0][0], resizeRef.element.points[1][1]]];
|
|
1539
2575
|
}
|
|
1540
2576
|
if (resizeRef.handle === ResizeHandle.se) {
|
|
1541
|
-
points = [resizeRef.element.points[0]
|
|
2577
|
+
points = [resizeState.endTransformPoint, resizeRef.element.points[0]];
|
|
1542
2578
|
}
|
|
1543
2579
|
if (resizeRef.handle === ResizeHandle.sw) {
|
|
1544
|
-
points = [
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
2580
|
+
points = [resizeState.endTransformPoint, [resizeRef.element.points[1][0], resizeRef.element.points[0][1]]];
|
|
2581
|
+
}
|
|
2582
|
+
if (isShift || PlaitDrawElement.isImage(resizeRef.element)) {
|
|
2583
|
+
const rectangle = getRectangleByPoints(points);
|
|
2584
|
+
const factor = points[0][1] > points[1][1] ? 1 : -1;
|
|
2585
|
+
const height = rectangle.width * ratio * factor;
|
|
2586
|
+
points = [[resizeState.endTransformPoint[0], points[1][1] + height], points[1]];
|
|
2587
|
+
}
|
|
2588
|
+
if (PlaitDrawElement.isGeometry(resizeRef.element)) {
|
|
2589
|
+
const { height: textHeight } = PlaitGeometry.getTextManage(resizeRef.element).getSize();
|
|
2590
|
+
DrawTransforms.resizeGeometry(board, points, textHeight, resizeRef.path);
|
|
2591
|
+
}
|
|
2592
|
+
else {
|
|
2593
|
+
points = normalizeShapePoints(points);
|
|
2594
|
+
Transforms.setNode(board, { points }, resizeRef.path);
|
|
1548
2595
|
}
|
|
1549
|
-
points = normalizeShapePoints(points, isShift);
|
|
1550
|
-
const { height: textHeight } = PlaitGeometry.getTextManage(resizeRef.element).getSize();
|
|
1551
|
-
DrawTransforms.resizeGeometry(board, points, textHeight, resizeRef.path);
|
|
1552
2596
|
}
|
|
1553
2597
|
};
|
|
1554
2598
|
withResize(board, options);
|
|
@@ -1559,34 +2603,44 @@ var LineResizeHandle;
|
|
|
1559
2603
|
(function (LineResizeHandle) {
|
|
1560
2604
|
LineResizeHandle["source"] = "source";
|
|
1561
2605
|
LineResizeHandle["target"] = "target";
|
|
2606
|
+
LineResizeHandle["addHandle"] = "addHandle";
|
|
1562
2607
|
})(LineResizeHandle || (LineResizeHandle = {}));
|
|
1563
2608
|
const getHitLineResizeHandleRef = (board, element, point) => {
|
|
1564
|
-
const
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
y: targetPoint[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
1575
|
-
width: RESIZE_HANDLE_DIAMETER,
|
|
1576
|
-
height: RESIZE_HANDLE_DIAMETER
|
|
1577
|
-
};
|
|
1578
|
-
const isHitSourceRectangle = RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), sourceRectangle);
|
|
1579
|
-
const isHitTargetRectangle = RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), targetRectangle);
|
|
1580
|
-
if (isHitSourceRectangle) {
|
|
1581
|
-
return { rectangle: sourceRectangle, handle: LineResizeHandle.source };
|
|
2609
|
+
const points = PlaitLine.getPoints(board, element);
|
|
2610
|
+
const index = getHitPointIndex(points, point);
|
|
2611
|
+
if (index !== -1) {
|
|
2612
|
+
if (index === 0) {
|
|
2613
|
+
return { handle: LineResizeHandle.source, index };
|
|
2614
|
+
}
|
|
2615
|
+
if (index === points.length - 1) {
|
|
2616
|
+
return { handle: LineResizeHandle.target, index };
|
|
2617
|
+
}
|
|
2618
|
+
return { index };
|
|
1582
2619
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
2620
|
+
const middlePoints = getMiddlePoints(board, element);
|
|
2621
|
+
const middleIndex = getHitPointIndex(middlePoints, point);
|
|
2622
|
+
if (middleIndex !== -1) {
|
|
2623
|
+
return { handle: LineResizeHandle.addHandle, index: middleIndex };
|
|
1585
2624
|
}
|
|
1586
2625
|
return undefined;
|
|
1587
2626
|
};
|
|
2627
|
+
function getHitPointIndex(points, movingPoint) {
|
|
2628
|
+
const rectangles = points.map(point => {
|
|
2629
|
+
return {
|
|
2630
|
+
x: point[0] - RESIZE_HANDLE_DIAMETER / 2,
|
|
2631
|
+
y: point[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
2632
|
+
width: RESIZE_HANDLE_DIAMETER,
|
|
2633
|
+
height: RESIZE_HANDLE_DIAMETER
|
|
2634
|
+
};
|
|
2635
|
+
});
|
|
2636
|
+
const rectangle = rectangles.find(rectangle => {
|
|
2637
|
+
return RectangleClient.isHit(RectangleClient.toRectangleClient([movingPoint, movingPoint]), rectangle);
|
|
2638
|
+
});
|
|
2639
|
+
return rectangle ? rectangles.indexOf(rectangle) : -1;
|
|
2640
|
+
}
|
|
1588
2641
|
|
|
1589
2642
|
const withLineResize = (board) => {
|
|
2643
|
+
let pointIndex = 0;
|
|
1590
2644
|
const options = {
|
|
1591
2645
|
key: 'draw-line',
|
|
1592
2646
|
canResize: () => {
|
|
@@ -1603,6 +2657,7 @@ const withLineResize = (board) => {
|
|
|
1603
2657
|
element: value,
|
|
1604
2658
|
handle: handleRef.handle
|
|
1605
2659
|
};
|
|
2660
|
+
pointIndex = handleRef.index;
|
|
1606
2661
|
}
|
|
1607
2662
|
});
|
|
1608
2663
|
return result;
|
|
@@ -1614,17 +2669,23 @@ const withLineResize = (board) => {
|
|
|
1614
2669
|
let source = { ...resizeRef.element.source };
|
|
1615
2670
|
let target = { ...resizeRef.element.target };
|
|
1616
2671
|
if (resizeRef.handle === LineResizeHandle.source) {
|
|
1617
|
-
points[
|
|
2672
|
+
points[pointIndex] = resizeState.endTransformPoint;
|
|
1618
2673
|
const hitElement = getHitOutlineGeometry(board, resizeState.endTransformPoint, -4);
|
|
1619
2674
|
source.connection = hitElement ? transformPointToConnection(board, resizeState.endTransformPoint, hitElement) : undefined;
|
|
1620
2675
|
source.boundId = hitElement ? hitElement.id : undefined;
|
|
1621
2676
|
}
|
|
1622
|
-
if (resizeRef.handle === LineResizeHandle.target) {
|
|
1623
|
-
points[
|
|
2677
|
+
else if (resizeRef.handle === LineResizeHandle.target) {
|
|
2678
|
+
points[pointIndex] = resizeState.endTransformPoint;
|
|
1624
2679
|
const hitElement = getHitOutlineGeometry(board, resizeState.endTransformPoint, -4);
|
|
1625
2680
|
target.connection = hitElement ? transformPointToConnection(board, resizeState.endTransformPoint, hitElement) : undefined;
|
|
1626
2681
|
target.boundId = hitElement ? hitElement.id : undefined;
|
|
1627
2682
|
}
|
|
2683
|
+
else if (resizeRef.handle === LineResizeHandle.addHandle) {
|
|
2684
|
+
points.splice(pointIndex + 1, 0, resizeState.endTransformPoint);
|
|
2685
|
+
}
|
|
2686
|
+
else {
|
|
2687
|
+
points[pointIndex] = resizeState.endTransformPoint;
|
|
2688
|
+
}
|
|
1628
2689
|
DrawTransforms.resizeLine(board, { points, source, target }, resizeRef.path);
|
|
1629
2690
|
}
|
|
1630
2691
|
};
|
|
@@ -1637,9 +2698,14 @@ const withLineBoundReaction = (board) => {
|
|
|
1637
2698
|
let boundShapeG = null;
|
|
1638
2699
|
board.pointerMove = (event) => {
|
|
1639
2700
|
boundShapeG?.remove();
|
|
1640
|
-
const
|
|
2701
|
+
const linePointers = Object.keys(LineShape);
|
|
2702
|
+
const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
|
|
1641
2703
|
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1642
|
-
const isLineResizing = isResizingByCondition(board,
|
|
2704
|
+
const isLineResizing = isResizingByCondition(board, resizeRef => {
|
|
2705
|
+
const { element, handle } = resizeRef;
|
|
2706
|
+
const isSourceOrTarget = handle === LineResizeHandle.target || handle === LineResizeHandle.source;
|
|
2707
|
+
return PlaitDrawElement.isLine(element) && isSourceOrTarget;
|
|
2708
|
+
});
|
|
1643
2709
|
if (isLinePointer || isLineResizing) {
|
|
1644
2710
|
const hitElement = getHitOutlineGeometry(board, movingPoint, -4);
|
|
1645
2711
|
if (hitElement) {
|
|
@@ -1717,8 +2783,74 @@ function editHandle(board, element, manageIndex, isFirstEdit = false) {
|
|
|
1717
2783
|
});
|
|
1718
2784
|
}
|
|
1719
2785
|
|
|
2786
|
+
class ImageComponent extends CommonPluginElement {
|
|
2787
|
+
get activeGenerator() {
|
|
2788
|
+
return this.imageGenerator.componentRef.instance.activeGenerator;
|
|
2789
|
+
}
|
|
2790
|
+
constructor(viewContainerRef, cdr) {
|
|
2791
|
+
super(cdr);
|
|
2792
|
+
this.viewContainerRef = viewContainerRef;
|
|
2793
|
+
this.cdr = cdr;
|
|
2794
|
+
this.destroy$ = new Subject();
|
|
2795
|
+
}
|
|
2796
|
+
initializeGenerator() {
|
|
2797
|
+
this.imageGenerator = new ImageGenerator(this.board, {
|
|
2798
|
+
getRectangle: (element) => {
|
|
2799
|
+
return {
|
|
2800
|
+
x: element.points[0][0],
|
|
2801
|
+
y: element.points[0][1],
|
|
2802
|
+
width: element.points[1][0] - element.points[0][0],
|
|
2803
|
+
height: element.points[1][1] - element.points[0][1]
|
|
2804
|
+
};
|
|
2805
|
+
},
|
|
2806
|
+
getImageItem: element => {
|
|
2807
|
+
return {
|
|
2808
|
+
url: element.url,
|
|
2809
|
+
width: element.points[1][0] - element.points[0][0],
|
|
2810
|
+
height: element.points[1][1] - element.points[0][1]
|
|
2811
|
+
};
|
|
2812
|
+
}
|
|
2813
|
+
});
|
|
2814
|
+
}
|
|
2815
|
+
ngOnInit() {
|
|
2816
|
+
super.ngOnInit();
|
|
2817
|
+
this.initializeGenerator();
|
|
2818
|
+
this.imageGenerator.draw(this.element, this.g, this.viewContainerRef);
|
|
2819
|
+
}
|
|
2820
|
+
onContextChanged(value, previous) {
|
|
2821
|
+
if (value.element !== previous.element) {
|
|
2822
|
+
this.imageGenerator.updateImage(this.g, previous.element, value.element);
|
|
2823
|
+
this.imageGenerator.componentRef.instance.isFocus = this.selected;
|
|
2824
|
+
}
|
|
2825
|
+
else {
|
|
2826
|
+
const hasSameSelected = value.selected === previous.selected;
|
|
2827
|
+
const hasSameHandleState = this.activeGenerator.options.hasResizeHandle() === this.activeGenerator.hasResizeHandle;
|
|
2828
|
+
if (!hasSameSelected || !hasSameHandleState) {
|
|
2829
|
+
this.imageGenerator.componentRef.instance.isFocus = this.selected;
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
ngOnDestroy() {
|
|
2834
|
+
super.ngOnDestroy();
|
|
2835
|
+
this.destroy$.next();
|
|
2836
|
+
this.destroy$.complete();
|
|
2837
|
+
this.imageGenerator.destroy();
|
|
2838
|
+
}
|
|
2839
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: ImageComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2840
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.3", type: ImageComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2841
|
+
}
|
|
2842
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: ImageComponent, decorators: [{
|
|
2843
|
+
type: Component,
|
|
2844
|
+
args: [{
|
|
2845
|
+
selector: 'plait-draw-geometry',
|
|
2846
|
+
template: ``,
|
|
2847
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2848
|
+
standalone: true
|
|
2849
|
+
}]
|
|
2850
|
+
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
2851
|
+
|
|
1720
2852
|
const withDraw = (board) => {
|
|
1721
|
-
const { drawElement, getRectangle, isHitSelection, isMovable,
|
|
2853
|
+
const { drawElement, getRectangle, isHitSelection, isMovable, isAlign } = board;
|
|
1722
2854
|
board.drawElement = (context) => {
|
|
1723
2855
|
if (PlaitDrawElement.isGeometry(context.element)) {
|
|
1724
2856
|
return GeometryComponent;
|
|
@@ -1726,6 +2858,9 @@ const withDraw = (board) => {
|
|
|
1726
2858
|
else if (PlaitDrawElement.isLine(context.element)) {
|
|
1727
2859
|
return LineComponent;
|
|
1728
2860
|
}
|
|
2861
|
+
else if (PlaitDrawElement.isImage(context.element)) {
|
|
2862
|
+
return ImageComponent;
|
|
2863
|
+
}
|
|
1729
2864
|
return drawElement(context);
|
|
1730
2865
|
};
|
|
1731
2866
|
board.getRectangle = (element) => {
|
|
@@ -1733,9 +2868,11 @@ const withDraw = (board) => {
|
|
|
1733
2868
|
return getRectangleByPoints(element.points);
|
|
1734
2869
|
}
|
|
1735
2870
|
if (PlaitDrawElement.isLine(element)) {
|
|
1736
|
-
const
|
|
1737
|
-
|
|
1738
|
-
|
|
2871
|
+
const points = getLinePoints(board, element);
|
|
2872
|
+
return getRectangleByPoints(points);
|
|
2873
|
+
}
|
|
2874
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
2875
|
+
return getRectangleByPoints(element.points);
|
|
1739
2876
|
}
|
|
1740
2877
|
return getRectangle(element);
|
|
1741
2878
|
};
|
|
@@ -1749,6 +2886,11 @@ const withDraw = (board) => {
|
|
|
1749
2886
|
}
|
|
1750
2887
|
return RectangleClient.isHit(rangeRectangle, client);
|
|
1751
2888
|
}
|
|
2889
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
2890
|
+
const client = getRectangleByPoints(element.points);
|
|
2891
|
+
const rangeRectangle = RectangleClient.toRectangleClient([range.anchor, range.focus]);
|
|
2892
|
+
return RectangleClient.isHit(rangeRectangle, client);
|
|
2893
|
+
}
|
|
1752
2894
|
if (PlaitDrawElement.isLine(element)) {
|
|
1753
2895
|
const points = getLinePoints(board, element);
|
|
1754
2896
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
@@ -1767,17 +2909,34 @@ const withDraw = (board) => {
|
|
|
1767
2909
|
if (PlaitDrawElement.isGeometry(element)) {
|
|
1768
2910
|
return true;
|
|
1769
2911
|
}
|
|
2912
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
2913
|
+
return true;
|
|
2914
|
+
}
|
|
1770
2915
|
if (PlaitDrawElement.isLine(element)) {
|
|
1771
|
-
|
|
2916
|
+
const selectedElements = getSelectedElements(board);
|
|
2917
|
+
const isSelected = (boundId) => {
|
|
2918
|
+
return !!selectedElements.find(value => value.id === boundId);
|
|
2919
|
+
};
|
|
2920
|
+
if ((element.source.boundId && !isSelected(element.source.boundId)) ||
|
|
2921
|
+
(element.target.boundId && !isSelected(element.target.boundId))) {
|
|
2922
|
+
return false;
|
|
2923
|
+
}
|
|
2924
|
+
return true;
|
|
1772
2925
|
}
|
|
1773
2926
|
return isMovable(element);
|
|
1774
2927
|
};
|
|
1775
|
-
|
|
2928
|
+
board.isAlign = (element) => {
|
|
2929
|
+
if (PlaitDrawElement.isGeometry(element) || PlaitDrawElement.isImage(element)) {
|
|
2930
|
+
return true;
|
|
2931
|
+
}
|
|
2932
|
+
return isAlign(element);
|
|
2933
|
+
};
|
|
2934
|
+
return withLineText(withLineBoundReaction(withLineResize(withGeometryResize(withLineCreateByDraw(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board)))))))));
|
|
1776
2935
|
};
|
|
1777
2936
|
|
|
1778
2937
|
/**
|
|
1779
2938
|
* Generated bundle index. Do not edit.
|
|
1780
2939
|
*/
|
|
1781
2940
|
|
|
1782
|
-
export { DefaultGeometryActiveStyle, DefaultGeometryProperty, DefaultGeometryStyle, DefaultTextProperty,
|
|
2941
|
+
export { DEFAULT_IMAGE_WIDTH, DefaultGeometryActiveStyle, DefaultGeometryProperty, DefaultGeometryStyle, DefaultTextProperty, DrawTransforms, GeometryComponent, GeometryShape, GeometryThreshold, LineComponent, LineHandleKey, LineMarkerType, LineShape, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, StrokeStyle, createGeometryElement, createLineElement, drawBoundMask, drawGeometry, drawLine, getBoardLines, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getEdgeOnPolygonByPoint, getElbowPoints, getExtendPoint, getFillByElement, getGeometryPointers, getHitConnectorPoint, getHitLineTextIndex, getLineDashByElement, getLineHandleRefPair, getLinePointers, getLinePoints, getLineTextRectangle, getNearestPoint, getPointsByCenterPoint, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedLineElements, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTextRectangle, getVectorByConnection, isHitLineText, isHitPolyLine, removeDuplicatePoints, transformOpsToPoints, transformPointToConnection, withDraw };
|
|
1783
2942
|
//# sourceMappingURL=plait-draw.mjs.map
|