@plait/draw 0.28.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants/geometry.d.ts +71 -1
- package/constants/pointer.d.ts +4 -2
- package/engines/{comment.d.ts → basic-shapes/comment.d.ts} +1 -1
- package/engines/{cross.d.ts → basic-shapes/cross.d.ts} +2 -2
- package/engines/{diamond.d.ts → basic-shapes/diamond.d.ts} +1 -1
- package/engines/basic-shapes/ellipse.d.ts +13 -0
- package/engines/{hexagon.d.ts → basic-shapes/hexagon.d.ts} +2 -2
- package/engines/{left-arrow.d.ts → basic-shapes/left-arrow.d.ts} +2 -2
- package/engines/{octagon.d.ts → basic-shapes/octagon.d.ts} +2 -2
- package/engines/basic-shapes/parallelogram.d.ts +4 -0
- package/engines/{pentagon-arrow.d.ts → basic-shapes/pentagon-arrow.d.ts} +2 -2
- package/engines/{pentagon.d.ts → basic-shapes/pentagon.d.ts} +2 -2
- package/engines/basic-shapes/polygon.d.ts +8 -0
- package/engines/{process-arrow.d.ts → basic-shapes/process-arrow.d.ts} +2 -2
- package/engines/{rectangle.d.ts → basic-shapes/rectangle.d.ts} +1 -1
- package/engines/{right-arrow.d.ts → basic-shapes/right-arrow.d.ts} +2 -2
- package/engines/{round-comment.d.ts → basic-shapes/round-comment.d.ts} +1 -1
- package/engines/{round-rectangle.d.ts → basic-shapes/round-rectangle.d.ts} +1 -1
- package/engines/{star.d.ts → basic-shapes/star.d.ts} +2 -2
- package/engines/{trapezoid.d.ts → basic-shapes/trapezoid.d.ts} +2 -2
- package/engines/{triangle.d.ts → basic-shapes/triangle.d.ts} +2 -2
- package/engines/{two-way-arrow.d.ts → basic-shapes/two-way-arrow.d.ts} +2 -2
- package/engines/flowchart/delay.d.ts +2 -0
- package/engines/flowchart/manual-input.d.ts +4 -0
- package/engines/flowchart/manual-loop.d.ts +4 -0
- package/engines/flowchart/merge.d.ts +4 -0
- package/engines/flowchart/preparation.d.ts +4 -0
- package/engines/flowchart/stored-data.d.ts +2 -0
- package/engines/flowchart/terminal.d.ts +5 -0
- package/engines/index.d.ts +3 -3
- package/esm2022/constants/geometry.mjs +40 -2
- package/esm2022/constants/line.mjs +1 -1
- package/esm2022/constants/pointer.mjs +9 -3
- package/esm2022/engines/basic-shapes/comment.mjs +57 -0
- package/esm2022/engines/basic-shapes/cross.mjs +33 -0
- package/esm2022/engines/basic-shapes/diamond.mjs +16 -0
- package/esm2022/engines/basic-shapes/ellipse.mjs +100 -0
- package/esm2022/engines/basic-shapes/hexagon.mjs +27 -0
- package/esm2022/engines/basic-shapes/left-arrow.mjs +30 -0
- package/esm2022/engines/basic-shapes/octagon.mjs +29 -0
- package/esm2022/engines/basic-shapes/parallelogram.mjs +25 -0
- package/esm2022/engines/basic-shapes/pentagon-arrow.mjs +24 -0
- package/esm2022/engines/basic-shapes/pentagon.mjs +30 -0
- package/esm2022/engines/basic-shapes/polygon.mjs +40 -0
- package/esm2022/engines/basic-shapes/process-arrow.mjs +26 -0
- package/esm2022/engines/basic-shapes/rectangle.mjs +26 -0
- package/esm2022/engines/basic-shapes/right-arrow.mjs +28 -0
- package/esm2022/engines/basic-shapes/round-comment.mjs +81 -0
- package/esm2022/engines/basic-shapes/round-rectangle.mjs +59 -0
- package/esm2022/engines/basic-shapes/star.mjs +39 -0
- package/esm2022/engines/basic-shapes/trapezoid.mjs +25 -0
- package/esm2022/engines/basic-shapes/triangle.mjs +33 -0
- package/esm2022/engines/basic-shapes/two-way-arrow.mjs +25 -0
- package/esm2022/engines/flowchart/delay.mjs +45 -0
- package/esm2022/engines/flowchart/manual-input.mjs +32 -0
- package/esm2022/engines/flowchart/manual-loop.mjs +25 -0
- package/esm2022/engines/flowchart/merge.mjs +34 -0
- package/esm2022/engines/flowchart/preparation.mjs +27 -0
- package/esm2022/engines/flowchart/stored-data.mjs +74 -0
- package/esm2022/engines/flowchart/terminal.mjs +59 -0
- package/esm2022/engines/index.mjs +59 -41
- package/esm2022/generators/geometry-shape.generator.mjs +3 -3
- package/esm2022/generators/line-active.generator.mjs +1 -1
- package/esm2022/generators/line.generator.mjs +1 -1
- package/esm2022/geometry.component.mjs +9 -5
- package/esm2022/image.component.mjs +4 -4
- package/esm2022/interfaces/geometry.mjs +38 -24
- package/esm2022/interfaces/index.mjs +9 -3
- package/esm2022/interfaces/text.mjs +1 -1
- package/esm2022/line.component.mjs +4 -4
- package/esm2022/plugins/with-draw-fragment.mjs +5 -4
- package/esm2022/plugins/with-draw.mjs +15 -31
- package/esm2022/plugins/with-geometry-create.mjs +32 -20
- package/esm2022/plugins/with-line-create.mjs +2 -2
- package/esm2022/plugins/with-line-text.mjs +4 -4
- package/esm2022/transforms/geometry.mjs +6 -6
- package/esm2022/utils/geometry.mjs +74 -5
- package/esm2022/utils/hit.mjs +58 -0
- package/esm2022/utils/index.mjs +2 -1
- package/esm2022/utils/line-arrow.mjs +3 -3
- package/esm2022/utils/line.mjs +39 -17
- package/esm2022/utils/shape.mjs +3 -3
- package/fesm2022/plait-draw.mjs +1200 -872
- package/fesm2022/plait-draw.mjs.map +1 -1
- package/interfaces/geometry.d.ts +19 -5
- package/interfaces/index.d.ts +2 -0
- package/interfaces/text.d.ts +2 -2
- package/package.json +1 -1
- package/plugins/with-geometry-create.d.ts +7 -1
- package/transforms/geometry.d.ts +2 -2
- package/transforms/index.d.ts +1 -1
- package/utils/geometry.d.ts +23 -3
- package/utils/hit.d.ts +3 -0
- package/utils/index.d.ts +1 -0
- package/utils/line.d.ts +2 -3
- package/utils/shape.d.ts +2 -2
- package/engines/ellipse.d.ts +0 -4
- package/engines/parallelogram.d.ts +0 -4
- package/esm2022/engines/comment.mjs +0 -57
- package/esm2022/engines/cross.mjs +0 -46
- package/esm2022/engines/diamond.mjs +0 -30
- package/esm2022/engines/ellipse.mjs +0 -92
- package/esm2022/engines/hexagon.mjs +0 -40
- package/esm2022/engines/left-arrow.mjs +0 -45
- package/esm2022/engines/octagon.mjs +0 -42
- package/esm2022/engines/parallelogram.mjs +0 -39
- package/esm2022/engines/pentagon-arrow.mjs +0 -39
- package/esm2022/engines/pentagon.mjs +0 -39
- package/esm2022/engines/process-arrow.mjs +0 -41
- package/esm2022/engines/rectangle.mjs +0 -26
- package/esm2022/engines/right-arrow.mjs +0 -45
- package/esm2022/engines/round-comment.mjs +0 -81
- package/esm2022/engines/round-rectangle.mjs +0 -59
- package/esm2022/engines/star.mjs +0 -45
- package/esm2022/engines/trapezoid.mjs +0 -40
- package/esm2022/engines/triangle.mjs +0 -40
- package/esm2022/engines/two-way-arrow.mjs +0 -48
package/fesm2022/plait-draw.mjs
CHANGED
|
@@ -1,36 +1,50 @@
|
|
|
1
|
-
import { PlaitElement, ACTIVE_STROKE_WIDTH, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle,
|
|
2
|
-
import { getRectangleByPoints, getFactorByPoints, getDirectionByVector, getOppositeDirection, getDirectionFactor, getPoints, getPointByVector, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90,
|
|
3
|
-
import { Alignment,
|
|
1
|
+
import { PlaitElement, ACTIVE_STROKE_WIDTH, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Point, BOARD_TO_HOST, transformPoint, toPoint, idCreator, createG, BoardTransforms, PlaitPointerType, preventTouchMove, createForeignObject, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, distanceBetweenPointAndSegment, arrowPoints, createPath, drawLinearPath, rotate, getElementById, distanceBetweenPointAndPoint, distanceBetweenPointAndSegments, createMask, createRect, findElements, getSelectedElements, isPolylineHitRectangle, isSelectionMoving, PlaitPluginElementComponent, setClipboardData, getDataFromClipboard, depthFirstRecursion, getIsRecursionFunc, getHitElementByPoint } from '@plait/core';
|
|
2
|
+
import { getRectangleByPoints, Generator, normalizeShapePoints, isDndMode, isDrawingMode, getFactorByPoints, getDirectionByVector, getOppositeDirection, getDirectionFactor, DEFAULT_ROUTE_MARGIN, reduceRouteMargin, getNextPoint, generateElbowLineRoute, getPoints, removeDuplicatePoints, getPointByVector, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90, CommonPluginElement, ActiveGenerator, WithTextPluginKey, RESIZE_HANDLE_DIAMETER, PRIMARY_COLOR, isVirtualKey, isDelete, isSpaceHotkey, acceptImageTypes, getElementOfFocusedImage, buildImage, getRectangleResizeHandleRefs, ResizeHandle, withResize, isResizingByCondition, getRatioByPoint, ImageGenerator } from '@plait/common';
|
|
3
|
+
import { AlignEditor, Alignment, DEFAULT_FONT_SIZE, buildText, TextManage, getTextFromClipboard, getTextSize } from '@plait/text';
|
|
4
|
+
import { isKeyHotkey } from 'is-hotkey';
|
|
4
5
|
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
5
6
|
import * as i0 from '@angular/core';
|
|
6
7
|
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
7
8
|
import { Subject } from 'rxjs';
|
|
8
|
-
import { isKeyHotkey } from 'is-hotkey';
|
|
9
9
|
import { Node } from 'slate';
|
|
10
10
|
|
|
11
|
-
var
|
|
12
|
-
(function (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
})(
|
|
11
|
+
var BasicShapes;
|
|
12
|
+
(function (BasicShapes) {
|
|
13
|
+
BasicShapes["rectangle"] = "rectangle";
|
|
14
|
+
BasicShapes["ellipse"] = "ellipse";
|
|
15
|
+
BasicShapes["diamond"] = "diamond";
|
|
16
|
+
BasicShapes["roundRectangle"] = "roundRectangle";
|
|
17
|
+
BasicShapes["parallelogram"] = "parallelogram";
|
|
18
|
+
BasicShapes["text"] = "text";
|
|
19
|
+
BasicShapes["triangle"] = "triangle";
|
|
20
|
+
BasicShapes["leftArrow"] = "leftArrow";
|
|
21
|
+
BasicShapes["trapezoid"] = "trapezoid";
|
|
22
|
+
BasicShapes["rightArrow"] = "rightArrow";
|
|
23
|
+
BasicShapes["cross"] = "cross";
|
|
24
|
+
BasicShapes["star"] = "star";
|
|
25
|
+
BasicShapes["pentagon"] = "pentagon";
|
|
26
|
+
BasicShapes["hexagon"] = "hexagon";
|
|
27
|
+
BasicShapes["octagon"] = "octagon";
|
|
28
|
+
BasicShapes["pentagonArrow"] = "pentagonArrow";
|
|
29
|
+
BasicShapes["processArrow"] = "processArrow";
|
|
30
|
+
BasicShapes["twoWayArrow"] = "twoWayArrow";
|
|
31
|
+
BasicShapes["comment"] = "comment";
|
|
32
|
+
BasicShapes["roundComment"] = "roundComment";
|
|
33
|
+
})(BasicShapes || (BasicShapes = {}));
|
|
34
|
+
var FlowchartSymbols;
|
|
35
|
+
(function (FlowchartSymbols) {
|
|
36
|
+
FlowchartSymbols["process"] = "process";
|
|
37
|
+
FlowchartSymbols["decision"] = "decision";
|
|
38
|
+
FlowchartSymbols["data"] = "data";
|
|
39
|
+
FlowchartSymbols["connector"] = "connector";
|
|
40
|
+
FlowchartSymbols["terminal"] = "terminal";
|
|
41
|
+
FlowchartSymbols["manualInput"] = "manualInput";
|
|
42
|
+
FlowchartSymbols["preparation"] = "preparation";
|
|
43
|
+
FlowchartSymbols["manualLoop"] = "manualLoop";
|
|
44
|
+
FlowchartSymbols["merge"] = "merge";
|
|
45
|
+
FlowchartSymbols["delay"] = "delay";
|
|
46
|
+
FlowchartSymbols["storedData"] = "storedData";
|
|
47
|
+
})(FlowchartSymbols || (FlowchartSymbols = {}));
|
|
34
48
|
const PlaitGeometry = {
|
|
35
49
|
getTextEditor(element) {
|
|
36
50
|
return PlaitGeometry.getTextManage(element).componentRef.instance.editor;
|
|
@@ -57,7 +71,7 @@ const DefaultGeometryActiveStyle = {
|
|
|
57
71
|
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
58
72
|
selectionStrokeWidth: ACTIVE_STROKE_WIDTH
|
|
59
73
|
};
|
|
60
|
-
const
|
|
74
|
+
const DefaultBasicShapeProperty = {
|
|
61
75
|
width: 100,
|
|
62
76
|
height: 100,
|
|
63
77
|
strokeColor: '#333',
|
|
@@ -71,9 +85,52 @@ const DefaultTextProperty = {
|
|
|
71
85
|
const GeometryThreshold = {
|
|
72
86
|
defaultTextMaxWidth: 34 * 14
|
|
73
87
|
};
|
|
88
|
+
const DefaultConnectorProperty = {
|
|
89
|
+
width: 44,
|
|
90
|
+
height: 44
|
|
91
|
+
};
|
|
92
|
+
const DefaultFlowchartProperty = {
|
|
93
|
+
width: 120,
|
|
94
|
+
height: 60
|
|
95
|
+
};
|
|
96
|
+
const DefaultDecisionProperty = {
|
|
97
|
+
width: 140,
|
|
98
|
+
height: 70
|
|
99
|
+
};
|
|
100
|
+
const DefaultDataProperty = {
|
|
101
|
+
width: 124,
|
|
102
|
+
height: 60
|
|
103
|
+
};
|
|
104
|
+
const DefaultManualInputProperty = {
|
|
105
|
+
width: 117,
|
|
106
|
+
height: 59
|
|
107
|
+
};
|
|
108
|
+
const DefaultMergeProperty = {
|
|
109
|
+
width: 47,
|
|
110
|
+
height: 33
|
|
111
|
+
};
|
|
112
|
+
const DefaultFlowchartPropertyMap = {
|
|
113
|
+
[FlowchartSymbols.connector]: DefaultConnectorProperty,
|
|
114
|
+
[FlowchartSymbols.process]: DefaultFlowchartProperty,
|
|
115
|
+
[FlowchartSymbols.decision]: DefaultDecisionProperty,
|
|
116
|
+
[FlowchartSymbols.data]: DefaultDataProperty,
|
|
117
|
+
[FlowchartSymbols.terminal]: DefaultFlowchartProperty,
|
|
118
|
+
[FlowchartSymbols.manualInput]: DefaultManualInputProperty,
|
|
119
|
+
[FlowchartSymbols.preparation]: DefaultFlowchartProperty,
|
|
120
|
+
[FlowchartSymbols.manualLoop]: DefaultFlowchartProperty,
|
|
121
|
+
[FlowchartSymbols.merge]: DefaultMergeProperty,
|
|
122
|
+
[FlowchartSymbols.delay]: DefaultFlowchartProperty,
|
|
123
|
+
[FlowchartSymbols.storedData]: DefaultFlowchartProperty
|
|
124
|
+
};
|
|
74
125
|
|
|
75
126
|
const getGeometryPointers = () => {
|
|
76
|
-
return Object.keys(
|
|
127
|
+
return [...Object.keys(BasicShapes), ...Object.keys(FlowchartSymbols)];
|
|
128
|
+
};
|
|
129
|
+
const getBasicPointers = () => {
|
|
130
|
+
return Object.keys(BasicShapes);
|
|
131
|
+
};
|
|
132
|
+
const getFlowchartPointers = () => {
|
|
133
|
+
return Object.keys(FlowchartSymbols);
|
|
77
134
|
};
|
|
78
135
|
const getLinePointers = () => {
|
|
79
136
|
return Object.keys(LineShape);
|
|
@@ -155,33 +212,44 @@ const getCommentPoints = (rectangle) => {
|
|
|
155
212
|
];
|
|
156
213
|
};
|
|
157
214
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
215
|
+
function createPolygonEngine(options) {
|
|
216
|
+
const getPoints = options.getPolygonPoints;
|
|
217
|
+
const engine = {
|
|
218
|
+
draw(board, rectangle, options) {
|
|
219
|
+
const points = getPoints(rectangle);
|
|
220
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
221
|
+
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
222
|
+
setStrokeLinecap(polygon, 'round');
|
|
223
|
+
return polygon;
|
|
224
|
+
},
|
|
225
|
+
isHit(rectangle, point) {
|
|
226
|
+
const points = getPoints(rectangle);
|
|
227
|
+
return isPointInPolygon(point, points);
|
|
228
|
+
},
|
|
229
|
+
getCornerPoints(rectangle) {
|
|
230
|
+
return getPoints(rectangle);
|
|
231
|
+
},
|
|
232
|
+
getNearestPoint(rectangle, point) {
|
|
233
|
+
return getNearestPointBetweenPointAndSegments(point, getPoints(rectangle));
|
|
234
|
+
},
|
|
235
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
236
|
+
const corners = getPoints(rectangle);
|
|
237
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
238
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
239
|
+
},
|
|
240
|
+
getConnectorPoints(rectangle) {
|
|
241
|
+
if (options.getConnectorPoints) {
|
|
242
|
+
return options.getConnectorPoints(rectangle);
|
|
243
|
+
}
|
|
244
|
+
return getPoints(rectangle);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
if (options.getTextRectangle) {
|
|
248
|
+
engine.getTextRectangle = options.getTextRectangle;
|
|
183
249
|
}
|
|
184
|
-
|
|
250
|
+
return engine;
|
|
251
|
+
}
|
|
252
|
+
|
|
185
253
|
const getCrossPoints = (rectangle) => {
|
|
186
254
|
return [
|
|
187
255
|
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
@@ -198,34 +266,32 @@ const getCrossPoints = (rectangle) => {
|
|
|
198
266
|
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height / 4]
|
|
199
267
|
];
|
|
200
268
|
};
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const points = RectangleClient.getEdgeCenterPoints(rectangle);
|
|
205
|
-
const rs = PlaitBoard.getRoughSVG(board);
|
|
206
|
-
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
207
|
-
setStrokeLinecap(polygon, 'round');
|
|
208
|
-
return polygon;
|
|
209
|
-
},
|
|
210
|
-
isHit(rectangle, point) {
|
|
211
|
-
const controlPoints = RectangleClient.getEdgeCenterPoints(rectangle);
|
|
212
|
-
return isPointInPolygon(point, controlPoints);
|
|
213
|
-
},
|
|
214
|
-
getCornerPoints(rectangle) {
|
|
269
|
+
const CrossEngine = createPolygonEngine({
|
|
270
|
+
getPolygonPoints: getCrossPoints,
|
|
271
|
+
getConnectorPoints(rectangle) {
|
|
215
272
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
216
273
|
},
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
274
|
+
getTextRectangle(element) {
|
|
275
|
+
const rectangle = getTextRectangle(element);
|
|
276
|
+
const width = rectangle.width;
|
|
277
|
+
rectangle.width = rectangle.width / 2;
|
|
278
|
+
rectangle.x += width / 4;
|
|
279
|
+
return rectangle;
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const DiamondEngine = createPolygonEngine({
|
|
284
|
+
getPolygonPoints: RectangleClient.getEdgeCenterPoints,
|
|
225
285
|
getConnectorPoints(rectangle) {
|
|
226
286
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
287
|
+
},
|
|
288
|
+
getTextRectangle(element) {
|
|
289
|
+
const rectangle = getTextRectangle(element);
|
|
290
|
+
rectangle.width = rectangle.width / 2;
|
|
291
|
+
rectangle.x += rectangle.width / 2;
|
|
292
|
+
return rectangle;
|
|
227
293
|
}
|
|
228
|
-
};
|
|
294
|
+
});
|
|
229
295
|
|
|
230
296
|
const EllipseEngine = {
|
|
231
297
|
draw(board, rectangle, options) {
|
|
@@ -255,6 +321,13 @@ const EllipseEngine = {
|
|
|
255
321
|
},
|
|
256
322
|
getConnectorPoints(rectangle) {
|
|
257
323
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
324
|
+
},
|
|
325
|
+
getTextRectangle(element) {
|
|
326
|
+
const rectangle = getTextRectangle(element);
|
|
327
|
+
const width = rectangle.width;
|
|
328
|
+
rectangle.width = (rectangle.width * 3) / 4;
|
|
329
|
+
rectangle.x += width / 8;
|
|
330
|
+
return rectangle;
|
|
258
331
|
}
|
|
259
332
|
};
|
|
260
333
|
function getNearestPointBetweenPointAndEllipse(point, center, rx, ry, rotation = 0) {
|
|
@@ -318,33 +391,6 @@ function getVectorBySlope(x, y, slope) {
|
|
|
318
391
|
return vector;
|
|
319
392
|
}
|
|
320
393
|
|
|
321
|
-
const HexagonEngine = {
|
|
322
|
-
draw(board, rectangle, options) {
|
|
323
|
-
const points = getHexagonPoints(rectangle);
|
|
324
|
-
const rs = PlaitBoard.getRoughSVG(board);
|
|
325
|
-
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
326
|
-
setStrokeLinecap(polygon, 'round');
|
|
327
|
-
return polygon;
|
|
328
|
-
},
|
|
329
|
-
isHit(rectangle, point) {
|
|
330
|
-
const parallelogramPoints = getHexagonPoints(rectangle);
|
|
331
|
-
return isPointInPolygon(point, parallelogramPoints);
|
|
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
394
|
const getHexagonPoints = (rectangle) => {
|
|
349
395
|
return [
|
|
350
396
|
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
@@ -355,38 +401,20 @@ const getHexagonPoints = (rectangle) => {
|
|
|
355
401
|
[rectangle.x, rectangle.y + rectangle.height / 2]
|
|
356
402
|
];
|
|
357
403
|
};
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
},
|
|
374
|
-
getNearestPoint(rectangle, point) {
|
|
375
|
-
const cornerPoints = getLeftArrowPoints(rectangle);
|
|
376
|
-
return getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
377
|
-
},
|
|
378
|
-
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
379
|
-
const corners = getLeftArrowPoints(rectangle);
|
|
380
|
-
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
381
|
-
return getEdgeOnPolygonByPoint(corners, point);
|
|
382
|
-
},
|
|
404
|
+
const HexagonEngine = createPolygonEngine({
|
|
405
|
+
getPolygonPoints: getHexagonPoints,
|
|
383
406
|
getConnectorPoints(rectangle) {
|
|
384
|
-
return
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
407
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
408
|
+
},
|
|
409
|
+
getTextRectangle(element) {
|
|
410
|
+
const rectangle = getTextRectangle(element);
|
|
411
|
+
const width = rectangle.width;
|
|
412
|
+
rectangle.width = (rectangle.width * 3) / 4;
|
|
413
|
+
rectangle.x += width / 8;
|
|
414
|
+
return rectangle;
|
|
388
415
|
}
|
|
389
|
-
};
|
|
416
|
+
});
|
|
417
|
+
|
|
390
418
|
const getLeftArrowPoints = (rectangle) => {
|
|
391
419
|
return [
|
|
392
420
|
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
@@ -398,34 +426,23 @@ const getLeftArrowPoints = (rectangle) => {
|
|
|
398
426
|
[rectangle.x + rectangle.width * 0.32, rectangle.y + rectangle.height]
|
|
399
427
|
];
|
|
400
428
|
};
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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);
|
|
429
|
+
const LeftArrowEngine = createPolygonEngine({
|
|
430
|
+
getPolygonPoints: getLeftArrowPoints,
|
|
431
|
+
getConnectorPoints: (rectangle) => {
|
|
432
|
+
return [
|
|
433
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
434
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2]
|
|
435
|
+
];
|
|
424
436
|
},
|
|
425
|
-
|
|
426
|
-
|
|
437
|
+
getTextRectangle(element) {
|
|
438
|
+
const rectangle = getTextRectangle(element);
|
|
439
|
+
const width = rectangle.width;
|
|
440
|
+
rectangle.width = rectangle.width * (1 - 0.32);
|
|
441
|
+
rectangle.x += width * 0.32;
|
|
442
|
+
return rectangle;
|
|
427
443
|
}
|
|
428
|
-
};
|
|
444
|
+
});
|
|
445
|
+
|
|
429
446
|
const getOctagonPoints = (rectangle) => {
|
|
430
447
|
return [
|
|
431
448
|
[rectangle.x + (rectangle.width * 3) / 10, rectangle.y],
|
|
@@ -438,36 +455,21 @@ const getOctagonPoints = (rectangle) => {
|
|
|
438
455
|
[rectangle.x, rectangle.y + (rectangle.height * 3) / 10]
|
|
439
456
|
];
|
|
440
457
|
};
|
|
441
|
-
|
|
442
|
-
|
|
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
|
-
},
|
|
458
|
+
const OctagonEngine = createPolygonEngine({
|
|
459
|
+
getPolygonPoints: getOctagonPoints,
|
|
465
460
|
getConnectorPoints(rectangle) {
|
|
466
|
-
|
|
467
|
-
|
|
461
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
462
|
+
},
|
|
463
|
+
getTextRectangle(element) {
|
|
464
|
+
const rectangle = getTextRectangle(element);
|
|
465
|
+
const width = rectangle.width;
|
|
466
|
+
rectangle.width = (rectangle.width * 3) / 4;
|
|
467
|
+
rectangle.x += width / 8;
|
|
468
|
+
return rectangle;
|
|
468
469
|
}
|
|
469
|
-
};
|
|
470
|
-
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
const getParallelogramPoints = (rectangle) => {
|
|
471
473
|
return [
|
|
472
474
|
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
473
475
|
[rectangle.x + rectangle.width, rectangle.y],
|
|
@@ -475,34 +477,21 @@ const getParallelogramCornerPoints = (rectangle) => {
|
|
|
475
477
|
[rectangle.x, rectangle.y + rectangle.height]
|
|
476
478
|
];
|
|
477
479
|
};
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
const
|
|
482
|
-
|
|
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);
|
|
480
|
+
const ParallelogramEngine = createPolygonEngine({
|
|
481
|
+
getPolygonPoints: getParallelogramPoints,
|
|
482
|
+
getConnectorPoints: (rectangle) => {
|
|
483
|
+
const cornerPoints = getParallelogramPoints(rectangle);
|
|
484
|
+
return getCenterPointsOnPolygon(cornerPoints);
|
|
501
485
|
},
|
|
502
|
-
|
|
503
|
-
|
|
486
|
+
getTextRectangle(element) {
|
|
487
|
+
const rectangle = getTextRectangle(element);
|
|
488
|
+
const width = rectangle.width;
|
|
489
|
+
rectangle.width = rectangle.width / 2;
|
|
490
|
+
rectangle.x += width / 4;
|
|
491
|
+
return rectangle;
|
|
504
492
|
}
|
|
505
|
-
};
|
|
493
|
+
});
|
|
494
|
+
|
|
506
495
|
const getPentagonPoints = (rectangle) => {
|
|
507
496
|
return [
|
|
508
497
|
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
@@ -512,34 +501,23 @@ const getPentagonPoints = (rectangle) => {
|
|
|
512
501
|
[rectangle.x, rectangle.y + (rectangle.height * 2) / 5]
|
|
513
502
|
];
|
|
514
503
|
};
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const
|
|
519
|
-
const
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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);
|
|
504
|
+
const PentagonEngine = createPolygonEngine({
|
|
505
|
+
getPolygonPoints: getPentagonPoints,
|
|
506
|
+
getTextRectangle(element) {
|
|
507
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
508
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
509
|
+
const height = element.textHeight;
|
|
510
|
+
const originWidth = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
511
|
+
const width = (originWidth * 3) / 5;
|
|
512
|
+
return {
|
|
513
|
+
height,
|
|
514
|
+
width: width > 0 ? width : 0,
|
|
515
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + originWidth / 5,
|
|
516
|
+
y: elementRectangle.y + elementRectangle.height / 5 + ((elementRectangle.height * 4) / 5 - height) / 2
|
|
517
|
+
};
|
|
541
518
|
}
|
|
542
|
-
};
|
|
519
|
+
});
|
|
520
|
+
|
|
543
521
|
const getPentagonArrowPoints = (rectangle) => {
|
|
544
522
|
return [
|
|
545
523
|
[rectangle.x, rectangle.y],
|
|
@@ -549,34 +527,18 @@ const getPentagonArrowPoints = (rectangle) => {
|
|
|
549
527
|
[rectangle.x, rectangle.y + rectangle.height]
|
|
550
528
|
];
|
|
551
529
|
};
|
|
552
|
-
|
|
553
|
-
|
|
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
|
-
},
|
|
530
|
+
const PentagonArrowEngine = createPolygonEngine({
|
|
531
|
+
getPolygonPoints: getPentagonArrowPoints,
|
|
576
532
|
getConnectorPoints(rectangle) {
|
|
577
|
-
return
|
|
533
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
534
|
+
},
|
|
535
|
+
getTextRectangle(element) {
|
|
536
|
+
const rectangle = getTextRectangle(element);
|
|
537
|
+
rectangle.width = (rectangle.width * 3) / 5;
|
|
538
|
+
return rectangle;
|
|
578
539
|
}
|
|
579
|
-
};
|
|
540
|
+
});
|
|
541
|
+
|
|
580
542
|
const getProcessArrowPoints = (rectangle) => {
|
|
581
543
|
const wider = rectangle.width > rectangle.height / 2;
|
|
582
544
|
return [
|
|
@@ -588,6 +550,17 @@ const getProcessArrowPoints = (rectangle) => {
|
|
|
588
550
|
[rectangle.x + (wider ? rectangle.height / 2 : rectangle.width), rectangle.y + rectangle.height / 2]
|
|
589
551
|
];
|
|
590
552
|
};
|
|
553
|
+
const ProcessArrowEngine = createPolygonEngine({
|
|
554
|
+
getPolygonPoints: getProcessArrowPoints,
|
|
555
|
+
getTextRectangle(element) {
|
|
556
|
+
const rectangle = getTextRectangle(element);
|
|
557
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
558
|
+
const width = rectangle.width;
|
|
559
|
+
rectangle.width = elementRectangle.height / 2;
|
|
560
|
+
rectangle.x += elementRectangle.height / 2;
|
|
561
|
+
return rectangle;
|
|
562
|
+
}
|
|
563
|
+
});
|
|
591
564
|
|
|
592
565
|
const RectangleEngine = {
|
|
593
566
|
draw(board, rectangle, options) {
|
|
@@ -613,48 +586,31 @@ const RectangleEngine = {
|
|
|
613
586
|
}
|
|
614
587
|
};
|
|
615
588
|
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
589
|
+
const getRightArrowPoints = (rectangle) => {
|
|
590
|
+
return [
|
|
591
|
+
[rectangle.x, rectangle.y + rectangle.height * 0.2],
|
|
592
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y + rectangle.height * 0.2],
|
|
593
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y],
|
|
594
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
595
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y + rectangle.height],
|
|
596
|
+
[rectangle.x + rectangle.width * 0.68, rectangle.y + rectangle.height * 0.8],
|
|
597
|
+
[rectangle.x, rectangle.y + rectangle.height * 0.8]
|
|
598
|
+
];
|
|
599
|
+
};
|
|
600
|
+
const RightArrowEngine = createPolygonEngine({
|
|
601
|
+
getPolygonPoints: getRightArrowPoints,
|
|
602
|
+
getConnectorPoints: (rectangle) => {
|
|
603
|
+
return [
|
|
604
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
605
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2]
|
|
606
|
+
];
|
|
623
607
|
},
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
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
|
-
];
|
|
608
|
+
getTextRectangle(element) {
|
|
609
|
+
const rectangle = getTextRectangle(element);
|
|
610
|
+
rectangle.width = rectangle.width * 0.68;
|
|
611
|
+
return rectangle;
|
|
645
612
|
}
|
|
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
|
-
};
|
|
613
|
+
});
|
|
658
614
|
|
|
659
615
|
const RoundRectangleEngine = {
|
|
660
616
|
draw(board, rectangle, options) {
|
|
@@ -667,7 +623,7 @@ const RoundRectangleEngine = {
|
|
|
667
623
|
return RectangleClient.getCornerPoints(rectangle);
|
|
668
624
|
},
|
|
669
625
|
getNearestPoint(rectangle, point) {
|
|
670
|
-
return getNearestPointBetweenPointAndRoundRectangle(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
626
|
+
return getNearestPointBetweenPointAndRoundRectangle$1(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
671
627
|
},
|
|
672
628
|
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
673
629
|
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
@@ -681,7 +637,7 @@ const RoundRectangleEngine = {
|
|
|
681
637
|
const getRoundRectangleRadius = (rectangle) => {
|
|
682
638
|
return Math.min(rectangle.width * 0.1, rectangle.height * 0.1);
|
|
683
639
|
};
|
|
684
|
-
function getNearestPointBetweenPointAndRoundRectangle(point, rectangle, radius) {
|
|
640
|
+
function getNearestPointBetweenPointAndRoundRectangle$1(point, rectangle, radius) {
|
|
685
641
|
const { x: rectX, y: rectY, width, height } = rectangle;
|
|
686
642
|
const cornerPoints = RectangleClient.getCornerPoints(rectangle);
|
|
687
643
|
let result = getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
@@ -731,7 +687,7 @@ const RoundCommentEngine = {
|
|
|
731
687
|
const point9 = [x1 + rectangle.width / 4, y2];
|
|
732
688
|
const point10 = [x1 + rectangle.width / 4, rectangle.y + rectangle.height];
|
|
733
689
|
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);
|
|
690
|
+
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, fillStyle: 'solid' });
|
|
735
691
|
},
|
|
736
692
|
isHit(rectangle, point) {
|
|
737
693
|
const points = [
|
|
@@ -786,34 +742,82 @@ const getRoundCommentPoints = (rectangle) => {
|
|
|
786
742
|
];
|
|
787
743
|
};
|
|
788
744
|
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
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);
|
|
745
|
+
const getTrapezoidPoints = (rectangle) => {
|
|
746
|
+
return [
|
|
747
|
+
[rectangle.x + rectangle.width * 0.15, rectangle.y],
|
|
748
|
+
[rectangle.x + rectangle.width * 0.85, rectangle.y],
|
|
749
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
|
|
750
|
+
[rectangle.x, rectangle.y + rectangle.height]
|
|
751
|
+
];
|
|
752
|
+
};
|
|
753
|
+
const TrapezoidEngine = createPolygonEngine({
|
|
754
|
+
getPolygonPoints: getTrapezoidPoints,
|
|
755
|
+
getConnectorPoints(rectangle) {
|
|
756
|
+
const points = getTrapezoidPoints(rectangle);
|
|
757
|
+
return getCenterPointsOnPolygon(points);
|
|
811
758
|
},
|
|
759
|
+
getTextRectangle(element) {
|
|
760
|
+
const rectangle = getTextRectangle(element);
|
|
761
|
+
const width = rectangle.width;
|
|
762
|
+
rectangle.width = (rectangle.width * 3) / 4;
|
|
763
|
+
rectangle.x += width / 8;
|
|
764
|
+
return rectangle;
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
const getTrianglePoints = (rectangle) => {
|
|
769
|
+
return [
|
|
770
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
771
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
|
|
772
|
+
[rectangle.x, rectangle.y + rectangle.height]
|
|
773
|
+
];
|
|
774
|
+
};
|
|
775
|
+
const TriangleEngine = createPolygonEngine({
|
|
776
|
+
getPolygonPoints: getTrianglePoints,
|
|
812
777
|
getConnectorPoints(rectangle) {
|
|
813
|
-
const
|
|
814
|
-
|
|
778
|
+
const cornerPoints = getTrianglePoints(rectangle);
|
|
779
|
+
const lineCenterPoints = getCenterPointsOnPolygon(cornerPoints);
|
|
780
|
+
return [...lineCenterPoints, ...cornerPoints];
|
|
781
|
+
},
|
|
782
|
+
getTextRectangle(element) {
|
|
783
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
784
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
785
|
+
const height = element.textHeight;
|
|
786
|
+
const originWidth = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
787
|
+
const width = (originWidth * 2) / 3;
|
|
788
|
+
return {
|
|
789
|
+
height,
|
|
790
|
+
width: width > 0 ? width : 0,
|
|
791
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + originWidth / 6,
|
|
792
|
+
y: elementRectangle.y + (elementRectangle.height * 3) / 5 + ((elementRectangle.height * 2) / 5 - height) / 2
|
|
793
|
+
};
|
|
815
794
|
}
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
const getTwoWayArrowPoints = (rectangle) => {
|
|
798
|
+
return [
|
|
799
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
800
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y],
|
|
801
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y + rectangle.height / 5],
|
|
802
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y + rectangle.height / 5],
|
|
803
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y],
|
|
804
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
805
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y + rectangle.height],
|
|
806
|
+
[rectangle.x + (rectangle.width * 17) / 25, rectangle.y + (rectangle.height * 4) / 5],
|
|
807
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y + (rectangle.height * 4) / 5],
|
|
808
|
+
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y + rectangle.height]
|
|
809
|
+
];
|
|
816
810
|
};
|
|
811
|
+
const TwoWayArrowEngine = createPolygonEngine({
|
|
812
|
+
getPolygonPoints: getTwoWayArrowPoints,
|
|
813
|
+
getConnectorPoints: (rectangle) => {
|
|
814
|
+
return [
|
|
815
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
816
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2]
|
|
817
|
+
];
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
|
|
817
821
|
const getStarPoints = (rectangle) => {
|
|
818
822
|
return [
|
|
819
823
|
[rectangle.x + rectangle.width / 2, rectangle.y + (rectangle.height * 75) / 91],
|
|
@@ -828,169 +832,679 @@ const getStarPoints = (rectangle) => {
|
|
|
828
832
|
[rectangle.x + (rectangle.width * 77.3892626) / 96, rectangle.y + rectangle.height]
|
|
829
833
|
];
|
|
830
834
|
};
|
|
835
|
+
const StarEngine = createPolygonEngine({
|
|
836
|
+
getPolygonPoints: getStarPoints,
|
|
837
|
+
getConnectorPoints: (rectangle) => {
|
|
838
|
+
const points = getStarPoints(rectangle);
|
|
839
|
+
return [points[1], points[3], points[5], points[7], points[9]];
|
|
840
|
+
},
|
|
841
|
+
getTextRectangle(element) {
|
|
842
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
843
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
844
|
+
const height = element.textHeight;
|
|
845
|
+
const originWidth = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
846
|
+
const width = originWidth / 2;
|
|
847
|
+
return {
|
|
848
|
+
height,
|
|
849
|
+
width: width > 0 ? width : 0,
|
|
850
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + originWidth / 4,
|
|
851
|
+
y: elementRectangle.y + (elementRectangle.height * 1) / 5 + ((elementRectangle.height * 4) / 5 - height) / 2
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
});
|
|
831
855
|
|
|
832
|
-
const
|
|
856
|
+
const TerminalEngine = {
|
|
833
857
|
draw(board, rectangle, options) {
|
|
834
|
-
|
|
835
|
-
const rs = PlaitBoard.getRoughSVG(board);
|
|
836
|
-
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
837
|
-
setStrokeLinecap(polygon, 'round');
|
|
838
|
-
return polygon;
|
|
858
|
+
return drawRoundRectangle(PlaitBoard.getRoughSVG(board), rectangle.x, rectangle.y, rectangle.x + rectangle.width, rectangle.y + rectangle.height, { ...options, fillStyle: 'solid' }, false, getStartEndRadius(rectangle));
|
|
839
859
|
},
|
|
840
860
|
isHit(rectangle, point) {
|
|
841
|
-
|
|
842
|
-
return isPointInPolygon(point, points);
|
|
861
|
+
return isPointInRoundRectangle(point, rectangle, getStartEndRadius(rectangle));
|
|
843
862
|
},
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
return getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
863
|
+
getCornerPoints(rectangle) {
|
|
864
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
847
865
|
},
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
return getCenterPointsOnPolygon(points);
|
|
866
|
+
getNearestPoint(rectangle, point) {
|
|
867
|
+
return getNearestPointBetweenPointAndRoundRectangle(point, rectangle, getStartEndRadius(rectangle));
|
|
851
868
|
},
|
|
852
869
|
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
853
|
-
const corners =
|
|
870
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
854
871
|
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
855
872
|
return getEdgeOnPolygonByPoint(corners, point);
|
|
856
873
|
},
|
|
857
|
-
|
|
858
|
-
return
|
|
874
|
+
getConnectorPoints(rectangle) {
|
|
875
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
859
876
|
}
|
|
860
877
|
};
|
|
861
|
-
const
|
|
878
|
+
const getStartEndRadius = (rectangle) => {
|
|
879
|
+
return Math.min(rectangle.width / 2, rectangle.height / 2);
|
|
880
|
+
};
|
|
881
|
+
function getNearestPointBetweenPointAndRoundRectangle(point, rectangle, radius) {
|
|
882
|
+
const { x: rectX, y: rectY, width, height } = rectangle;
|
|
883
|
+
const cornerPoints = RectangleClient.getCornerPoints(rectangle);
|
|
884
|
+
let result = getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
885
|
+
let circleCenter = null;
|
|
886
|
+
const inLeftTop = point[0] >= rectX && point[0] <= rectX + radius && point[1] >= rectY && point[1] <= rectY + radius;
|
|
887
|
+
if (inLeftTop) {
|
|
888
|
+
circleCenter = [rectX + radius, rectY + radius];
|
|
889
|
+
}
|
|
890
|
+
const inLeftBottom = point[0] >= rectX && point[0] <= rectX + radius && point[1] >= rectY + height && point[1] <= rectY + height - radius;
|
|
891
|
+
if (inLeftBottom) {
|
|
892
|
+
circleCenter = [rectX + radius, rectY + height - radius];
|
|
893
|
+
}
|
|
894
|
+
const inRightTop = point[0] >= rectX + width - radius && point[0] <= rectX + width && point[1] >= rectY && point[1] <= rectY + radius;
|
|
895
|
+
if (inRightTop) {
|
|
896
|
+
circleCenter = [rectX + width - radius, rectY + radius];
|
|
897
|
+
}
|
|
898
|
+
const inRightBottom = point[0] >= rectX + width - radius &&
|
|
899
|
+
point[0] <= rectX + width &&
|
|
900
|
+
point[1] >= rectY + height - radius &&
|
|
901
|
+
point[1] <= rectY + height;
|
|
902
|
+
if (inRightBottom) {
|
|
903
|
+
circleCenter = [rectX + width - radius, rectY + height - radius];
|
|
904
|
+
}
|
|
905
|
+
if (circleCenter) {
|
|
906
|
+
result = getNearestPointBetweenPointAndEllipse(point, circleCenter, radius, radius);
|
|
907
|
+
}
|
|
908
|
+
return result;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
const getManualInputPoints = (rectangle) => {
|
|
862
912
|
return [
|
|
863
|
-
[rectangle.x + rectangle.
|
|
864
|
-
[rectangle.x + rectangle.width
|
|
913
|
+
[rectangle.x, rectangle.y + rectangle.height / 4],
|
|
914
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
865
915
|
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
|
|
866
916
|
[rectangle.x, rectangle.y + rectangle.height]
|
|
867
917
|
];
|
|
868
918
|
};
|
|
919
|
+
const ManualInputEngine = createPolygonEngine({
|
|
920
|
+
getPolygonPoints: getManualInputPoints,
|
|
921
|
+
getConnectorPoints: (rectangle) => {
|
|
922
|
+
const cornerPoints = getManualInputPoints(rectangle);
|
|
923
|
+
return getCenterPointsOnPolygon(cornerPoints);
|
|
924
|
+
},
|
|
925
|
+
getTextRectangle: (element) => {
|
|
926
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
927
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
928
|
+
const height = element.textHeight;
|
|
929
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
930
|
+
return {
|
|
931
|
+
height,
|
|
932
|
+
width: width > 0 ? width : 0,
|
|
933
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
934
|
+
y: elementRectangle.y + elementRectangle.height / 4 + ((elementRectangle.height * 3) / 4 - height) / 2
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
|
|
939
|
+
const getPreparationPoints = (rectangle) => {
|
|
940
|
+
return [
|
|
941
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
942
|
+
[rectangle.x + rectangle.width / 6, rectangle.y],
|
|
943
|
+
[rectangle.x + (rectangle.width * 5) / 6, rectangle.y],
|
|
944
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
945
|
+
[rectangle.x + (rectangle.width * 5) / 6, rectangle.y + rectangle.height],
|
|
946
|
+
[rectangle.x + rectangle.width / 6, rectangle.y + rectangle.height]
|
|
947
|
+
];
|
|
948
|
+
};
|
|
949
|
+
const PreparationEngine = createPolygonEngine({
|
|
950
|
+
getPolygonPoints: getPreparationPoints,
|
|
951
|
+
getConnectorPoints: (rectangle) => {
|
|
952
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
953
|
+
},
|
|
954
|
+
getTextRectangle(element) {
|
|
955
|
+
const rectangle = getTextRectangle(element);
|
|
956
|
+
const width = rectangle.width;
|
|
957
|
+
rectangle.width = (rectangle.width * 2) / 3;
|
|
958
|
+
rectangle.x += width / 6;
|
|
959
|
+
return rectangle;
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
|
|
963
|
+
const getManualLoopPoints = (rectangle) => {
|
|
964
|
+
return [
|
|
965
|
+
[rectangle.x, rectangle.y],
|
|
966
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
967
|
+
[rectangle.x + (rectangle.width * 7) / 8, rectangle.y + rectangle.height],
|
|
968
|
+
[rectangle.x + rectangle.width / 8, rectangle.y + rectangle.height]
|
|
969
|
+
];
|
|
970
|
+
};
|
|
971
|
+
const ManualLoopEngine = createPolygonEngine({
|
|
972
|
+
getPolygonPoints: getManualLoopPoints,
|
|
973
|
+
getConnectorPoints: (rectangle) => {
|
|
974
|
+
const cornerPoints = getManualLoopPoints(rectangle);
|
|
975
|
+
return getCenterPointsOnPolygon(cornerPoints);
|
|
976
|
+
},
|
|
977
|
+
getTextRectangle(element) {
|
|
978
|
+
const rectangle = getTextRectangle(element);
|
|
979
|
+
const width = rectangle.width;
|
|
980
|
+
rectangle.width = (rectangle.width * 3) / 4;
|
|
981
|
+
rectangle.x += width / 8;
|
|
982
|
+
return rectangle;
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
const getMergePoints = (rectangle) => {
|
|
987
|
+
return [
|
|
988
|
+
[rectangle.x, rectangle.y],
|
|
989
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
990
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height]
|
|
991
|
+
];
|
|
992
|
+
};
|
|
993
|
+
const MergeEngine = createPolygonEngine({
|
|
994
|
+
getPolygonPoints: getMergePoints,
|
|
995
|
+
getConnectorPoints: (rectangle) => {
|
|
996
|
+
const cornerPoints = getMergePoints(rectangle);
|
|
997
|
+
const lineCenterPoints = getCenterPointsOnPolygon(cornerPoints);
|
|
998
|
+
return [...lineCenterPoints, ...cornerPoints];
|
|
999
|
+
},
|
|
1000
|
+
getTextRectangle(element) {
|
|
1001
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
1002
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1003
|
+
const height = element.textHeight;
|
|
1004
|
+
const originWidth = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
1005
|
+
const width = (originWidth * 2) / 3;
|
|
1006
|
+
return {
|
|
1007
|
+
height,
|
|
1008
|
+
width: width > 0 ? width : 0,
|
|
1009
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + originWidth / 6,
|
|
1010
|
+
y: elementRectangle.y + ((elementRectangle.height * 2) / 3 - height) / 2
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
});
|
|
869
1014
|
|
|
870
|
-
const
|
|
1015
|
+
const DelayEngine = {
|
|
871
1016
|
draw(board, rectangle, options) {
|
|
872
|
-
const points = getTrianglePoints(rectangle);
|
|
873
1017
|
const rs = PlaitBoard.getRoughSVG(board);
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
|
|
1018
|
+
const shape = rs.path(`M${rectangle.x} ${rectangle.y} L${rectangle.x + (rectangle.width * 3) / 4} ${rectangle.y} A ${rectangle.width /
|
|
1019
|
+
4} ${rectangle.height / 2}, 0, 0, 1,${rectangle.x + (rectangle.width * 3) / 4} ${rectangle.y + rectangle.height} L${rectangle.x} ${rectangle.y + rectangle.height} Z`, { ...options, fillStyle: 'solid' });
|
|
1020
|
+
setStrokeLinecap(shape, 'round');
|
|
1021
|
+
return shape;
|
|
877
1022
|
},
|
|
878
1023
|
isHit(rectangle, point) {
|
|
879
|
-
|
|
880
|
-
|
|
1024
|
+
//split shape to rectangle and a half ellipse
|
|
1025
|
+
const rangeRectangle = RectangleClient.toRectangleClient([point, point]);
|
|
1026
|
+
const isInRectangle = RectangleClient.isHit({
|
|
1027
|
+
...rectangle,
|
|
1028
|
+
width: (rectangle.width * 3) / 4
|
|
1029
|
+
}, rangeRectangle);
|
|
1030
|
+
const isInEllipse = isPointInEllipse(point, [rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height / 2], rectangle.width / 4, rectangle.height / 2);
|
|
1031
|
+
return isInRectangle || isInEllipse;
|
|
1032
|
+
},
|
|
1033
|
+
getCornerPoints(rectangle) {
|
|
1034
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
881
1035
|
},
|
|
882
1036
|
getNearestPoint(rectangle, point) {
|
|
883
|
-
const
|
|
884
|
-
|
|
1037
|
+
const nearestPoint = getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
1038
|
+
if (nearestPoint[0] > rectangle.x + (rectangle.width * 3) / 4) {
|
|
1039
|
+
return getNearestPointBetweenPointAndEllipse(point, [rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height / 2], rectangle.width / 4, rectangle.height / 2);
|
|
1040
|
+
}
|
|
1041
|
+
return nearestPoint;
|
|
1042
|
+
},
|
|
1043
|
+
getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
|
|
1044
|
+
const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
1045
|
+
const centerPoint = [rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height / 2];
|
|
1046
|
+
const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
|
|
1047
|
+
const a = rectangle.width / 4;
|
|
1048
|
+
const b = rectangle.height / 2;
|
|
1049
|
+
const slope = getTangentSlope(point[0], point[1], a, b);
|
|
1050
|
+
return getVectorBySlope(point[0], point[1], slope);
|
|
885
1051
|
},
|
|
886
1052
|
getConnectorPoints(rectangle) {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1053
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
const StoredDataEngine = {
|
|
1058
|
+
draw(board, rectangle, options) {
|
|
1059
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
1060
|
+
const shape = rs.path(`M${rectangle.x + rectangle.width / 10} ${rectangle.y} L${rectangle.x + rectangle.width} ${rectangle.y} A ${rectangle.width /
|
|
1061
|
+
10} ${rectangle.height / 2}, 1, 0, 0,${rectangle.x + rectangle.width} ${rectangle.y + rectangle.height} L${rectangle.x +
|
|
1062
|
+
rectangle.width / 10} ${rectangle.y + rectangle.height}A ${rectangle.width / 10} ${rectangle.height /
|
|
1063
|
+
2}, 0, 0, 1,${rectangle.x + rectangle.width / 10} ${rectangle.y}`, { ...options, fillStyle: 'solid' });
|
|
1064
|
+
setStrokeLinecap(shape, 'round');
|
|
1065
|
+
return shape;
|
|
890
1066
|
},
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
const
|
|
894
|
-
|
|
1067
|
+
isHit(rectangle, point) {
|
|
1068
|
+
//split shape to rectangle and a half ellipse
|
|
1069
|
+
const rangeRectangle = RectangleClient.toRectangleClient([point, point]);
|
|
1070
|
+
const isInRectangle = RectangleClient.isHit({
|
|
1071
|
+
...rectangle,
|
|
1072
|
+
x: rectangle.x + rectangle.width / 10,
|
|
1073
|
+
width: (rectangle.width * 9) / 10
|
|
1074
|
+
}, rangeRectangle);
|
|
1075
|
+
const isInFrontEllipse = isPointInEllipse(point, [rectangle.x + rectangle.width / 10, rectangle.y + rectangle.height / 2], rectangle.width / 10, rectangle.height / 2);
|
|
1076
|
+
const notInBackEllipse = !isPointInEllipse(point, [rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2], rectangle.width / 10, rectangle.height / 2);
|
|
1077
|
+
return (isInRectangle && notInBackEllipse) || isInFrontEllipse;
|
|
895
1078
|
},
|
|
896
1079
|
getCornerPoints(rectangle) {
|
|
897
|
-
return
|
|
898
|
-
}
|
|
1080
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
1081
|
+
},
|
|
1082
|
+
getNearestPoint(rectangle, point) {
|
|
1083
|
+
const nearestPoint = getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
1084
|
+
if (nearestPoint[0] < rectangle.x + rectangle.width / 10) {
|
|
1085
|
+
const nearestPoint = getNearestPointBetweenPointAndEllipse(point, [rectangle.x + rectangle.width / 10, rectangle.y + rectangle.height / 2], rectangle.width / 10, rectangle.height / 2);
|
|
1086
|
+
if (nearestPoint[0] > rectangle.x + rectangle.width / 10) {
|
|
1087
|
+
nearestPoint[0] = (rectangle.x + rectangle.width / 10) * 2 - nearestPoint[0];
|
|
1088
|
+
}
|
|
1089
|
+
return nearestPoint;
|
|
1090
|
+
}
|
|
1091
|
+
if (nearestPoint[0] > rectangle.x + (rectangle.width * 9) / 10) {
|
|
1092
|
+
return getNearestPointBetweenPointAndEllipse(point, [rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2], rectangle.width / 10, rectangle.height / 2);
|
|
1093
|
+
}
|
|
1094
|
+
return nearestPoint;
|
|
1095
|
+
},
|
|
1096
|
+
getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
|
|
1097
|
+
const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
1098
|
+
let centerPoint = [rectangle.x + rectangle.width / 10, rectangle.y + rectangle.height / 2];
|
|
1099
|
+
let a = rectangle.width / 10;
|
|
1100
|
+
let b = rectangle.height / 2;
|
|
1101
|
+
const isBackEllipse = connectionPoint[0] > rectangle.x + (rectangle.width * 9) / 10 && connectionPoint[1] > rectangle.y;
|
|
1102
|
+
if (isBackEllipse) {
|
|
1103
|
+
centerPoint = [rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2];
|
|
1104
|
+
}
|
|
1105
|
+
const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
|
|
1106
|
+
const slope = getTangentSlope(point[0], point[1], a, b);
|
|
1107
|
+
const vector = getVectorBySlope(point[0], point[1], slope);
|
|
1108
|
+
return isBackEllipse ? vector.map(num => -num) : vector;
|
|
1109
|
+
},
|
|
1110
|
+
getConnectorPoints(rectangle) {
|
|
1111
|
+
return [
|
|
1112
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
1113
|
+
[rectangle.x + (rectangle.width * 9) / 10, rectangle.y + rectangle.height / 2],
|
|
1114
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height],
|
|
1115
|
+
[rectangle.x, rectangle.y + rectangle.height / 2]
|
|
1116
|
+
];
|
|
1117
|
+
},
|
|
1118
|
+
getTextRectangle(element) {
|
|
1119
|
+
const rectangle = getTextRectangle(element);
|
|
1120
|
+
const width = rectangle.width;
|
|
1121
|
+
rectangle.width = (rectangle.width * 3) / 4;
|
|
1122
|
+
rectangle.x += width / 8;
|
|
1123
|
+
return rectangle;
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
const ShapeEngineMap = {
|
|
1128
|
+
[BasicShapes.rectangle]: RectangleEngine,
|
|
1129
|
+
[BasicShapes.diamond]: DiamondEngine,
|
|
1130
|
+
[BasicShapes.ellipse]: EllipseEngine,
|
|
1131
|
+
[BasicShapes.parallelogram]: ParallelogramEngine,
|
|
1132
|
+
[BasicShapes.roundRectangle]: RoundRectangleEngine,
|
|
1133
|
+
[BasicShapes.text]: RectangleEngine,
|
|
1134
|
+
[BasicShapes.triangle]: TriangleEngine,
|
|
1135
|
+
[BasicShapes.leftArrow]: LeftArrowEngine,
|
|
1136
|
+
[BasicShapes.trapezoid]: TrapezoidEngine,
|
|
1137
|
+
[BasicShapes.rightArrow]: RightArrowEngine,
|
|
1138
|
+
[BasicShapes.cross]: CrossEngine,
|
|
1139
|
+
[BasicShapes.star]: StarEngine,
|
|
1140
|
+
[BasicShapes.pentagon]: PentagonEngine,
|
|
1141
|
+
[BasicShapes.hexagon]: HexagonEngine,
|
|
1142
|
+
[BasicShapes.octagon]: OctagonEngine,
|
|
1143
|
+
[BasicShapes.pentagonArrow]: PentagonArrowEngine,
|
|
1144
|
+
[BasicShapes.processArrow]: ProcessArrowEngine,
|
|
1145
|
+
[BasicShapes.twoWayArrow]: TwoWayArrowEngine,
|
|
1146
|
+
[BasicShapes.comment]: CommentEngine,
|
|
1147
|
+
[BasicShapes.roundComment]: RoundCommentEngine,
|
|
1148
|
+
[FlowchartSymbols.process]: RectangleEngine,
|
|
1149
|
+
[FlowchartSymbols.decision]: DiamondEngine,
|
|
1150
|
+
[FlowchartSymbols.connector]: EllipseEngine,
|
|
1151
|
+
[FlowchartSymbols.data]: ParallelogramEngine,
|
|
1152
|
+
[FlowchartSymbols.terminal]: TerminalEngine,
|
|
1153
|
+
[FlowchartSymbols.manualInput]: ManualInputEngine,
|
|
1154
|
+
[FlowchartSymbols.preparation]: PreparationEngine,
|
|
1155
|
+
[FlowchartSymbols.manualLoop]: ManualLoopEngine,
|
|
1156
|
+
[FlowchartSymbols.merge]: MergeEngine,
|
|
1157
|
+
[FlowchartSymbols.delay]: DelayEngine,
|
|
1158
|
+
[FlowchartSymbols.storedData]: StoredDataEngine
|
|
1159
|
+
};
|
|
1160
|
+
const getEngine = (shape) => {
|
|
1161
|
+
return ShapeEngineMap[shape];
|
|
1162
|
+
};
|
|
1163
|
+
|
|
1164
|
+
const getShape = (value) => {
|
|
1165
|
+
if (PlaitDrawElement.isImage(value)) {
|
|
1166
|
+
return BasicShapes.rectangle;
|
|
1167
|
+
}
|
|
1168
|
+
return value.shape;
|
|
1169
|
+
};
|
|
1170
|
+
|
|
1171
|
+
class GeometryShapeGenerator extends Generator {
|
|
1172
|
+
canDraw(element, data) {
|
|
1173
|
+
return true;
|
|
1174
|
+
}
|
|
1175
|
+
baseDraw(element, data) {
|
|
1176
|
+
const rectangle = getRectangleByPoints(element.points);
|
|
1177
|
+
const shape = element.shape;
|
|
1178
|
+
if (shape === BasicShapes.text) {
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1182
|
+
const strokeColor = getStrokeColorByElement(element);
|
|
1183
|
+
const fill = getFillByElement(element);
|
|
1184
|
+
const strokeLineDash = getLineDashByElement(element);
|
|
1185
|
+
return drawGeometry(this.board, RectangleClient.inflate(rectangle, -strokeWidth), shape, {
|
|
1186
|
+
stroke: strokeColor,
|
|
1187
|
+
strokeWidth,
|
|
1188
|
+
fill,
|
|
1189
|
+
strokeLineDash
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
const insertGeometry = (board, points, shape) => {
|
|
1195
|
+
let newElement = createGeometryElement(shape, points, '', {
|
|
1196
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1197
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1198
|
+
});
|
|
1199
|
+
Transforms.insertNode(board, newElement, [board.children.length]);
|
|
1200
|
+
clearSelectedElement(board);
|
|
1201
|
+
addSelectedElement(board, newElement);
|
|
1202
|
+
};
|
|
1203
|
+
const insertText = (board, points, text = '文本') => {
|
|
1204
|
+
let newElement = createGeometryElement(BasicShapes.text, points, text);
|
|
1205
|
+
Transforms.insertNode(board, newElement, [board.children.length]);
|
|
1206
|
+
clearSelectedElement(board);
|
|
1207
|
+
addSelectedElement(board, newElement);
|
|
1208
|
+
};
|
|
1209
|
+
const resizeGeometry = (board, points, textHeight, path) => {
|
|
1210
|
+
const normalizePoints = normalizeShapePoints(points);
|
|
1211
|
+
const element = PlaitNode.get(board, path);
|
|
1212
|
+
const newHeight = textHeight / board.viewport.zoom;
|
|
1213
|
+
const newProperties = { points: normalizePoints, textHeight: newHeight };
|
|
1214
|
+
if (PlaitDrawElement.isText(element) && element.autoSize) {
|
|
1215
|
+
newProperties.autoSize = false;
|
|
1216
|
+
}
|
|
1217
|
+
Transforms.setNode(board, newProperties, path);
|
|
1218
|
+
};
|
|
1219
|
+
|
|
1220
|
+
const normalizePoints = (board, element, width, textHeight) => {
|
|
1221
|
+
let points = element.points;
|
|
1222
|
+
let autoSize = element.autoSize;
|
|
1223
|
+
const defaultSpace = ShapeDefaultSpace.rectangleAndText;
|
|
1224
|
+
if (autoSize) {
|
|
1225
|
+
const editor = PlaitGeometry.getTextEditor(element);
|
|
1226
|
+
if (AlignEditor.isActive(editor, Alignment.right)) {
|
|
1227
|
+
points = [
|
|
1228
|
+
[points[1][0] - (width + defaultSpace * 2), points[0][1]],
|
|
1229
|
+
[points[1][0], points[0][1] + textHeight]
|
|
1230
|
+
];
|
|
1231
|
+
}
|
|
1232
|
+
else if (AlignEditor.isActive(editor, Alignment.center)) {
|
|
1233
|
+
const oldWidth = Math.abs(points[0][0] - points[1][0]);
|
|
1234
|
+
const offset = (width - oldWidth) / 2;
|
|
1235
|
+
points = [
|
|
1236
|
+
[points[0][0] - offset - defaultSpace, points[0][1]],
|
|
1237
|
+
[points[1][0] + offset + defaultSpace, points[0][1] + textHeight]
|
|
1238
|
+
];
|
|
1239
|
+
}
|
|
1240
|
+
else {
|
|
1241
|
+
points = [points[0], [points[0][0] + width + defaultSpace * 2, points[0][1] + textHeight]];
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
return { points };
|
|
1245
|
+
};
|
|
1246
|
+
const setText = (board, element, text, width, textHeight) => {
|
|
1247
|
+
const newElement = {
|
|
1248
|
+
text,
|
|
1249
|
+
textHeight,
|
|
1250
|
+
...normalizePoints(board, element, width, textHeight)
|
|
1251
|
+
};
|
|
1252
|
+
const path = board.children.findIndex(child => child === element);
|
|
1253
|
+
Transforms.setNode(board, newElement, [path]);
|
|
1254
|
+
};
|
|
1255
|
+
const setTextSize = (board, element, textWidth, textHeight) => {
|
|
1256
|
+
if (element.autoSize) {
|
|
1257
|
+
const newElement = {
|
|
1258
|
+
textHeight,
|
|
1259
|
+
...normalizePoints(board, element, textWidth, textHeight)
|
|
1260
|
+
};
|
|
1261
|
+
const isPointsEqual = Point.isEquals(element.points[0], newElement.points[0]) && Point.isEquals(element.points[1], newElement.points[1]);
|
|
1262
|
+
const isTextHeightEqual = Math.round(textHeight) === Math.round(element.textHeight);
|
|
1263
|
+
if (!isPointsEqual || !isTextHeightEqual) {
|
|
1264
|
+
const path = board.children.findIndex(child => child === element);
|
|
1265
|
+
Transforms.setNode(board, newElement, [path]);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
const insertImage = (board, imageItem, startPoint) => {
|
|
1271
|
+
const { width, height, url } = imageItem;
|
|
1272
|
+
const host = BOARD_TO_HOST.get(board);
|
|
1273
|
+
const viewportWidth = PlaitBoard.getComponent(board).nativeElement.clientWidth;
|
|
1274
|
+
const viewportHeight = PlaitBoard.getComponent(board).nativeElement.clientHeight;
|
|
1275
|
+
const point = transformPoint(board, toPoint(viewportWidth / 2, viewportHeight / 2, host));
|
|
1276
|
+
const points = startPoint
|
|
1277
|
+
? [startPoint, [startPoint[0] + width, startPoint[1] + height]]
|
|
1278
|
+
: [
|
|
1279
|
+
[point[0] - width / 2, point[1] - height / 2],
|
|
1280
|
+
[point[0] + width / 2, point[1] + height / 2]
|
|
1281
|
+
];
|
|
1282
|
+
const imageElement = {
|
|
1283
|
+
id: idCreator(),
|
|
1284
|
+
type: 'image',
|
|
1285
|
+
points,
|
|
1286
|
+
url
|
|
1287
|
+
};
|
|
1288
|
+
Transforms.insertNode(board, imageElement, [board.children.length]);
|
|
1289
|
+
Transforms.addSelectionWithTemporaryElements(board, [imageElement]);
|
|
1290
|
+
};
|
|
1291
|
+
|
|
1292
|
+
const resizeLine = (board, options, path) => {
|
|
1293
|
+
Transforms.setNode(board, options, path);
|
|
1294
|
+
};
|
|
1295
|
+
const setLineTexts = (board, element, texts) => {
|
|
1296
|
+
const path = PlaitBoard.findPath(board, element);
|
|
1297
|
+
Transforms.setNode(board, { texts }, path);
|
|
1298
|
+
};
|
|
1299
|
+
const removeLineText = (board, element, index) => {
|
|
1300
|
+
const path = PlaitBoard.findPath(board, element);
|
|
1301
|
+
const texts = element.texts?.length ? [...element.texts] : [];
|
|
1302
|
+
const newTexts = [...texts];
|
|
1303
|
+
newTexts.splice(index, 1);
|
|
1304
|
+
Transforms.setNode(board, { texts: newTexts }, path);
|
|
1305
|
+
};
|
|
1306
|
+
const setLineMark = (board, element, handleKey, marker) => {
|
|
1307
|
+
const path = PlaitBoard.findPath(board, element);
|
|
1308
|
+
let handle = handleKey === LineHandleKey.source ? element.source : element.target;
|
|
1309
|
+
handle = { ...handle, marker };
|
|
1310
|
+
Transforms.setNode(board, { [handleKey]: handle }, path);
|
|
1311
|
+
};
|
|
1312
|
+
|
|
1313
|
+
const DrawTransforms = {
|
|
1314
|
+
setText,
|
|
1315
|
+
insertGeometry,
|
|
1316
|
+
resizeGeometry,
|
|
1317
|
+
insertText,
|
|
1318
|
+
setTextSize,
|
|
1319
|
+
resizeLine,
|
|
1320
|
+
setLineTexts,
|
|
1321
|
+
removeLineText,
|
|
1322
|
+
setLineMark,
|
|
1323
|
+
insertImage
|
|
1324
|
+
};
|
|
1325
|
+
|
|
1326
|
+
const withGeometryCreateByDrag = (board) => {
|
|
1327
|
+
const { pointerMove, pointerUp } = board;
|
|
1328
|
+
let geometryShapeG = null;
|
|
1329
|
+
board.pointerMove = (event) => {
|
|
1330
|
+
geometryShapeG?.remove();
|
|
1331
|
+
geometryShapeG = createG();
|
|
1332
|
+
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
1333
|
+
const geometryPointers = getGeometryPointers();
|
|
1334
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1335
|
+
const dragMode = isGeometryPointer && isDndMode(board);
|
|
1336
|
+
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1337
|
+
const pointer = PlaitBoard.getPointer(board);
|
|
1338
|
+
if (dragMode) {
|
|
1339
|
+
const points = getDefaultGeometryPoints(pointer, movingPoint);
|
|
1340
|
+
if (pointer === BasicShapes.text) {
|
|
1341
|
+
const textG = getTemporaryTextG(movingPoint);
|
|
1342
|
+
geometryShapeG.appendChild(textG);
|
|
1343
|
+
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
1344
|
+
}
|
|
1345
|
+
else {
|
|
1346
|
+
const temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1347
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1348
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1349
|
+
});
|
|
1350
|
+
geometryGenerator.draw(temporaryElement, geometryShapeG);
|
|
1351
|
+
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
pointerMove(event);
|
|
1355
|
+
};
|
|
1356
|
+
board.pointerUp = (event) => {
|
|
1357
|
+
const pointer = PlaitBoard.getPointer(board);
|
|
1358
|
+
const geometryPointers = getGeometryPointers();
|
|
1359
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1360
|
+
const dragMode = isGeometryPointer && isDndMode(board);
|
|
1361
|
+
if (dragMode) {
|
|
1362
|
+
const targetPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1363
|
+
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
1364
|
+
if (pointer === BasicShapes.text) {
|
|
1365
|
+
DrawTransforms.insertText(board, points);
|
|
1366
|
+
}
|
|
1367
|
+
else {
|
|
1368
|
+
DrawTransforms.insertGeometry(board, points, pointer);
|
|
1369
|
+
}
|
|
1370
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
1371
|
+
}
|
|
1372
|
+
geometryShapeG?.remove();
|
|
1373
|
+
geometryShapeG = null;
|
|
1374
|
+
preventTouchMove(board, event, false);
|
|
1375
|
+
pointerUp(event);
|
|
1376
|
+
};
|
|
1377
|
+
return board;
|
|
1378
|
+
};
|
|
1379
|
+
const withGeometryCreateByDrawing = (board) => {
|
|
1380
|
+
const { pointerDown, pointerMove, pointerUp, keydown, keyup } = board;
|
|
1381
|
+
let start = null;
|
|
1382
|
+
let geometryShapeG = null;
|
|
1383
|
+
let temporaryElement = null;
|
|
1384
|
+
let isShift = false;
|
|
1385
|
+
board.keydown = (event) => {
|
|
1386
|
+
isShift = isKeyHotkey('shift', event);
|
|
1387
|
+
keydown(event);
|
|
1388
|
+
};
|
|
1389
|
+
board.keyup = (event) => {
|
|
1390
|
+
isShift = false;
|
|
1391
|
+
keyup(event);
|
|
1392
|
+
};
|
|
1393
|
+
board.pointerDown = (event) => {
|
|
1394
|
+
const geometryPointers = getGeometryPointers();
|
|
1395
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1396
|
+
if (isGeometryPointer && isDrawingMode(board)) {
|
|
1397
|
+
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1398
|
+
start = point;
|
|
1399
|
+
const pointer = PlaitBoard.getPointer(board);
|
|
1400
|
+
preventTouchMove(board, event, true);
|
|
1401
|
+
if (pointer === BasicShapes.text) {
|
|
1402
|
+
const points = getDefaultGeometryPoints(pointer, point);
|
|
1403
|
+
const textElement = createGeometryElement(BasicShapes.text, points, DefaultTextProperty.text);
|
|
1404
|
+
Transforms.insertNode(board, textElement, [board.children.length]);
|
|
1405
|
+
clearSelectedElement(board);
|
|
1406
|
+
addSelectedElement(board, textElement);
|
|
1407
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
1408
|
+
start = null;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
pointerDown(event);
|
|
1412
|
+
};
|
|
1413
|
+
board.pointerMove = (event) => {
|
|
1414
|
+
geometryShapeG?.remove();
|
|
1415
|
+
geometryShapeG = createG();
|
|
1416
|
+
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
1417
|
+
const drawMode = !!start;
|
|
1418
|
+
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1419
|
+
const pointer = PlaitBoard.getPointer(board);
|
|
1420
|
+
if (drawMode && pointer !== BasicShapes.text) {
|
|
1421
|
+
const points = normalizeShapePoints([start, movingPoint], isShift);
|
|
1422
|
+
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1423
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1424
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1425
|
+
});
|
|
1426
|
+
geometryGenerator.draw(temporaryElement, geometryShapeG);
|
|
1427
|
+
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
1428
|
+
}
|
|
1429
|
+
pointerMove(event);
|
|
1430
|
+
};
|
|
1431
|
+
board.pointerUp = (event) => {
|
|
1432
|
+
const isDrawMode = !!start;
|
|
1433
|
+
if (isDrawMode) {
|
|
1434
|
+
const targetPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1435
|
+
const { width, height } = RectangleClient.toRectangleClient([start, targetPoint]);
|
|
1436
|
+
if (Math.hypot(width, height) === 0) {
|
|
1437
|
+
const pointer = PlaitBoard.getPointer(board);
|
|
1438
|
+
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
1439
|
+
if (pointer !== BasicShapes.text) {
|
|
1440
|
+
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1441
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1442
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
if (temporaryElement) {
|
|
1448
|
+
Transforms.insertNode(board, temporaryElement, [board.children.length]);
|
|
1449
|
+
clearSelectedElement(board);
|
|
1450
|
+
addSelectedElement(board, temporaryElement);
|
|
1451
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
1452
|
+
}
|
|
1453
|
+
geometryShapeG?.remove();
|
|
1454
|
+
geometryShapeG = null;
|
|
1455
|
+
start = null;
|
|
1456
|
+
temporaryElement = null;
|
|
1457
|
+
preventTouchMove(board, event, false);
|
|
1458
|
+
pointerUp(event);
|
|
1459
|
+
};
|
|
1460
|
+
return board;
|
|
899
1461
|
};
|
|
900
|
-
const
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
|
|
904
|
-
[rectangle.x, rectangle.y + rectangle.height]
|
|
905
|
-
];
|
|
1462
|
+
const getDefaultGeometryPoints = (pointer, targetPoint) => {
|
|
1463
|
+
const defaultProperty = getGeometryDefaultProperty(pointer);
|
|
1464
|
+
return getPointsByCenterPoint(targetPoint, defaultProperty.width, defaultProperty.height);
|
|
906
1465
|
};
|
|
907
|
-
|
|
908
|
-
const
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
return
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
return
|
|
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
|
-
];
|
|
1466
|
+
const getGeometryDefaultProperty = (pointer) => {
|
|
1467
|
+
const isText = pointer === BasicShapes.text;
|
|
1468
|
+
const isFlowChart = getFlowchartPointers().includes(pointer);
|
|
1469
|
+
if (isText) {
|
|
1470
|
+
return DefaultTextProperty;
|
|
1471
|
+
}
|
|
1472
|
+
else if (isFlowChart) {
|
|
1473
|
+
return getDefaultFlowchartProperty(pointer);
|
|
1474
|
+
}
|
|
1475
|
+
else {
|
|
1476
|
+
return DefaultBasicShapeProperty;
|
|
937
1477
|
}
|
|
938
1478
|
};
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
[rectangle.x + (rectangle.width * 8) / 25, rectangle.y + rectangle.height]
|
|
951
|
-
];
|
|
952
|
-
};
|
|
953
|
-
|
|
954
|
-
const ShapeEngineMap = {
|
|
955
|
-
[GeometryShape.rectangle]: RectangleEngine,
|
|
956
|
-
[GeometryShape.diamond]: DiamondEngine,
|
|
957
|
-
[GeometryShape.ellipse]: EllipseEngine,
|
|
958
|
-
[GeometryShape.parallelogram]: ParallelogramEngine,
|
|
959
|
-
[GeometryShape.roundRectangle]: RoundRectangleEngine,
|
|
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
|
|
975
|
-
};
|
|
976
|
-
const getEngine = (shape) => {
|
|
977
|
-
return ShapeEngineMap[shape];
|
|
1479
|
+
const getTemporaryTextG = (movingPoint) => {
|
|
1480
|
+
const textG = createG();
|
|
1481
|
+
const width = DefaultTextProperty.width - ShapeDefaultSpace.rectangleAndText * 2;
|
|
1482
|
+
const foreignObject = createForeignObject(movingPoint[0] - width / 2, movingPoint[1] - DefaultTextProperty.height / 2, width, DefaultTextProperty.height);
|
|
1483
|
+
const richtext = document.createElement('div');
|
|
1484
|
+
richtext.textContent = DefaultTextProperty.text;
|
|
1485
|
+
richtext.style.fontSize = `${DEFAULT_FONT_SIZE}px`;
|
|
1486
|
+
richtext.style.cursor = 'default';
|
|
1487
|
+
foreignObject.appendChild(richtext);
|
|
1488
|
+
textG.appendChild(foreignObject);
|
|
1489
|
+
return textG;
|
|
978
1490
|
};
|
|
979
1491
|
|
|
980
|
-
const
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
return value.shape;
|
|
1492
|
+
const DefaultLineStyle = {
|
|
1493
|
+
strokeWidth: 2,
|
|
1494
|
+
strokeColor: '#000'
|
|
985
1495
|
};
|
|
986
1496
|
|
|
987
1497
|
const createGeometryElement = (shape, points, text, options) => {
|
|
988
1498
|
let textOptions = {};
|
|
989
1499
|
let alignment = Alignment.center;
|
|
990
|
-
if (shape ===
|
|
1500
|
+
if (shape === BasicShapes.text) {
|
|
991
1501
|
textOptions = { autoSize: true };
|
|
992
1502
|
alignment = undefined;
|
|
993
1503
|
}
|
|
1504
|
+
let flowchartOptions = {};
|
|
1505
|
+
if (getFlowchartPointers().includes(shape)) {
|
|
1506
|
+
flowchartOptions = { fill: '#ffffff' };
|
|
1507
|
+
}
|
|
994
1508
|
return {
|
|
995
1509
|
id: idCreator(),
|
|
996
1510
|
type: 'geometry',
|
|
@@ -1001,7 +1515,8 @@ const createGeometryElement = (shape, points, text, options) => {
|
|
|
1001
1515
|
text: buildText(text, alignment),
|
|
1002
1516
|
points,
|
|
1003
1517
|
...textOptions,
|
|
1004
|
-
...options
|
|
1518
|
+
...options,
|
|
1519
|
+
...flowchartOptions
|
|
1005
1520
|
};
|
|
1006
1521
|
};
|
|
1007
1522
|
const getPointsByCenterPoint = (point, width, height) => {
|
|
@@ -1073,6 +1588,66 @@ const getEdgeOnPolygonByPoint = (corners, point) => {
|
|
|
1073
1588
|
}
|
|
1074
1589
|
return null;
|
|
1075
1590
|
};
|
|
1591
|
+
const getDefaultFlowchartProperty = (symbol) => {
|
|
1592
|
+
return DefaultFlowchartPropertyMap[symbol];
|
|
1593
|
+
};
|
|
1594
|
+
const createDefaultFlowchart = (point) => {
|
|
1595
|
+
const decisionProperty = getDefaultFlowchartProperty(FlowchartSymbols.decision);
|
|
1596
|
+
const processProperty = getDefaultFlowchartProperty(FlowchartSymbols.process);
|
|
1597
|
+
const terminalProperty = getDefaultFlowchartProperty(FlowchartSymbols.terminal);
|
|
1598
|
+
const options = {
|
|
1599
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1600
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1601
|
+
};
|
|
1602
|
+
const lineOptions = {
|
|
1603
|
+
strokeColor: DefaultLineStyle.strokeColor,
|
|
1604
|
+
strokeWidth: DefaultLineStyle.strokeWidth
|
|
1605
|
+
};
|
|
1606
|
+
const startElement = createGeometryElement(FlowchartSymbols.terminal, getDefaultGeometryPoints(FlowchartSymbols.terminal, point), '开始', options);
|
|
1607
|
+
const processPoint1 = [point[0], point[1] + terminalProperty.height / 2 + 55 + processProperty.height / 2];
|
|
1608
|
+
const processElement1 = createGeometryElement(FlowchartSymbols.process, getDefaultGeometryPoints(FlowchartSymbols.process, processPoint1), '过程', options);
|
|
1609
|
+
const decisionPoint = [processPoint1[0], processPoint1[1] + processProperty.height / 2 + 55 + decisionProperty.height / 2];
|
|
1610
|
+
const decisionElement = createGeometryElement(FlowchartSymbols.decision, getDefaultGeometryPoints(FlowchartSymbols.decision, decisionPoint), '过程', options);
|
|
1611
|
+
const processPoint2 = [decisionPoint[0] + decisionProperty.width / 2 + 75 + processProperty.width / 2, decisionPoint[1]];
|
|
1612
|
+
const processElement2 = createGeometryElement(FlowchartSymbols.process, getDefaultGeometryPoints(FlowchartSymbols.process, processPoint2), '过程', options);
|
|
1613
|
+
const endPoint = [decisionPoint[0], decisionPoint[1] + decisionProperty.height / 2 + 95 + terminalProperty.height / 2];
|
|
1614
|
+
const endElement = createGeometryElement(FlowchartSymbols.terminal, getDefaultGeometryPoints(FlowchartSymbols.terminal, endPoint), '结束', options);
|
|
1615
|
+
const line1 = createLineElement(LineShape.elbow, [
|
|
1616
|
+
[0, 0],
|
|
1617
|
+
[0, 0]
|
|
1618
|
+
], { marker: LineMarkerType.none, connection: [0.5, 1], boundId: startElement.id }, { marker: LineMarkerType.arrow, connection: [0.5, 0], boundId: processElement1.id }, [], lineOptions);
|
|
1619
|
+
const line2 = createLineElement(LineShape.elbow, [
|
|
1620
|
+
[0, 0],
|
|
1621
|
+
[0, 0]
|
|
1622
|
+
], { marker: LineMarkerType.none, connection: [0.5, 1], boundId: processElement1.id }, { marker: LineMarkerType.arrow, connection: [0.5, 0], boundId: decisionElement.id }, [], lineOptions);
|
|
1623
|
+
const line3 = createLineElement(LineShape.elbow, [
|
|
1624
|
+
[0, 0],
|
|
1625
|
+
[0, 0]
|
|
1626
|
+
], { marker: LineMarkerType.none, connection: [0.5, 1], boundId: decisionElement.id }, { marker: LineMarkerType.arrow, connection: [0.5, 0], boundId: endElement.id }, [
|
|
1627
|
+
{
|
|
1628
|
+
text: buildText('是'),
|
|
1629
|
+
position: 0.5,
|
|
1630
|
+
width: 14,
|
|
1631
|
+
height: 20
|
|
1632
|
+
}
|
|
1633
|
+
], lineOptions);
|
|
1634
|
+
const line4 = createLineElement(LineShape.elbow, [
|
|
1635
|
+
[0, 0],
|
|
1636
|
+
[0, 0]
|
|
1637
|
+
], { marker: LineMarkerType.none, connection: [1, 0.5], boundId: decisionElement.id }, { marker: LineMarkerType.arrow, connection: [0, 0.5], boundId: processElement2.id }, [
|
|
1638
|
+
{
|
|
1639
|
+
text: buildText('否'),
|
|
1640
|
+
position: 0.5,
|
|
1641
|
+
width: 14,
|
|
1642
|
+
height: 20
|
|
1643
|
+
}
|
|
1644
|
+
], lineOptions);
|
|
1645
|
+
const line5 = createLineElement(LineShape.elbow, [
|
|
1646
|
+
[0, 0],
|
|
1647
|
+
[0, 0]
|
|
1648
|
+
], { marker: LineMarkerType.none, connection: [0.5, 1], boundId: processElement2.id }, { marker: LineMarkerType.arrow, connection: [1, 0.5], boundId: endElement.id }, [], lineOptions);
|
|
1649
|
+
return [startElement, processElement1, decisionElement, processElement2, endElement, line1, line2, line3, line4, line5];
|
|
1650
|
+
};
|
|
1076
1651
|
|
|
1077
1652
|
const drawLineArrow = (element, points, options) => {
|
|
1078
1653
|
const arrowG = createG();
|
|
@@ -1112,11 +1687,11 @@ const getArrow = (element, arrowOptions, options) => {
|
|
|
1112
1687
|
break;
|
|
1113
1688
|
}
|
|
1114
1689
|
case LineMarkerType.oneSideUp: {
|
|
1115
|
-
targetArrow = drawOneSideArrow(source, target, 'up', options);
|
|
1690
|
+
targetArrow = drawOneSideArrow(source, target, isSource ? 'down' : 'up', options);
|
|
1116
1691
|
break;
|
|
1117
1692
|
}
|
|
1118
1693
|
case LineMarkerType.oneSideDown: {
|
|
1119
|
-
targetArrow = drawOneSideArrow(source, target, 'down', options);
|
|
1694
|
+
targetArrow = drawOneSideArrow(source, target, isSource ? 'up' : 'down', options);
|
|
1120
1695
|
break;
|
|
1121
1696
|
}
|
|
1122
1697
|
case LineMarkerType.hollowTriangle: {
|
|
@@ -1183,13 +1758,13 @@ const drawHollowTriangleArrow = (source, target, options) => {
|
|
|
1183
1758
|
return drawLinearPath([pointLeft, pointRight, target], { ...options, fill: 'white' }, true);
|
|
1184
1759
|
};
|
|
1185
1760
|
|
|
1186
|
-
const createLineElement = (shape, points, source, target, options) => {
|
|
1761
|
+
const createLineElement = (shape, points, source, target, texts, options) => {
|
|
1187
1762
|
return {
|
|
1188
1763
|
id: idCreator(),
|
|
1189
1764
|
type: 'line',
|
|
1190
1765
|
shape,
|
|
1191
1766
|
source,
|
|
1192
|
-
texts: [],
|
|
1767
|
+
texts: texts ? texts : [],
|
|
1193
1768
|
target,
|
|
1194
1769
|
opacity: 1,
|
|
1195
1770
|
points,
|
|
@@ -1260,8 +1835,41 @@ const getLineHandleRefPair = (board, element) => {
|
|
|
1260
1835
|
const getElbowPoints = (board, element) => {
|
|
1261
1836
|
if (element.points.length === 2) {
|
|
1262
1837
|
const handleRefPair = getLineHandleRefPair(board, element);
|
|
1263
|
-
const offset = element.source.boundId || element.target.boundId ?
|
|
1264
|
-
|
|
1838
|
+
const offset = element.source.boundId || element.target.boundId ? DEFAULT_ROUTE_MARGIN : 0;
|
|
1839
|
+
const sourceElement = element.source.boundId && getElementById(board, element.source.boundId);
|
|
1840
|
+
const targetElement = element.target.boundId && getElementById(board, element.target.boundId);
|
|
1841
|
+
const isBound = sourceElement && targetElement;
|
|
1842
|
+
let points = [];
|
|
1843
|
+
if (isBound) {
|
|
1844
|
+
const targetRectangle = RectangleClient.inflate(getRectangleByPoints(targetElement.points), getStrokeWidthByElement(targetElement) * 2);
|
|
1845
|
+
const sourceRectangle = RectangleClient.inflate(getRectangleByPoints(sourceElement.points), getStrokeWidthByElement(sourceElement) * 2);
|
|
1846
|
+
const sourcePoint = handleRefPair.source.point;
|
|
1847
|
+
const targetPoint = handleRefPair.target.point;
|
|
1848
|
+
const { sourceOffset, targetOffset } = reduceRouteMargin(sourceRectangle, targetRectangle);
|
|
1849
|
+
const sourceOuterRectangle = RectangleClient.expand(sourceRectangle, sourceOffset[3], sourceOffset[0], sourceOffset[1], sourceOffset[2]);
|
|
1850
|
+
const targetOuterRectangle = RectangleClient.expand(targetRectangle, targetOffset[3], targetOffset[0], targetOffset[1], targetOffset[2]);
|
|
1851
|
+
const nextSourcePoint = getNextPoint(sourcePoint, sourceOuterRectangle, handleRefPair.source.direction);
|
|
1852
|
+
const nextTargetPoint = getNextPoint(targetPoint, targetOuterRectangle, handleRefPair.target.direction);
|
|
1853
|
+
const isIntersect = RectangleClient.isPointInRectangle(targetRectangle, sourcePoint) ||
|
|
1854
|
+
RectangleClient.isPointInRectangle(targetOuterRectangle, nextSourcePoint) ||
|
|
1855
|
+
RectangleClient.isPointInRectangle(sourceOuterRectangle, nextTargetPoint) ||
|
|
1856
|
+
RectangleClient.isPointInRectangle(sourceRectangle, targetPoint);
|
|
1857
|
+
if (!isIntersect) {
|
|
1858
|
+
points = generateElbowLineRoute({
|
|
1859
|
+
sourcePoint,
|
|
1860
|
+
nextSourcePoint,
|
|
1861
|
+
sourceRectangle,
|
|
1862
|
+
sourceOuterRectangle,
|
|
1863
|
+
targetPoint,
|
|
1864
|
+
nextTargetPoint,
|
|
1865
|
+
targetRectangle,
|
|
1866
|
+
targetOuterRectangle
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
if (!points.length) {
|
|
1871
|
+
points = getPoints(handleRefPair.source.point, handleRefPair.source.direction, handleRefPair.target.point, handleRefPair.target.direction, offset);
|
|
1872
|
+
}
|
|
1265
1873
|
points = removeDuplicatePoints(points);
|
|
1266
1874
|
return points;
|
|
1267
1875
|
}
|
|
@@ -1434,17 +2042,6 @@ const getBoardLines = (board) => {
|
|
|
1434
2042
|
recursion: (element) => PlaitDrawElement.isDrawElement(element)
|
|
1435
2043
|
});
|
|
1436
2044
|
};
|
|
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
2045
|
const getExtendPoint = (source, target, extendDistance) => {
|
|
1449
2046
|
const distance = distanceBetweenPointAndPoint(...source, ...target);
|
|
1450
2047
|
const sin = (target[1] - source[1]) / distance;
|
|
@@ -1510,6 +2107,55 @@ const getSelectedImageElements = (board) => {
|
|
|
1510
2107
|
return selectedElements;
|
|
1511
2108
|
};
|
|
1512
2109
|
|
|
2110
|
+
const isRectangleHitDrawElement = (board, element, selection) => {
|
|
2111
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
2112
|
+
const client = getRectangleByPoints(element.points);
|
|
2113
|
+
const rangeRectangle = RectangleClient.toRectangleClient([selection.anchor, selection.focus]);
|
|
2114
|
+
if (element.textHeight > client.height) {
|
|
2115
|
+
const textClient = getTextRectangle(element);
|
|
2116
|
+
return RectangleClient.isHit(rangeRectangle, client) || RectangleClient.isHit(rangeRectangle, textClient);
|
|
2117
|
+
}
|
|
2118
|
+
return RectangleClient.isHit(rangeRectangle, client);
|
|
2119
|
+
}
|
|
2120
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
2121
|
+
const client = getRectangleByPoints(element.points);
|
|
2122
|
+
const rangeRectangle = RectangleClient.toRectangleClient([selection.anchor, selection.focus]);
|
|
2123
|
+
return RectangleClient.isHit(rangeRectangle, client);
|
|
2124
|
+
}
|
|
2125
|
+
if (PlaitDrawElement.isLine(element)) {
|
|
2126
|
+
const points = getLinePoints(board, element);
|
|
2127
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
2128
|
+
const isHitText = isHitLineText(board, element, selection.focus);
|
|
2129
|
+
const isHit = isHitPolyLine(points, selection.focus, strokeWidth, 3) || isHitText;
|
|
2130
|
+
const rangeRectangle = RectangleClient.toRectangleClient([selection.anchor, selection.focus]);
|
|
2131
|
+
const isContainPolyLinePoint = points.some(point => {
|
|
2132
|
+
return RectangleClient.isHit(rangeRectangle, RectangleClient.toRectangleClient([point, point]));
|
|
2133
|
+
});
|
|
2134
|
+
const isIntersect = Point.isEquals(selection.anchor, selection.focus) ? isHit : isPolylineHitRectangle(points, rangeRectangle);
|
|
2135
|
+
return isContainPolyLinePoint || isIntersect;
|
|
2136
|
+
}
|
|
2137
|
+
return null;
|
|
2138
|
+
};
|
|
2139
|
+
const isHitDrawElement = (board, element, point) => {
|
|
2140
|
+
if (PlaitDrawElement.isGeometry(element)) {
|
|
2141
|
+
const fill = getFillByElement(element);
|
|
2142
|
+
if (fill !== DefaultGeometryStyle.fill) {
|
|
2143
|
+
return isRectangleHitDrawElement(board, element, { anchor: point, focus: point });
|
|
2144
|
+
}
|
|
2145
|
+
else {
|
|
2146
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
2147
|
+
const engine = getEngine(getShape(element));
|
|
2148
|
+
const corners = engine.getCornerPoints(getRectangleByPoints(element.points));
|
|
2149
|
+
const isHit = isHitPolyLine(corners, point, strokeWidth, 3);
|
|
2150
|
+
return isHit;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
if (PlaitDrawElement.isImage(element) || PlaitDrawElement.isLine(element)) {
|
|
2154
|
+
return isRectangleHitDrawElement(board, element, { anchor: point, focus: point });
|
|
2155
|
+
}
|
|
2156
|
+
return null;
|
|
2157
|
+
};
|
|
2158
|
+
|
|
1513
2159
|
var LineMarkerType;
|
|
1514
2160
|
(function (LineMarkerType) {
|
|
1515
2161
|
LineMarkerType["arrow"] = "arrow";
|
|
@@ -1562,208 +2208,59 @@ const PlaitLine = {
|
|
|
1562
2208
|
return PlaitLine.isSourceMarkOrTargetMark(line, markType, LineHandleKey.target);
|
|
1563
2209
|
},
|
|
1564
2210
|
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
|
-
};
|
|
1613
|
-
|
|
1614
|
-
class GeometryShapeGenerator extends Generator {
|
|
1615
|
-
canDraw(element, data) {
|
|
1616
|
-
return true;
|
|
1617
|
-
}
|
|
1618
|
-
baseDraw(element, data) {
|
|
1619
|
-
const rectangle = getRectangleByPoints(element.points);
|
|
1620
|
-
const shape = element.shape;
|
|
1621
|
-
if (shape === GeometryShape.text) {
|
|
1622
|
-
return;
|
|
1623
|
-
}
|
|
1624
|
-
const strokeWidth = getStrokeWidthByElement(element);
|
|
1625
|
-
const strokeColor = getStrokeColorByElement(element);
|
|
1626
|
-
const fill = getFillByElement(element);
|
|
1627
|
-
const strokeLineDash = getLineDashByElement(element);
|
|
1628
|
-
return drawGeometry(this.board, RectangleClient.inflate(rectangle, -strokeWidth), shape, {
|
|
1629
|
-
stroke: strokeColor,
|
|
1630
|
-
strokeWidth,
|
|
1631
|
-
fill,
|
|
1632
|
-
strokeLineDash
|
|
1633
|
-
});
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
const insertGeometry = (board, points, shape) => {
|
|
1638
|
-
let newElement = createGeometryElement(shape, points, '', {
|
|
1639
|
-
strokeColor: DefaultGeometryProperty.strokeColor,
|
|
1640
|
-
strokeWidth: DefaultGeometryProperty.strokeWidth
|
|
1641
|
-
});
|
|
1642
|
-
Transforms.insertNode(board, newElement, [board.children.length]);
|
|
1643
|
-
clearSelectedElement(board);
|
|
1644
|
-
addSelectedElement(board, newElement);
|
|
1645
|
-
};
|
|
1646
|
-
const insertText = (board, points, text = '文本') => {
|
|
1647
|
-
let newElement = createGeometryElement(GeometryShape.text, points, text);
|
|
1648
|
-
Transforms.insertNode(board, newElement, [board.children.length]);
|
|
1649
|
-
clearSelectedElement(board);
|
|
1650
|
-
addSelectedElement(board, newElement);
|
|
1651
|
-
};
|
|
1652
|
-
const resizeGeometry = (board, points, textHeight, path) => {
|
|
1653
|
-
const normalizePoints = normalizeShapePoints(points);
|
|
1654
|
-
const element = PlaitNode.get(board, path);
|
|
1655
|
-
const newHeight = textHeight / board.viewport.zoom;
|
|
1656
|
-
const newProperties = { points: normalizePoints, textHeight: newHeight };
|
|
1657
|
-
if (PlaitDrawElement.isText(element) && element.autoSize) {
|
|
1658
|
-
newProperties.autoSize = false;
|
|
1659
|
-
}
|
|
1660
|
-
Transforms.setNode(board, newProperties, path);
|
|
1661
|
-
};
|
|
1662
|
-
|
|
1663
|
-
const normalizePoints = (board, element, width, textHeight) => {
|
|
1664
|
-
let points = element.points;
|
|
1665
|
-
let autoSize = element.autoSize;
|
|
1666
|
-
const defaultSpace = ShapeDefaultSpace.rectangleAndText;
|
|
1667
|
-
if (autoSize) {
|
|
1668
|
-
const editor = PlaitGeometry.getTextEditor(element);
|
|
1669
|
-
if (AlignEditor.isActive(editor, Alignment.right)) {
|
|
1670
|
-
points = [
|
|
1671
|
-
[points[1][0] - (width + defaultSpace * 2), points[0][1]],
|
|
1672
|
-
[points[1][0], points[0][1] + textHeight]
|
|
1673
|
-
];
|
|
1674
|
-
}
|
|
1675
|
-
else if (AlignEditor.isActive(editor, Alignment.center)) {
|
|
1676
|
-
const oldWidth = Math.abs(points[0][0] - points[1][0]);
|
|
1677
|
-
const offset = (width - oldWidth) / 2;
|
|
1678
|
-
points = [
|
|
1679
|
-
[points[0][0] - offset - defaultSpace, points[0][1]],
|
|
1680
|
-
[points[1][0] + offset + defaultSpace, points[0][1] + textHeight]
|
|
1681
|
-
];
|
|
1682
|
-
}
|
|
1683
|
-
else {
|
|
1684
|
-
points = [points[0], [points[0][0] + width + defaultSpace * 2, points[0][1] + textHeight]];
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
return { points };
|
|
1688
|
-
};
|
|
1689
|
-
const setText = (board, element, text, width, textHeight) => {
|
|
1690
|
-
const newElement = {
|
|
1691
|
-
text,
|
|
1692
|
-
textHeight,
|
|
1693
|
-
...normalizePoints(board, element, width, textHeight)
|
|
1694
|
-
};
|
|
1695
|
-
const path = board.children.findIndex(child => child === element);
|
|
1696
|
-
Transforms.setNode(board, newElement, [path]);
|
|
1697
|
-
};
|
|
1698
|
-
const setTextSize = (board, element, textWidth, textHeight) => {
|
|
1699
|
-
if (element.autoSize) {
|
|
1700
|
-
const newElement = {
|
|
1701
|
-
textHeight,
|
|
1702
|
-
...normalizePoints(board, element, textWidth, textHeight)
|
|
1703
|
-
};
|
|
1704
|
-
const isPointsEqual = Point.isEquals(element.points[0], newElement.points[0]) && Point.isEquals(element.points[1], newElement.points[1]);
|
|
1705
|
-
const isTextHeightEqual = Math.round(textHeight) === Math.round(element.textHeight);
|
|
1706
|
-
if (!isPointsEqual || !isTextHeightEqual) {
|
|
1707
|
-
const path = board.children.findIndex(child => child === element);
|
|
1708
|
-
Transforms.setNode(board, newElement, [path]);
|
|
1709
|
-
}
|
|
2211
|
+
return line.source.boundId === element.id;
|
|
2212
|
+
},
|
|
2213
|
+
isBoundElementOfTarget(line, element) {
|
|
2214
|
+
return line.target.boundId === element.id;
|
|
2215
|
+
},
|
|
2216
|
+
getPoints(board, line) {
|
|
2217
|
+
let sourcePoint = line.source.boundId
|
|
2218
|
+
? getConnectionPoint(getElementById(board, line.source.boundId), line.source.connection)
|
|
2219
|
+
: line.points[0];
|
|
2220
|
+
let targetPoint = line.target.boundId
|
|
2221
|
+
? getConnectionPoint(getElementById(board, line.target.boundId), line.target.connection)
|
|
2222
|
+
: line.points[line.points.length - 1];
|
|
2223
|
+
const restPoints = line.points.length > 2 ? line.points.slice(1, line.points.length - 1) : [];
|
|
2224
|
+
return [sourcePoint, ...restPoints, targetPoint];
|
|
1710
2225
|
}
|
|
1711
2226
|
};
|
|
1712
2227
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
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
|
-
|
|
1735
|
-
const resizeLine = (board, options, path) => {
|
|
1736
|
-
Transforms.setNode(board, options, path);
|
|
1737
|
-
};
|
|
1738
|
-
const setLineTexts = (board, element, texts) => {
|
|
1739
|
-
const path = PlaitBoard.findPath(board, element);
|
|
1740
|
-
Transforms.setNode(board, { texts }, path);
|
|
1741
|
-
};
|
|
1742
|
-
const removeLineText = (board, element, index) => {
|
|
1743
|
-
const path = PlaitBoard.findPath(board, element);
|
|
1744
|
-
const texts = element.texts?.length ? [...element.texts] : [];
|
|
1745
|
-
const newTexts = [...texts];
|
|
1746
|
-
newTexts.splice(index, 1);
|
|
1747
|
-
Transforms.setNode(board, { texts: newTexts }, path);
|
|
1748
|
-
};
|
|
1749
|
-
const setLineMark = (board, element, handleKey, marker) => {
|
|
1750
|
-
const path = PlaitBoard.findPath(board, element);
|
|
1751
|
-
let handle = handleKey === LineHandleKey.source ? element.source : element.target;
|
|
1752
|
-
handle = { ...handle, marker };
|
|
1753
|
-
Transforms.setNode(board, { [handleKey]: handle }, path);
|
|
1754
|
-
};
|
|
2228
|
+
var StrokeStyle;
|
|
2229
|
+
(function (StrokeStyle) {
|
|
2230
|
+
StrokeStyle["solid"] = "solid";
|
|
2231
|
+
StrokeStyle["dashed"] = "dashed";
|
|
2232
|
+
})(StrokeStyle || (StrokeStyle = {}));
|
|
1755
2233
|
|
|
1756
|
-
const
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
2234
|
+
const PlaitDrawElement = {
|
|
2235
|
+
isGeometry: (value) => {
|
|
2236
|
+
return value.type === 'geometry';
|
|
2237
|
+
},
|
|
2238
|
+
isLine: (value) => {
|
|
2239
|
+
return value.type === 'line';
|
|
2240
|
+
},
|
|
2241
|
+
isText: (value) => {
|
|
2242
|
+
return value.type === 'geometry' && value.shape === BasicShapes.text;
|
|
2243
|
+
},
|
|
2244
|
+
isImage: (value) => {
|
|
2245
|
+
return value.type === 'image';
|
|
2246
|
+
},
|
|
2247
|
+
isDrawElement: (value) => {
|
|
2248
|
+
if (PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isLine(value) || PlaitDrawElement.isImage(value)) {
|
|
2249
|
+
return true;
|
|
2250
|
+
}
|
|
2251
|
+
else {
|
|
2252
|
+
return false;
|
|
2253
|
+
}
|
|
2254
|
+
},
|
|
2255
|
+
isShape: (value) => {
|
|
2256
|
+
return PlaitDrawElement.isImage(value) || PlaitDrawElement.isGeometry(value);
|
|
2257
|
+
},
|
|
2258
|
+
isBaseShape: (value) => {
|
|
2259
|
+
return Object.keys(BasicShapes).includes(value.type);
|
|
2260
|
+
},
|
|
2261
|
+
isFlowchart: (value) => {
|
|
2262
|
+
return Object.keys(FlowchartSymbols).includes(value.type);
|
|
2263
|
+
}
|
|
1767
2264
|
};
|
|
1768
2265
|
|
|
1769
2266
|
class GeometryComponent extends CommonPluginElement {
|
|
@@ -1864,7 +2361,11 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
1864
2361
|
}
|
|
1865
2362
|
},
|
|
1866
2363
|
getMaxWidth: () => {
|
|
1867
|
-
|
|
2364
|
+
let width = getTextRectangle(this.element).width;
|
|
2365
|
+
const getRectangle = getEngine(this.element.shape).getTextRectangle;
|
|
2366
|
+
if (getRectangle) {
|
|
2367
|
+
width = getRectangle(this.element).width;
|
|
2368
|
+
}
|
|
1868
2369
|
return this.element?.autoSize ? GeometryThreshold.defaultTextMaxWidth : width;
|
|
1869
2370
|
},
|
|
1870
2371
|
textPlugins: plugins
|
|
@@ -1877,10 +2378,10 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
1877
2378
|
this.destroy$.next();
|
|
1878
2379
|
this.destroy$.complete();
|
|
1879
2380
|
}
|
|
1880
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.
|
|
1881
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.
|
|
2381
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GeometryComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2382
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: GeometryComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1882
2383
|
}
|
|
1883
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.
|
|
2384
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GeometryComponent, decorators: [{
|
|
1884
2385
|
type: Component,
|
|
1885
2386
|
args: [{
|
|
1886
2387
|
selector: 'plait-draw-geometry',
|
|
@@ -2118,10 +2619,10 @@ class LineComponent extends PlaitPluginElementComponent {
|
|
|
2118
2619
|
this.destroy$.next();
|
|
2119
2620
|
this.destroy$.complete();
|
|
2120
2621
|
}
|
|
2121
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.
|
|
2122
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.
|
|
2622
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LineComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2623
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LineComponent, isStandalone: true, selector: "plait-draw-line", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2123
2624
|
}
|
|
2124
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.
|
|
2625
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LineComponent, decorators: [{
|
|
2125
2626
|
type: Component,
|
|
2126
2627
|
args: [{
|
|
2127
2628
|
selector: 'plait-draw-line',
|
|
@@ -2160,160 +2661,6 @@ const withDrawHotkey = (board) => {
|
|
|
2160
2661
|
return board;
|
|
2161
2662
|
};
|
|
2162
2663
|
|
|
2163
|
-
const withGeometryCreateByDrag = (board) => {
|
|
2164
|
-
const { pointerMove, pointerUp } = board;
|
|
2165
|
-
let geometryShapeG = null;
|
|
2166
|
-
board.pointerMove = (event) => {
|
|
2167
|
-
geometryShapeG?.remove();
|
|
2168
|
-
geometryShapeG = createG();
|
|
2169
|
-
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
2170
|
-
const geometryPointers = getGeometryPointers();
|
|
2171
|
-
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
2172
|
-
const dragMode = isGeometryPointer && isDndMode(board);
|
|
2173
|
-
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2174
|
-
const pointer = PlaitBoard.getPointer(board);
|
|
2175
|
-
if (dragMode) {
|
|
2176
|
-
const points = getDefaultGeometryPoints(pointer, movingPoint);
|
|
2177
|
-
if (pointer === GeometryShape.text) {
|
|
2178
|
-
const textG = getTemporaryTextG(movingPoint);
|
|
2179
|
-
geometryShapeG.appendChild(textG);
|
|
2180
|
-
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
2181
|
-
}
|
|
2182
|
-
else {
|
|
2183
|
-
const temporaryElement = createGeometryElement(pointer, points, '', {
|
|
2184
|
-
strokeColor: DefaultGeometryProperty.strokeColor,
|
|
2185
|
-
strokeWidth: DefaultGeometryProperty.strokeWidth
|
|
2186
|
-
});
|
|
2187
|
-
geometryGenerator.draw(temporaryElement, geometryShapeG);
|
|
2188
|
-
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
2189
|
-
}
|
|
2190
|
-
}
|
|
2191
|
-
pointerMove(event);
|
|
2192
|
-
};
|
|
2193
|
-
board.pointerUp = (event) => {
|
|
2194
|
-
const pointer = PlaitBoard.getPointer(board);
|
|
2195
|
-
const geometryPointers = getGeometryPointers();
|
|
2196
|
-
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
2197
|
-
const dragMode = isGeometryPointer && isDndMode(board);
|
|
2198
|
-
if (dragMode) {
|
|
2199
|
-
const targetPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2200
|
-
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
2201
|
-
if (pointer === GeometryShape.text) {
|
|
2202
|
-
DrawTransforms.insertText(board, points);
|
|
2203
|
-
}
|
|
2204
|
-
else {
|
|
2205
|
-
DrawTransforms.insertGeometry(board, points, pointer);
|
|
2206
|
-
}
|
|
2207
|
-
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
2208
|
-
}
|
|
2209
|
-
geometryShapeG?.remove();
|
|
2210
|
-
geometryShapeG = null;
|
|
2211
|
-
preventTouchMove(board, event, false);
|
|
2212
|
-
pointerUp(event);
|
|
2213
|
-
};
|
|
2214
|
-
return board;
|
|
2215
|
-
};
|
|
2216
|
-
const withGeometryCreateByDrawing = (board) => {
|
|
2217
|
-
const { pointerDown, pointerMove, pointerUp, keydown, keyup } = board;
|
|
2218
|
-
let start = null;
|
|
2219
|
-
let geometryShapeG = null;
|
|
2220
|
-
let temporaryElement = null;
|
|
2221
|
-
let isShift = false;
|
|
2222
|
-
board.keydown = (event) => {
|
|
2223
|
-
isShift = isKeyHotkey('shift', event);
|
|
2224
|
-
keydown(event);
|
|
2225
|
-
};
|
|
2226
|
-
board.keyup = (event) => {
|
|
2227
|
-
isShift = false;
|
|
2228
|
-
keyup(event);
|
|
2229
|
-
};
|
|
2230
|
-
board.pointerDown = (event) => {
|
|
2231
|
-
const geometryPointers = getGeometryPointers();
|
|
2232
|
-
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
2233
|
-
if (isGeometryPointer && isDrawingMode(board)) {
|
|
2234
|
-
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2235
|
-
start = point;
|
|
2236
|
-
const pointer = PlaitBoard.getPointer(board);
|
|
2237
|
-
preventTouchMove(board, event, true);
|
|
2238
|
-
if (pointer === GeometryShape.text) {
|
|
2239
|
-
const points = getDefaultGeometryPoints(pointer, point);
|
|
2240
|
-
const textElement = createGeometryElement(GeometryShape.text, points, DefaultTextProperty.text);
|
|
2241
|
-
Transforms.insertNode(board, textElement, [board.children.length]);
|
|
2242
|
-
clearSelectedElement(board);
|
|
2243
|
-
addSelectedElement(board, textElement);
|
|
2244
|
-
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
2245
|
-
start = null;
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
pointerDown(event);
|
|
2249
|
-
};
|
|
2250
|
-
board.pointerMove = (event) => {
|
|
2251
|
-
geometryShapeG?.remove();
|
|
2252
|
-
geometryShapeG = createG();
|
|
2253
|
-
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
2254
|
-
const drawMode = !!start;
|
|
2255
|
-
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2256
|
-
const pointer = PlaitBoard.getPointer(board);
|
|
2257
|
-
if (drawMode && pointer !== GeometryShape.text) {
|
|
2258
|
-
const points = normalizeShapePoints([start, movingPoint], isShift);
|
|
2259
|
-
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
2260
|
-
strokeColor: DefaultGeometryProperty.strokeColor,
|
|
2261
|
-
strokeWidth: DefaultGeometryProperty.strokeWidth
|
|
2262
|
-
});
|
|
2263
|
-
geometryGenerator.draw(temporaryElement, geometryShapeG);
|
|
2264
|
-
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
2265
|
-
}
|
|
2266
|
-
pointerMove(event);
|
|
2267
|
-
};
|
|
2268
|
-
board.pointerUp = (event) => {
|
|
2269
|
-
const isDrawMode = !!start;
|
|
2270
|
-
if (isDrawMode) {
|
|
2271
|
-
const targetPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2272
|
-
const { width, height } = RectangleClient.toRectangleClient([start, targetPoint]);
|
|
2273
|
-
if (Math.hypot(width, height) === 0) {
|
|
2274
|
-
const pointer = PlaitBoard.getPointer(board);
|
|
2275
|
-
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
2276
|
-
if (pointer !== GeometryShape.text) {
|
|
2277
|
-
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
2278
|
-
strokeColor: DefaultGeometryProperty.strokeColor,
|
|
2279
|
-
strokeWidth: DefaultGeometryProperty.strokeWidth
|
|
2280
|
-
});
|
|
2281
|
-
}
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
if (temporaryElement) {
|
|
2285
|
-
Transforms.insertNode(board, temporaryElement, [board.children.length]);
|
|
2286
|
-
clearSelectedElement(board);
|
|
2287
|
-
addSelectedElement(board, temporaryElement);
|
|
2288
|
-
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
2289
|
-
}
|
|
2290
|
-
geometryShapeG?.remove();
|
|
2291
|
-
geometryShapeG = null;
|
|
2292
|
-
start = null;
|
|
2293
|
-
temporaryElement = null;
|
|
2294
|
-
preventTouchMove(board, event, false);
|
|
2295
|
-
pointerUp(event);
|
|
2296
|
-
};
|
|
2297
|
-
return board;
|
|
2298
|
-
};
|
|
2299
|
-
const getDefaultGeometryPoints = (pointer, targetPoint) => {
|
|
2300
|
-
return pointer === GeometryShape.text
|
|
2301
|
-
? getPointsByCenterPoint(targetPoint, DefaultTextProperty.width, DefaultTextProperty.height)
|
|
2302
|
-
: getPointsByCenterPoint(targetPoint, DefaultGeometryProperty.width, DefaultGeometryProperty.height);
|
|
2303
|
-
};
|
|
2304
|
-
const getTemporaryTextG = (movingPoint) => {
|
|
2305
|
-
const textG = createG();
|
|
2306
|
-
const width = DefaultTextProperty.width - ShapeDefaultSpace.rectangleAndText * 2;
|
|
2307
|
-
const foreignObject = createForeignObject(movingPoint[0] - width / 2, movingPoint[1] - DefaultTextProperty.height / 2, width, DefaultTextProperty.height);
|
|
2308
|
-
const richtext = document.createElement('div');
|
|
2309
|
-
richtext.textContent = DefaultTextProperty.text;
|
|
2310
|
-
richtext.style.fontSize = `${DEFAULT_FONT_SIZE}px`;
|
|
2311
|
-
richtext.style.cursor = 'default';
|
|
2312
|
-
foreignObject.appendChild(richtext);
|
|
2313
|
-
textG.appendChild(foreignObject);
|
|
2314
|
-
return textG;
|
|
2315
|
-
};
|
|
2316
|
-
|
|
2317
2664
|
const buildClipboardData = (board, elements, startPoint) => {
|
|
2318
2665
|
return elements.map(element => {
|
|
2319
2666
|
if (PlaitDrawElement.isGeometry(element) || PlaitDrawElement.isImage(element)) {
|
|
@@ -2404,13 +2751,13 @@ const withDrawFragment = (baseBoard) => {
|
|
|
2404
2751
|
};
|
|
2405
2752
|
board.insertFragment = (data, targetPoint) => {
|
|
2406
2753
|
const elements = getDataFromClipboard(data);
|
|
2754
|
+
const selectedElements = getSelectedElements(board);
|
|
2407
2755
|
const drawElements = elements.filter(value => PlaitDrawElement.isDrawElement(value));
|
|
2408
2756
|
if (elements.length > 0 && drawElements.length > 0) {
|
|
2409
2757
|
insertClipboardData(board, drawElements, targetPoint);
|
|
2410
2758
|
}
|
|
2411
2759
|
else if (elements.length === 0) {
|
|
2412
2760
|
const text = getTextFromClipboard(data);
|
|
2413
|
-
const selectedElements = getSelectedElements(board);
|
|
2414
2761
|
// (* ̄︶ ̄)
|
|
2415
2762
|
const insertAsChildren = selectedElements.length === 1 && selectedElements[0].children;
|
|
2416
2763
|
const insertAsFreeText = !insertAsChildren;
|
|
@@ -2422,7 +2769,8 @@ const withDrawFragment = (baseBoard) => {
|
|
|
2422
2769
|
}
|
|
2423
2770
|
if (data?.files.length) {
|
|
2424
2771
|
const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
|
|
2425
|
-
|
|
2772
|
+
const canInsertionImage = !getElementOfFocusedImage(board) && !(selectedElements.length === 1 && board.isImageBindingAllowed(selectedElements[0]));
|
|
2773
|
+
if (acceptImageArray.includes(data?.files[0].type) && canInsertionImage) {
|
|
2426
2774
|
const imageFile = data.files[0];
|
|
2427
2775
|
buildImage(board, imageFile, DEFAULT_IMAGE_WIDTH, imageItem => {
|
|
2428
2776
|
DrawTransforms.insertImage(board, imageItem, targetPoint);
|
|
@@ -2439,11 +2787,6 @@ const getBoundedLineElements = (board, plaitShapes) => {
|
|
|
2439
2787
|
return lines.filter(line => plaitShapes.find(shape => PlaitLine.isBoundElementOfSource(line, shape) || PlaitLine.isBoundElementOfTarget(line, shape)));
|
|
2440
2788
|
};
|
|
2441
2789
|
|
|
2442
|
-
const DefaultLineStyle = {
|
|
2443
|
-
strokeWidth: 2,
|
|
2444
|
-
strokeColor: '#000'
|
|
2445
|
-
};
|
|
2446
|
-
|
|
2447
2790
|
const getHitGeometryResizeHandleRef = (board, element, point) => {
|
|
2448
2791
|
const rectangle = getRectangleByPoints(element.points);
|
|
2449
2792
|
const resizeHandleRefs = getRectangleResizeHandleRefs(rectangle, RESIZE_HANDLE_DIAMETER);
|
|
@@ -2500,7 +2843,7 @@ const withLineCreateByDraw = (board) => {
|
|
|
2500
2843
|
targetRef.boundId = hitElement ? hitElement.id : undefined;
|
|
2501
2844
|
const lineGenerator = new LineShapeGenerator(board);
|
|
2502
2845
|
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 }, {
|
|
2846
|
+
temporaryElement = createLineElement(lineShape, [start, movingPoint], { marker: LineMarkerType.none, connection: sourceRef.connection, boundId: sourceRef?.boundId }, { marker: LineMarkerType.arrow, connection: targetRef.connection, boundId: targetRef?.boundId }, [], {
|
|
2504
2847
|
strokeColor: DefaultLineStyle.strokeColor,
|
|
2505
2848
|
strokeWidth: DefaultLineStyle.strokeWidth
|
|
2506
2849
|
});
|
|
@@ -2739,9 +3082,9 @@ const withLineText = (board) => {
|
|
|
2739
3082
|
const { dblclick } = board;
|
|
2740
3083
|
board.dblclick = (event) => {
|
|
2741
3084
|
const clickPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2742
|
-
const hitTarget =
|
|
3085
|
+
const hitTarget = getHitElementByPoint(board, clickPoint, (element) => {
|
|
2743
3086
|
return PlaitDrawElement.isLine(element);
|
|
2744
|
-
})
|
|
3087
|
+
});
|
|
2745
3088
|
if (hitTarget) {
|
|
2746
3089
|
const points = getLinePoints(board, hitTarget);
|
|
2747
3090
|
const point = getNearestPointBetweenPointAndSegments(clickPoint, points);
|
|
@@ -2836,10 +3179,10 @@ class ImageComponent extends CommonPluginElement {
|
|
|
2836
3179
|
this.destroy$.complete();
|
|
2837
3180
|
this.imageGenerator.destroy();
|
|
2838
3181
|
}
|
|
2839
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.
|
|
2840
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.
|
|
3182
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ImageComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3183
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ImageComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2841
3184
|
}
|
|
2842
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.
|
|
3185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ImageComponent, decorators: [{
|
|
2843
3186
|
type: Component,
|
|
2844
3187
|
args: [{
|
|
2845
3188
|
selector: 'plait-draw-geometry',
|
|
@@ -2850,7 +3193,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImpor
|
|
|
2850
3193
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
2851
3194
|
|
|
2852
3195
|
const withDraw = (board) => {
|
|
2853
|
-
const { drawElement, getRectangle,
|
|
3196
|
+
const { drawElement, getRectangle, isRectangleHit, isHit, isMovable, isAlign } = board;
|
|
2854
3197
|
board.drawElement = (context) => {
|
|
2855
3198
|
if (PlaitDrawElement.isGeometry(context.element)) {
|
|
2856
3199
|
return GeometryComponent;
|
|
@@ -2876,34 +3219,19 @@ const withDraw = (board) => {
|
|
|
2876
3219
|
}
|
|
2877
3220
|
return getRectangle(element);
|
|
2878
3221
|
};
|
|
2879
|
-
board.
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
if (element.textHeight > client.height) {
|
|
2884
|
-
const textClient = getTextRectangle(element);
|
|
2885
|
-
return RectangleClient.isHit(rangeRectangle, client) || RectangleClient.isHit(rangeRectangle, textClient);
|
|
2886
|
-
}
|
|
2887
|
-
return RectangleClient.isHit(rangeRectangle, client);
|
|
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);
|
|
3222
|
+
board.isRectangleHit = (element, selection) => {
|
|
3223
|
+
const result = isRectangleHitDrawElement(board, element, selection);
|
|
3224
|
+
if (result !== null) {
|
|
3225
|
+
return result;
|
|
2893
3226
|
}
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
const isContainPolyLinePoint = points.some(point => {
|
|
2901
|
-
return RectangleClient.isHit(rangeRectangle, RectangleClient.toRectangleClient([point, point]));
|
|
2902
|
-
});
|
|
2903
|
-
const isIntersect = range.anchor === range.focus ? isHit : isPolylineHitRectangle(points, rangeRectangle);
|
|
2904
|
-
return isContainPolyLinePoint || isIntersect;
|
|
3227
|
+
return isRectangleHit(element, selection);
|
|
3228
|
+
};
|
|
3229
|
+
board.isHit = (element, point) => {
|
|
3230
|
+
const result = isHitDrawElement(board, element, point);
|
|
3231
|
+
if (result !== null) {
|
|
3232
|
+
return result;
|
|
2905
3233
|
}
|
|
2906
|
-
return
|
|
3234
|
+
return isHit(element, point);
|
|
2907
3235
|
};
|
|
2908
3236
|
board.isMovable = (element) => {
|
|
2909
3237
|
if (PlaitDrawElement.isGeometry(element)) {
|
|
@@ -2938,5 +3266,5 @@ const withDraw = (board) => {
|
|
|
2938
3266
|
* Generated bundle index. Do not edit.
|
|
2939
3267
|
*/
|
|
2940
3268
|
|
|
2941
|
-
export { DEFAULT_IMAGE_WIDTH,
|
|
3269
|
+
export { BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultBasicShapeProperty, DefaultConnectorProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultGeometryActiveStyle, DefaultGeometryStyle, DefaultManualInputProperty, DefaultMergeProperty, DefaultTextProperty, DrawTransforms, FlowchartSymbols, GeometryComponent, GeometryThreshold, LineComponent, LineHandleKey, LineMarkerType, LineShape, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, StrokeStyle, createDefaultFlowchart, createGeometryElement, createLineElement, drawBoundMask, drawGeometry, drawLine, getBasicPointers, getBoardLines, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultFlowchartProperty, getEdgeOnPolygonByPoint, getElbowPoints, getExtendPoint, getFillByElement, getFlowchartPointers, getGeometryPointers, getHitConnectorPoint, getHitLineTextIndex, getLineDashByElement, getLineHandleRefPair, getLinePointers, getLinePoints, getLineTextRectangle, getNearestPoint, getPointsByCenterPoint, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedLineElements, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTextRectangle, getVectorByConnection, isHitDrawElement, isHitLineText, isHitPolyLine, isRectangleHitDrawElement, transformOpsToPoints, transformPointToConnection, withDraw };
|
|
2942
3270
|
//# sourceMappingURL=plait-draw.mjs.map
|