@plait/draw 0.1.0-next.9 → 0.29.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/image.d.ts +1 -0
- package/constants/index.d.ts +1 -0
- package/constants/pointer.d.ts +6 -10
- package/engines/basic-shapes/comment.d.ts +4 -0
- package/engines/basic-shapes/cross.d.ts +4 -0
- package/engines/basic-shapes/ellipse.d.ts +13 -0
- package/engines/basic-shapes/hexagon.d.ts +4 -0
- package/engines/basic-shapes/left-arrow.d.ts +4 -0
- package/engines/basic-shapes/octagon.d.ts +4 -0
- package/engines/basic-shapes/pentagon-arrow.d.ts +4 -0
- package/engines/basic-shapes/pentagon.d.ts +4 -0
- package/engines/basic-shapes/polygon.d.ts +8 -0
- package/engines/basic-shapes/process-arrow.d.ts +4 -0
- package/engines/basic-shapes/right-arrow.d.ts +4 -0
- package/engines/basic-shapes/round-comment.d.ts +4 -0
- package/engines/basic-shapes/star.d.ts +4 -0
- package/engines/basic-shapes/trapezoid.d.ts +4 -0
- package/engines/basic-shapes/triangle.d.ts +4 -0
- package/engines/basic-shapes/two-way-arrow.d.ts +4 -0
- 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 -0
- package/esm2022/constants/geometry.mjs +42 -4
- package/esm2022/constants/image.mjs +2 -0
- package/esm2022/constants/index.mjs +2 -1
- package/esm2022/constants/pointer.mjs +14 -19
- 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 +64 -0
- package/esm2022/generators/geometry-shape.generator.mjs +9 -4
- package/esm2022/generators/line-active.generator.mjs +71 -22
- package/esm2022/generators/line.generator.mjs +2 -11
- package/esm2022/geometry.component.mjs +20 -10
- package/esm2022/image.component.mjs +70 -0
- package/esm2022/interfaces/geometry.mjs +38 -10
- package/esm2022/interfaces/image.mjs +2 -0
- package/esm2022/interfaces/index.mjs +16 -4
- package/esm2022/interfaces/line.mjs +27 -4
- package/esm2022/interfaces/text.mjs +1 -1
- package/esm2022/line.component.mjs +17 -8
- package/esm2022/plugins/with-draw-fragment.mjs +37 -7
- package/esm2022/plugins/with-draw.mjs +38 -10
- package/esm2022/plugins/with-geometry-create.mjs +38 -23
- package/esm2022/plugins/with-geometry-resize.mjs +28 -20
- package/esm2022/plugins/with-line-bound-reaction.mjs +10 -5
- package/esm2022/plugins/with-line-create.mjs +7 -5
- package/esm2022/plugins/with-line-resize.mjs +12 -4
- package/esm2022/transforms/geometry-text.mjs +1 -1
- package/esm2022/transforms/geometry.mjs +6 -6
- package/esm2022/transforms/image.mjs +23 -0
- package/esm2022/transforms/index.mjs +4 -2
- package/esm2022/utils/clipboard.mjs +4 -3
- package/esm2022/utils/geometry.mjs +32 -10
- package/esm2022/utils/index.mjs +1 -1
- package/esm2022/utils/line-arrow.mjs +43 -18
- package/esm2022/utils/line.mjs +202 -51
- package/esm2022/utils/position/geometry.mjs +5 -4
- package/esm2022/utils/position/line.mjs +32 -22
- package/esm2022/utils/selected.mjs +5 -1
- package/esm2022/utils/shape.mjs +8 -0
- package/fesm2022/plait-draw.mjs +1704 -331
- package/fesm2022/plait-draw.mjs.map +1 -1
- package/generators/line-active.generator.d.ts +3 -0
- package/generators/line.generator.d.ts +1 -1
- package/geometry.component.d.ts +1 -1
- package/image.component.d.ts +20 -0
- package/interfaces/geometry.d.ts +39 -7
- package/interfaces/image.d.ts +7 -0
- package/interfaces/index.d.ts +7 -1
- package/interfaces/line.d.ts +19 -5
- package/interfaces/text.d.ts +2 -2
- package/line.component.d.ts +2 -1
- package/package.json +3 -2
- package/plugins/with-draw-fragment.d.ts +2 -0
- package/plugins/with-geometry-create.d.ts +6 -1
- package/styles/styles.scss +2 -2
- package/transforms/geometry.d.ts +2 -2
- package/transforms/image.d.ts +3 -0
- package/transforms/index.d.ts +2 -1
- package/utils/geometry.d.ts +23 -3
- package/utils/line.d.ts +14 -6
- package/utils/position/geometry.d.ts +2 -1
- package/utils/position/line.d.ts +7 -3
- package/utils/selected.d.ts +2 -0
- package/utils/shape.d.ts +2 -0
- package/esm2022/utils/engine/diamond.mjs +0 -22
- package/esm2022/utils/engine/ellipse.mjs +0 -55
- package/esm2022/utils/engine/index.mjs +0 -18
- package/esm2022/utils/engine/parallelogram.mjs +0 -32
- package/esm2022/utils/engine/rectangle.mjs +0 -18
- package/esm2022/utils/engine/round-rectangle.mjs +0 -49
- package/utils/engine/ellipse.d.ts +0 -4
- package/utils/engine/index.d.ts +0 -3
- package/{utils/engine → engines/basic-shapes}/diamond.d.ts +0 -0
- package/{utils/engine → engines/basic-shapes}/parallelogram.d.ts +1 -1
- /package/{utils/engine → engines/basic-shapes}/rectangle.d.ts +0 -0
- /package/{utils/engine → engines/basic-shapes}/round-rectangle.d.ts +0 -0
package/fesm2022/plait-draw.mjs
CHANGED
|
@@ -1,21 +1,50 @@
|
|
|
1
|
-
import { PlaitElement, ACTIVE_STROKE_WIDTH,
|
|
1
|
+
import { PlaitElement, ACTIVE_STROKE_WIDTH, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, idCreator, createG, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, distanceBetweenPointAndSegment, arrowPoints, createPath, drawLinearPath, rotate, getElementById, distanceBetweenPointAndPoint, distanceBetweenPointAndSegments, createMask, createRect, findElements, getSelectedElements, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Point, BOARD_TO_HOST, transformPoint, toPoint, isSelectionMoving, PlaitPluginElementComponent, BoardTransforms, PlaitPointerType, preventTouchMove, createForeignObject, setClipboardData, getDataFromClipboard, depthFirstRecursion, getIsRecursionFunc, getHitElements, isPolylineHitRectangle } from '@plait/core';
|
|
2
|
+
import { getRectangleByPoints, getFactorByPoints, getDirectionByVector, getOppositeDirection, getDirectionFactor, getPoints, getPointByVector, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90, Generator, normalizeShapePoints, CommonPluginElement, ActiveGenerator, WithTextPluginKey, RESIZE_HANDLE_DIAMETER, PRIMARY_COLOR, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, acceptImageTypes, buildImage, getRectangleResizeHandleRefs, ResizeHandle, withResize, isResizingByCondition, getRatioByPoint, ImageGenerator } from '@plait/common';
|
|
3
|
+
import { Alignment, buildText, AlignEditor, TextManage, DEFAULT_FONT_SIZE, getTextFromClipboard, getTextSize } from '@plait/text';
|
|
4
|
+
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
2
5
|
import * as i0 from '@angular/core';
|
|
3
6
|
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|
4
7
|
import { Subject } from 'rxjs';
|
|
5
|
-
import { getRectangleByPoints, getFactorByPoints, Direction, getDirectionByPoint, getPoints, getPointOnPolyline, getDirectionFactor, Generator, normalizeShapePoints, CommonPluginElement, ActiveGenerator, WithTextPluginKey, RESIZE_HANDLE_DIAMETER, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, getRectangleResizeHandleRefs, ResizeHandle, withResize, isResizingByCondition, getRatioByPoint } from '@plait/common';
|
|
6
|
-
import { Alignment, buildText, AlignEditor, TextManage, DEFAULT_FONT_SIZE, getTextFromClipboard, getTextSize } from '@plait/text';
|
|
7
8
|
import { isKeyHotkey } from 'is-hotkey';
|
|
8
9
|
import { Node } from 'slate';
|
|
9
10
|
|
|
10
|
-
var
|
|
11
|
-
(function (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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 = {}));
|
|
19
48
|
const PlaitGeometry = {
|
|
20
49
|
getTextEditor(element) {
|
|
21
50
|
return PlaitGeometry.getTextManage(element).componentRef.instance.editor;
|
|
@@ -29,79 +58,6 @@ const PlaitGeometry = {
|
|
|
29
58
|
}
|
|
30
59
|
};
|
|
31
60
|
|
|
32
|
-
var LineMarkerType;
|
|
33
|
-
(function (LineMarkerType) {
|
|
34
|
-
LineMarkerType["arrow"] = "arrow";
|
|
35
|
-
LineMarkerType["none"] = "none";
|
|
36
|
-
LineMarkerType["openTriangle"] = "open-triangle";
|
|
37
|
-
LineMarkerType["solidTriangle"] = "solid-triangle";
|
|
38
|
-
LineMarkerType["sharpArrow"] = "sharp-arrow";
|
|
39
|
-
})(LineMarkerType || (LineMarkerType = {}));
|
|
40
|
-
var LineShape;
|
|
41
|
-
(function (LineShape) {
|
|
42
|
-
LineShape["straight"] = "straight";
|
|
43
|
-
LineShape["curve"] = "curve";
|
|
44
|
-
LineShape["elbow"] = "elbow";
|
|
45
|
-
})(LineShape || (LineShape = {}));
|
|
46
|
-
var LineHandleKey;
|
|
47
|
-
(function (LineHandleKey) {
|
|
48
|
-
LineHandleKey["source"] = "source";
|
|
49
|
-
LineHandleKey["target"] = "target";
|
|
50
|
-
})(LineHandleKey || (LineHandleKey = {}));
|
|
51
|
-
const PlaitLine = {
|
|
52
|
-
getTextEditors(element) {
|
|
53
|
-
const component = PlaitElement.getComponent(element);
|
|
54
|
-
if (component) {
|
|
55
|
-
const manage = component.textManages.find(manage => manage.isEditing);
|
|
56
|
-
if (manage) {
|
|
57
|
-
return [manage.componentRef.instance.editor];
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
return component.textManages.map(manage => manage.componentRef.instance.editor);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
throw new Error('can not get correctly component in get text editor');
|
|
64
|
-
},
|
|
65
|
-
isSourceMark(line, markType) {
|
|
66
|
-
return line.source.marker === markType;
|
|
67
|
-
},
|
|
68
|
-
isTargetMark(line, markType) {
|
|
69
|
-
return line.target.marker === markType;
|
|
70
|
-
},
|
|
71
|
-
isBoundElementOfSource(line, element) {
|
|
72
|
-
return line.source.boundId === element.id;
|
|
73
|
-
},
|
|
74
|
-
isBoundElementOfTarget(line, element) {
|
|
75
|
-
return line.target.boundId === element.id;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
var StrokeStyle;
|
|
80
|
-
(function (StrokeStyle) {
|
|
81
|
-
StrokeStyle["solid"] = "solid";
|
|
82
|
-
StrokeStyle["dashed"] = "dashed";
|
|
83
|
-
})(StrokeStyle || (StrokeStyle = {}));
|
|
84
|
-
|
|
85
|
-
const PlaitDrawElement = {
|
|
86
|
-
isGeometry: (value) => {
|
|
87
|
-
return value.type === 'geometry';
|
|
88
|
-
},
|
|
89
|
-
isLine: (value) => {
|
|
90
|
-
return value.type === 'line';
|
|
91
|
-
},
|
|
92
|
-
isText: (value) => {
|
|
93
|
-
return value.type === 'geometry' && value.shape === GeometryShape.text;
|
|
94
|
-
},
|
|
95
|
-
isDrawElement: (value) => {
|
|
96
|
-
if (PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isLine(value)) {
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
61
|
const ShapeDefaultSpace = {
|
|
106
62
|
rectangleAndText: 4
|
|
107
63
|
};
|
|
@@ -115,7 +71,7 @@ const DefaultGeometryActiveStyle = {
|
|
|
115
71
|
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
116
72
|
selectionStrokeWidth: ACTIVE_STROKE_WIDTH
|
|
117
73
|
};
|
|
118
|
-
const
|
|
74
|
+
const DefaultBasicShapeProperty = {
|
|
119
75
|
width: 100,
|
|
120
76
|
height: 100,
|
|
121
77
|
strokeColor: '#333',
|
|
@@ -127,27 +83,60 @@ const DefaultTextProperty = {
|
|
|
127
83
|
text: '文本'
|
|
128
84
|
};
|
|
129
85
|
const GeometryThreshold = {
|
|
130
|
-
defaultTextMaxWidth: 34 * 14
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
86
|
+
defaultTextMaxWidth: 34 * 14
|
|
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
|
+
};
|
|
125
|
+
|
|
126
|
+
const getGeometryPointers = () => {
|
|
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);
|
|
134
|
+
};
|
|
135
|
+
const getLinePointers = () => {
|
|
136
|
+
return Object.keys(LineShape);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const DEFAULT_IMAGE_WIDTH = 1000;
|
|
151
140
|
|
|
152
141
|
const getStrokeWidthByElement = (element) => {
|
|
153
142
|
if (PlaitDrawElement.isText(element)) {
|
|
@@ -171,26 +160,138 @@ const getStrokeStyleByElement = (element) => {
|
|
|
171
160
|
return element.strokeStyle || StrokeStyle.solid;
|
|
172
161
|
};
|
|
173
162
|
|
|
174
|
-
const
|
|
163
|
+
const heightRatio$1 = 3 / 4;
|
|
164
|
+
const CommentEngine = {
|
|
175
165
|
draw(board, rectangle, options) {
|
|
176
|
-
const points =
|
|
166
|
+
const points = getCommentPoints(rectangle);
|
|
177
167
|
const rs = PlaitBoard.getRoughSVG(board);
|
|
178
168
|
const polygon = rs.polygon(points, { ...options, fillStyle: 'solid' });
|
|
179
169
|
setStrokeLinecap(polygon, 'round');
|
|
180
170
|
return polygon;
|
|
181
171
|
},
|
|
182
172
|
isHit(rectangle, point) {
|
|
183
|
-
const
|
|
184
|
-
return isPointInPolygon(point,
|
|
173
|
+
const parallelogramPoints = getCommentPoints(rectangle);
|
|
174
|
+
return isPointInPolygon(point, parallelogramPoints);
|
|
175
|
+
},
|
|
176
|
+
getCornerPoints(rectangle) {
|
|
177
|
+
return getCommentPoints(rectangle);
|
|
185
178
|
},
|
|
186
179
|
getNearestPoint(rectangle, point) {
|
|
187
|
-
|
|
188
|
-
|
|
180
|
+
return getNearestPointBetweenPointAndSegments(point, getCommentPoints(rectangle));
|
|
181
|
+
},
|
|
182
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
183
|
+
const corners = getCommentPoints(rectangle);
|
|
184
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
185
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
189
186
|
},
|
|
190
187
|
getConnectorPoints(rectangle) {
|
|
191
188
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
189
|
+
},
|
|
190
|
+
getTextRectangle(element) {
|
|
191
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
192
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
193
|
+
const height = element.textHeight;
|
|
194
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
195
|
+
return {
|
|
196
|
+
height,
|
|
197
|
+
width: width > 0 ? width : 0,
|
|
198
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
199
|
+
y: elementRectangle.y + (elementRectangle.height * heightRatio$1 - height) / 2
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const getCommentPoints = (rectangle) => {
|
|
204
|
+
return [
|
|
205
|
+
[rectangle.x, rectangle.y],
|
|
206
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
207
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * heightRatio$1],
|
|
208
|
+
[rectangle.x + (rectangle.width * 3) / 5, rectangle.y + rectangle.height * heightRatio$1],
|
|
209
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height],
|
|
210
|
+
[rectangle.x + (rectangle.width * 2) / 5, rectangle.y + rectangle.height * heightRatio$1],
|
|
211
|
+
[rectangle.x, rectangle.y + rectangle.height * heightRatio$1]
|
|
212
|
+
];
|
|
213
|
+
};
|
|
214
|
+
|
|
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;
|
|
192
249
|
}
|
|
250
|
+
return engine;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const getCrossPoints = (rectangle) => {
|
|
254
|
+
return [
|
|
255
|
+
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
256
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y],
|
|
257
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height / 4],
|
|
258
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 4],
|
|
259
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 3) / 4],
|
|
260
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + (rectangle.height * 3) / 4],
|
|
261
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height],
|
|
262
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
263
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + (rectangle.height * 3) / 4],
|
|
264
|
+
[rectangle.x, rectangle.y + (rectangle.height * 3) / 4],
|
|
265
|
+
[rectangle.x, rectangle.y + rectangle.height / 4],
|
|
266
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height / 4]
|
|
267
|
+
];
|
|
193
268
|
};
|
|
269
|
+
const CrossEngine = createPolygonEngine({
|
|
270
|
+
getPolygonPoints: getCrossPoints,
|
|
271
|
+
getConnectorPoints(rectangle) {
|
|
272
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
273
|
+
},
|
|
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,
|
|
285
|
+
getConnectorPoints(rectangle) {
|
|
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;
|
|
293
|
+
}
|
|
294
|
+
});
|
|
194
295
|
|
|
195
296
|
const EllipseEngine = {
|
|
196
297
|
draw(board, rectangle, options) {
|
|
@@ -202,12 +303,31 @@ const EllipseEngine = {
|
|
|
202
303
|
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
203
304
|
return isPointInEllipse(point, centerPoint, rectangle.width / 2, rectangle.height / 2);
|
|
204
305
|
},
|
|
306
|
+
getCornerPoints(rectangle) {
|
|
307
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
308
|
+
},
|
|
205
309
|
getNearestPoint(rectangle, point) {
|
|
206
310
|
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
207
311
|
return getNearestPointBetweenPointAndEllipse(point, centerPoint, rectangle.width / 2, rectangle.height / 2);
|
|
208
312
|
},
|
|
313
|
+
getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
|
|
314
|
+
const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
315
|
+
const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
316
|
+
const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
|
|
317
|
+
const a = rectangle.width / 2;
|
|
318
|
+
const b = rectangle.height / 2;
|
|
319
|
+
const slope = getTangentSlope(point[0], point[1], a, b);
|
|
320
|
+
return getVectorBySlope(point[0], point[1], slope);
|
|
321
|
+
},
|
|
209
322
|
getConnectorPoints(rectangle) {
|
|
210
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;
|
|
211
331
|
}
|
|
212
332
|
};
|
|
213
333
|
function getNearestPointBetweenPointAndEllipse(point, center, rx, ry, rotation = 0) {
|
|
@@ -245,28 +365,110 @@ function getNearestPointBetweenPointAndEllipse(point, center, rx, ry, rotation =
|
|
|
245
365
|
const signY = point[1] > center[1] ? 1 : -1;
|
|
246
366
|
return [center[0] + a * tx * signX, center[1] + b * ty * signY];
|
|
247
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* the result of slope is based on Cartesian coordinate system
|
|
370
|
+
* x, y are based on the position in the Cartesian coordinate system
|
|
371
|
+
*/
|
|
372
|
+
function getTangentSlope(x, y, a, b) {
|
|
373
|
+
const k = (-b * b * x) / (a * a * y);
|
|
374
|
+
return k;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* x, y are based on the position in the Cartesian coordinate system
|
|
378
|
+
*/
|
|
379
|
+
function getVectorBySlope(x, y, slope) {
|
|
380
|
+
const deltaX = 30;
|
|
381
|
+
const deltaY = -slope * deltaX;
|
|
382
|
+
let start = [0 - deltaX, 0 - deltaY];
|
|
383
|
+
let end = [0 + deltaX, 0 + deltaY];
|
|
384
|
+
// y < 0 acts on the lower half of the x-axis, with the starting point at the top and the end point at the bottom.
|
|
385
|
+
if (y < 0) {
|
|
386
|
+
const temp = start;
|
|
387
|
+
start = end;
|
|
388
|
+
end = temp;
|
|
389
|
+
}
|
|
390
|
+
const vector = [end[0] - start[0], end[1] - start[1]];
|
|
391
|
+
return vector;
|
|
392
|
+
}
|
|
248
393
|
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
394
|
+
const getHexagonPoints = (rectangle) => {
|
|
395
|
+
return [
|
|
396
|
+
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
397
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y],
|
|
398
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
399
|
+
[rectangle.x + (rectangle.width * 3) / 4, rectangle.y + rectangle.height],
|
|
400
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
401
|
+
[rectangle.x, rectangle.y + rectangle.height / 2]
|
|
402
|
+
];
|
|
403
|
+
};
|
|
404
|
+
const HexagonEngine = createPolygonEngine({
|
|
405
|
+
getPolygonPoints: getHexagonPoints,
|
|
406
|
+
getConnectorPoints(rectangle) {
|
|
407
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
260
408
|
},
|
|
261
|
-
|
|
262
|
-
const
|
|
263
|
-
|
|
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;
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const getLeftArrowPoints = (rectangle) => {
|
|
419
|
+
return [
|
|
420
|
+
[rectangle.x, rectangle.y + rectangle.height / 2],
|
|
421
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y],
|
|
422
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y + rectangle.height * 0.2],
|
|
423
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * 0.2],
|
|
424
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * 0.8],
|
|
425
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y + rectangle.height * 0.8],
|
|
426
|
+
[rectangle.x + rectangle.width * 0.32, rectangle.y + rectangle.height]
|
|
427
|
+
];
|
|
428
|
+
};
|
|
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
|
+
];
|
|
264
436
|
},
|
|
265
|
-
|
|
266
|
-
const
|
|
267
|
-
|
|
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;
|
|
268
443
|
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
const getOctagonPoints = (rectangle) => {
|
|
447
|
+
return [
|
|
448
|
+
[rectangle.x + (rectangle.width * 3) / 10, rectangle.y],
|
|
449
|
+
[rectangle.x + (rectangle.width * 7) / 10, rectangle.y],
|
|
450
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 3) / 10],
|
|
451
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 7) / 10],
|
|
452
|
+
[rectangle.x + (rectangle.width * 7) / 10, rectangle.y + rectangle.height],
|
|
453
|
+
[rectangle.x + (rectangle.width * 3) / 10, rectangle.y + rectangle.height],
|
|
454
|
+
[rectangle.x, rectangle.y + (rectangle.height * 7) / 10],
|
|
455
|
+
[rectangle.x, rectangle.y + (rectangle.height * 3) / 10]
|
|
456
|
+
];
|
|
269
457
|
};
|
|
458
|
+
const OctagonEngine = createPolygonEngine({
|
|
459
|
+
getPolygonPoints: getOctagonPoints,
|
|
460
|
+
getConnectorPoints(rectangle) {
|
|
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;
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
270
472
|
const getParallelogramPoints = (rectangle) => {
|
|
271
473
|
return [
|
|
272
474
|
[rectangle.x + rectangle.width / 4, rectangle.y],
|
|
@@ -275,6 +477,90 @@ const getParallelogramPoints = (rectangle) => {
|
|
|
275
477
|
[rectangle.x, rectangle.y + rectangle.height]
|
|
276
478
|
];
|
|
277
479
|
};
|
|
480
|
+
const ParallelogramEngine = createPolygonEngine({
|
|
481
|
+
getPolygonPoints: getParallelogramPoints,
|
|
482
|
+
getConnectorPoints: (rectangle) => {
|
|
483
|
+
const cornerPoints = getParallelogramPoints(rectangle);
|
|
484
|
+
return getCenterPointsOnPolygon(cornerPoints);
|
|
485
|
+
},
|
|
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;
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
const getPentagonPoints = (rectangle) => {
|
|
496
|
+
return [
|
|
497
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
498
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 2) / 5],
|
|
499
|
+
[rectangle.x + (rectangle.width * 4) / 5, rectangle.y + rectangle.height],
|
|
500
|
+
[rectangle.x + rectangle.width / 5, rectangle.y + rectangle.height],
|
|
501
|
+
[rectangle.x, rectangle.y + (rectangle.height * 2) / 5]
|
|
502
|
+
];
|
|
503
|
+
};
|
|
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
|
+
};
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const getPentagonArrowPoints = (rectangle) => {
|
|
522
|
+
return [
|
|
523
|
+
[rectangle.x, rectangle.y],
|
|
524
|
+
[rectangle.x + (rectangle.width * 3) / 5, rectangle.y],
|
|
525
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
526
|
+
[rectangle.x + (rectangle.width * 3) / 5, rectangle.y + rectangle.height],
|
|
527
|
+
[rectangle.x, rectangle.y + rectangle.height]
|
|
528
|
+
];
|
|
529
|
+
};
|
|
530
|
+
const PentagonArrowEngine = createPolygonEngine({
|
|
531
|
+
getPolygonPoints: getPentagonArrowPoints,
|
|
532
|
+
getConnectorPoints(rectangle) {
|
|
533
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
534
|
+
},
|
|
535
|
+
getTextRectangle(element) {
|
|
536
|
+
const rectangle = getTextRectangle(element);
|
|
537
|
+
rectangle.width = (rectangle.width * 3) / 5;
|
|
538
|
+
return rectangle;
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
const getProcessArrowPoints = (rectangle) => {
|
|
543
|
+
const wider = rectangle.width > rectangle.height / 2;
|
|
544
|
+
return [
|
|
545
|
+
[rectangle.x, rectangle.y],
|
|
546
|
+
[rectangle.x + (wider ? rectangle.width - rectangle.height / 2 : 0), rectangle.y],
|
|
547
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
548
|
+
[rectangle.x + (wider ? rectangle.width - rectangle.height / 2 : 0), rectangle.y + rectangle.height],
|
|
549
|
+
[rectangle.x, rectangle.y + rectangle.height],
|
|
550
|
+
[rectangle.x + (wider ? rectangle.height / 2 : rectangle.width), rectangle.y + rectangle.height / 2]
|
|
551
|
+
];
|
|
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
|
+
});
|
|
278
564
|
|
|
279
565
|
const RectangleEngine = {
|
|
280
566
|
draw(board, rectangle, options) {
|
|
@@ -284,15 +570,48 @@ const RectangleEngine = {
|
|
|
284
570
|
const rangeRectangle = RectangleClient.toRectangleClient([point, point]);
|
|
285
571
|
return RectangleClient.isHit(rectangle, rangeRectangle);
|
|
286
572
|
},
|
|
573
|
+
getCornerPoints(rectangle) {
|
|
574
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
575
|
+
},
|
|
287
576
|
getNearestPoint(rectangle, point) {
|
|
288
|
-
|
|
289
|
-
|
|
577
|
+
return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
|
|
578
|
+
},
|
|
579
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
580
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
581
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
582
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
290
583
|
},
|
|
291
584
|
getConnectorPoints(rectangle) {
|
|
292
585
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
293
586
|
}
|
|
294
587
|
};
|
|
295
588
|
|
|
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
|
+
];
|
|
607
|
+
},
|
|
608
|
+
getTextRectangle(element) {
|
|
609
|
+
const rectangle = getTextRectangle(element);
|
|
610
|
+
rectangle.width = rectangle.width * 0.68;
|
|
611
|
+
return rectangle;
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
|
|
296
615
|
const RoundRectangleEngine = {
|
|
297
616
|
draw(board, rectangle, options) {
|
|
298
617
|
return drawRoundRectangle(PlaitBoard.getRoughSVG(board), rectangle.x, rectangle.y, rectangle.x + rectangle.width, rectangle.y + rectangle.height, { ...options, fillStyle: 'solid' }, false, getRoundRectangleRadius(rectangle));
|
|
@@ -300,8 +619,16 @@ const RoundRectangleEngine = {
|
|
|
300
619
|
isHit(rectangle, point) {
|
|
301
620
|
return isPointInRoundRectangle(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
302
621
|
},
|
|
622
|
+
getCornerPoints(rectangle) {
|
|
623
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
624
|
+
},
|
|
303
625
|
getNearestPoint(rectangle, point) {
|
|
304
|
-
return getNearestPointBetweenPointAndRoundRectangle(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
626
|
+
return getNearestPointBetweenPointAndRoundRectangle$1(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
627
|
+
},
|
|
628
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
629
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
630
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
631
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
305
632
|
},
|
|
306
633
|
getConnectorPoints(rectangle) {
|
|
307
634
|
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
@@ -310,6 +637,247 @@ const RoundRectangleEngine = {
|
|
|
310
637
|
const getRoundRectangleRadius = (rectangle) => {
|
|
311
638
|
return Math.min(rectangle.width * 0.1, rectangle.height * 0.1);
|
|
312
639
|
};
|
|
640
|
+
function getNearestPointBetweenPointAndRoundRectangle$1(point, rectangle, radius) {
|
|
641
|
+
const { x: rectX, y: rectY, width, height } = rectangle;
|
|
642
|
+
const cornerPoints = RectangleClient.getCornerPoints(rectangle);
|
|
643
|
+
let result = getNearestPointBetweenPointAndSegments(point, cornerPoints);
|
|
644
|
+
let circleCenter = null;
|
|
645
|
+
const inLeftTop = point[0] >= rectX && point[0] <= rectX + radius && point[1] >= rectY && point[1] <= rectY + radius;
|
|
646
|
+
if (inLeftTop) {
|
|
647
|
+
circleCenter = [rectX + radius, rectY + radius];
|
|
648
|
+
}
|
|
649
|
+
const inLeftBottom = point[0] >= rectX && point[0] <= rectX + radius && point[1] >= rectY + height && point[1] <= rectY + height - radius;
|
|
650
|
+
if (inLeftBottom) {
|
|
651
|
+
circleCenter = [rectX + radius, rectY + height - radius];
|
|
652
|
+
}
|
|
653
|
+
const inRightTop = point[0] >= rectX + width - radius && point[0] <= rectX + width && point[1] >= rectY && point[1] <= rectY + radius;
|
|
654
|
+
if (inRightTop) {
|
|
655
|
+
circleCenter = [rectX + width - radius, rectY + radius];
|
|
656
|
+
}
|
|
657
|
+
const inRightBottom = point[0] >= rectX + width - radius &&
|
|
658
|
+
point[0] <= rectX + width &&
|
|
659
|
+
point[1] >= rectY + height - radius &&
|
|
660
|
+
point[1] <= rectY + height;
|
|
661
|
+
if (inRightBottom) {
|
|
662
|
+
circleCenter = [rectX + width - radius, rectY + height - radius];
|
|
663
|
+
}
|
|
664
|
+
if (circleCenter) {
|
|
665
|
+
result = getNearestPointBetweenPointAndEllipse(point, circleCenter, radius, radius);
|
|
666
|
+
}
|
|
667
|
+
return result;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const heightRatio = 3 / 4;
|
|
671
|
+
const RoundCommentEngine = {
|
|
672
|
+
draw(board, rectangle, options) {
|
|
673
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
674
|
+
const x1 = rectangle.x;
|
|
675
|
+
const y1 = rectangle.y;
|
|
676
|
+
const x2 = rectangle.x + rectangle.width;
|
|
677
|
+
const y2 = rectangle.y + rectangle.height * heightRatio;
|
|
678
|
+
const radius = getRoundRectangleRadius(rectangle);
|
|
679
|
+
const point1 = [x1 + radius, y1];
|
|
680
|
+
const point2 = [x2 - radius, y1];
|
|
681
|
+
const point3 = [x2, y1 + radius];
|
|
682
|
+
const point4 = [x2, y2 - radius];
|
|
683
|
+
const point5 = [x2 - radius, y2];
|
|
684
|
+
const point6 = [x1 + radius, y2];
|
|
685
|
+
const point7 = [x1, y2 - radius];
|
|
686
|
+
const point8 = [x1, y1 + radius];
|
|
687
|
+
const point9 = [x1 + rectangle.width / 4, y2];
|
|
688
|
+
const point10 = [x1 + rectangle.width / 4, rectangle.y + rectangle.height];
|
|
689
|
+
const point11 = [x1 + rectangle.width / 2, y2];
|
|
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' });
|
|
691
|
+
},
|
|
692
|
+
isHit(rectangle, point) {
|
|
693
|
+
const points = [
|
|
694
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + (rectangle.height * 3) / 4],
|
|
695
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
696
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + (rectangle.height * 3) / 4]
|
|
697
|
+
];
|
|
698
|
+
rectangle.height = (rectangle.height * 3) / 4;
|
|
699
|
+
return isPointInPolygon(point, points) || isPointInRoundRectangle(point, rectangle, getRoundRectangleRadius(rectangle));
|
|
700
|
+
},
|
|
701
|
+
getCornerPoints(rectangle) {
|
|
702
|
+
return getRoundCommentPoints(rectangle);
|
|
703
|
+
},
|
|
704
|
+
getNearestPoint(rectangle, point) {
|
|
705
|
+
return getNearestPointBetweenPointAndSegments(point, getRoundCommentPoints(rectangle));
|
|
706
|
+
},
|
|
707
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
708
|
+
const corners = getRoundCommentPoints(rectangle);
|
|
709
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
710
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
711
|
+
},
|
|
712
|
+
getConnectorPoints(rectangle) {
|
|
713
|
+
return [
|
|
714
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
715
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
|
|
716
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height * heightRatio],
|
|
717
|
+
[rectangle.x, rectangle.y + rectangle.height / 2]
|
|
718
|
+
];
|
|
719
|
+
},
|
|
720
|
+
getTextRectangle(element) {
|
|
721
|
+
const elementRectangle = getRectangleByPoints(element.points);
|
|
722
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
723
|
+
const height = element.textHeight;
|
|
724
|
+
const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
|
|
725
|
+
return {
|
|
726
|
+
height,
|
|
727
|
+
width: width > 0 ? width : 0,
|
|
728
|
+
x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
|
|
729
|
+
y: elementRectangle.y + (elementRectangle.height * heightRatio - height) / 2
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
const getRoundCommentPoints = (rectangle) => {
|
|
734
|
+
return [
|
|
735
|
+
[rectangle.x, rectangle.y],
|
|
736
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
737
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height * heightRatio],
|
|
738
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height * heightRatio],
|
|
739
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
|
|
740
|
+
[rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height * heightRatio],
|
|
741
|
+
[rectangle.x, rectangle.y + rectangle.height * heightRatio]
|
|
742
|
+
];
|
|
743
|
+
};
|
|
744
|
+
|
|
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);
|
|
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,
|
|
777
|
+
getConnectorPoints(rectangle) {
|
|
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
|
+
};
|
|
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
|
+
];
|
|
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
|
+
|
|
821
|
+
const getStarPoints = (rectangle) => {
|
|
822
|
+
return [
|
|
823
|
+
[rectangle.x + rectangle.width / 2, rectangle.y + (rectangle.height * 75) / 91],
|
|
824
|
+
[rectangle.x + (rectangle.width * 18.61) / 96, rectangle.y + rectangle.height],
|
|
825
|
+
[rectangle.x + (rectangle.width * 24.2235871) / 96, rectangle.y + (rectangle.height * 57.7254249) / 91],
|
|
826
|
+
[rectangle.x, rectangle.y + (rectangle.height * 34.5491503) / 91],
|
|
827
|
+
[rectangle.x + (rectangle.width * 33.3053687) / 96, rectangle.y + (rectangle.height * 29.7745751) / 91],
|
|
828
|
+
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
829
|
+
[rectangle.x + (rectangle.width * 62.6946313) / 96, rectangle.y + (rectangle.height * 29.7745751) / 91],
|
|
830
|
+
[rectangle.x + rectangle.width, rectangle.y + (rectangle.height * 34.5491503) / 91],
|
|
831
|
+
[rectangle.x + (rectangle.width * 71.7764129) / 96, rectangle.y + (rectangle.height * 57.7254249) / 91],
|
|
832
|
+
[rectangle.x + (rectangle.width * 77.3892626) / 96, rectangle.y + rectangle.height]
|
|
833
|
+
];
|
|
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
|
+
});
|
|
855
|
+
|
|
856
|
+
const TerminalEngine = {
|
|
857
|
+
draw(board, rectangle, options) {
|
|
858
|
+
return drawRoundRectangle(PlaitBoard.getRoughSVG(board), rectangle.x, rectangle.y, rectangle.x + rectangle.width, rectangle.y + rectangle.height, { ...options, fillStyle: 'solid' }, false, getStartEndRadius(rectangle));
|
|
859
|
+
},
|
|
860
|
+
isHit(rectangle, point) {
|
|
861
|
+
return isPointInRoundRectangle(point, rectangle, getStartEndRadius(rectangle));
|
|
862
|
+
},
|
|
863
|
+
getCornerPoints(rectangle) {
|
|
864
|
+
return RectangleClient.getCornerPoints(rectangle);
|
|
865
|
+
},
|
|
866
|
+
getNearestPoint(rectangle, point) {
|
|
867
|
+
return getNearestPointBetweenPointAndRoundRectangle(point, rectangle, getStartEndRadius(rectangle));
|
|
868
|
+
},
|
|
869
|
+
getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
|
|
870
|
+
const corners = RectangleEngine.getCornerPoints(rectangle);
|
|
871
|
+
const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
|
|
872
|
+
return getEdgeOnPolygonByPoint(corners, point);
|
|
873
|
+
},
|
|
874
|
+
getConnectorPoints(rectangle) {
|
|
875
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
const getStartEndRadius = (rectangle) => {
|
|
879
|
+
return Math.min(rectangle.width / 2, rectangle.height / 2);
|
|
880
|
+
};
|
|
313
881
|
function getNearestPointBetweenPointAndRoundRectangle(point, rectangle, radius) {
|
|
314
882
|
const { x: rectX, y: rectY, width, height } = rectangle;
|
|
315
883
|
const cornerPoints = RectangleClient.getCornerPoints(rectangle);
|
|
@@ -340,25 +908,277 @@ function getNearestPointBetweenPointAndRoundRectangle(point, rectangle, radius)
|
|
|
340
908
|
return result;
|
|
341
909
|
}
|
|
342
910
|
|
|
911
|
+
const getManualInputPoints = (rectangle) => {
|
|
912
|
+
return [
|
|
913
|
+
[rectangle.x, rectangle.y + rectangle.height / 4],
|
|
914
|
+
[rectangle.x + rectangle.width, rectangle.y],
|
|
915
|
+
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
|
|
916
|
+
[rectangle.x, rectangle.y + rectangle.height]
|
|
917
|
+
];
|
|
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
|
+
});
|
|
1014
|
+
|
|
1015
|
+
const DelayEngine = {
|
|
1016
|
+
draw(board, rectangle, options) {
|
|
1017
|
+
const rs = PlaitBoard.getRoughSVG(board);
|
|
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;
|
|
1022
|
+
},
|
|
1023
|
+
isHit(rectangle, point) {
|
|
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);
|
|
1035
|
+
},
|
|
1036
|
+
getNearestPoint(rectangle, point) {
|
|
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);
|
|
1051
|
+
},
|
|
1052
|
+
getConnectorPoints(rectangle) {
|
|
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;
|
|
1066
|
+
},
|
|
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;
|
|
1078
|
+
},
|
|
1079
|
+
getCornerPoints(rectangle) {
|
|
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
|
+
|
|
343
1127
|
const ShapeEngineMap = {
|
|
344
|
-
[
|
|
345
|
-
[
|
|
346
|
-
[
|
|
347
|
-
[
|
|
348
|
-
[
|
|
349
|
-
[
|
|
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
|
|
350
1159
|
};
|
|
351
1160
|
const getEngine = (shape) => {
|
|
352
1161
|
return ShapeEngineMap[shape];
|
|
353
1162
|
};
|
|
354
1163
|
|
|
1164
|
+
const getShape = (value) => {
|
|
1165
|
+
if (PlaitDrawElement.isImage(value)) {
|
|
1166
|
+
return BasicShapes.rectangle;
|
|
1167
|
+
}
|
|
1168
|
+
return value.shape;
|
|
1169
|
+
};
|
|
1170
|
+
|
|
355
1171
|
const createGeometryElement = (shape, points, text, options) => {
|
|
356
1172
|
let textOptions = {};
|
|
357
1173
|
let alignment = Alignment.center;
|
|
358
|
-
if (shape ===
|
|
1174
|
+
if (shape === BasicShapes.text) {
|
|
359
1175
|
textOptions = { autoSize: true };
|
|
360
1176
|
alignment = undefined;
|
|
361
1177
|
}
|
|
1178
|
+
let flowchartOptions = {};
|
|
1179
|
+
if (getFlowchartPointers().includes(shape)) {
|
|
1180
|
+
flowchartOptions = { fill: '#ffffff' };
|
|
1181
|
+
}
|
|
362
1182
|
return {
|
|
363
1183
|
id: idCreator(),
|
|
364
1184
|
type: 'geometry',
|
|
@@ -369,7 +1189,8 @@ const createGeometryElement = (shape, points, text, options) => {
|
|
|
369
1189
|
text: buildText(text, alignment),
|
|
370
1190
|
points,
|
|
371
1191
|
...textOptions,
|
|
372
|
-
...options
|
|
1192
|
+
...options,
|
|
1193
|
+
...flowchartOptions
|
|
373
1194
|
};
|
|
374
1195
|
};
|
|
375
1196
|
const getPointsByCenterPoint = (point, width, height) => {
|
|
@@ -393,14 +1214,15 @@ const drawBoundMask = (board, element) => {
|
|
|
393
1214
|
const G = createG();
|
|
394
1215
|
const rectangle = getRectangleByPoints(element.points);
|
|
395
1216
|
const activeRectangle = RectangleClient.inflate(rectangle, ACTIVE_STROKE_WIDTH);
|
|
396
|
-
const
|
|
1217
|
+
const shape = getShape(element);
|
|
1218
|
+
const maskG = drawGeometry(board, activeRectangle, shape, {
|
|
397
1219
|
stroke: SELECTION_BORDER_COLOR,
|
|
398
1220
|
strokeWidth: 1,
|
|
399
1221
|
fill: SELECTION_FILL_COLOR,
|
|
400
1222
|
fillStyle: 'solid'
|
|
401
1223
|
});
|
|
402
1224
|
G.appendChild(maskG);
|
|
403
|
-
const connectorPoints = getEngine(
|
|
1225
|
+
const connectorPoints = getEngine(shape).getConnectorPoints(activeRectangle);
|
|
404
1226
|
connectorPoints.forEach(point => {
|
|
405
1227
|
const circleG = drawCircle(PlaitBoard.getRoughSVG(board), point, 6, {
|
|
406
1228
|
stroke: '#999999',
|
|
@@ -418,7 +1240,8 @@ const drawGeometry = (board, outerRectangle, shape, options) => {
|
|
|
418
1240
|
const getNearestPoint = (element, point, inflateDelta = 0) => {
|
|
419
1241
|
const rectangle = getRectangleByPoints(element.points);
|
|
420
1242
|
const activeRectangle = RectangleClient.inflate(rectangle, inflateDelta);
|
|
421
|
-
|
|
1243
|
+
const shape = getShape(element);
|
|
1244
|
+
return getEngine(shape).getNearestPoint(activeRectangle, point);
|
|
422
1245
|
};
|
|
423
1246
|
const getCenterPointsOnPolygon = (points) => {
|
|
424
1247
|
const centerPoint = [];
|
|
@@ -428,6 +1251,20 @@ const getCenterPointsOnPolygon = (points) => {
|
|
|
428
1251
|
}
|
|
429
1252
|
return centerPoint;
|
|
430
1253
|
};
|
|
1254
|
+
const getEdgeOnPolygonByPoint = (corners, point) => {
|
|
1255
|
+
for (let index = 1; index <= corners.length; index++) {
|
|
1256
|
+
let start = corners[index - 1];
|
|
1257
|
+
let end = index === corners.length ? corners[0] : corners[index];
|
|
1258
|
+
const distance = distanceBetweenPointAndSegment(point[0], point[1], start[0], start[1], end[0], end[1]);
|
|
1259
|
+
if (distance < 1) {
|
|
1260
|
+
return [start, end];
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
return null;
|
|
1264
|
+
};
|
|
1265
|
+
const getDefaultFlowchartProperty = (symbol) => {
|
|
1266
|
+
return DefaultFlowchartPropertyMap[symbol];
|
|
1267
|
+
};
|
|
431
1268
|
|
|
432
1269
|
const drawLineArrow = (element, points, options) => {
|
|
433
1270
|
const arrowG = createG();
|
|
@@ -435,16 +1272,19 @@ const drawLineArrow = (element, points, options) => {
|
|
|
435
1272
|
return null;
|
|
436
1273
|
}
|
|
437
1274
|
if (!PlaitLine.isSourceMark(element, LineMarkerType.none)) {
|
|
438
|
-
const
|
|
1275
|
+
const source = getExtendPoint(points[0], points[1], 24);
|
|
1276
|
+
const sourceArrow = getArrow(element, { marker: element.source.marker, source, target: points[0], isSource: true }, options);
|
|
439
1277
|
sourceArrow && arrowG.appendChild(sourceArrow);
|
|
440
1278
|
}
|
|
441
1279
|
if (!PlaitLine.isTargetMark(element, LineMarkerType.none)) {
|
|
442
|
-
const
|
|
1280
|
+
const source = getExtendPoint(points[points.length - 1], points[points.length - 2], 24);
|
|
1281
|
+
const arrow = getArrow(element, { marker: element.target.marker, source, target: points[points.length - 1], isSource: false }, options);
|
|
443
1282
|
arrow && arrowG.appendChild(arrow);
|
|
444
1283
|
}
|
|
445
1284
|
return arrowG;
|
|
446
1285
|
};
|
|
447
|
-
const getArrow = (element,
|
|
1286
|
+
const getArrow = (element, arrowOptions, options) => {
|
|
1287
|
+
const { marker, source, target, isSource } = arrowOptions;
|
|
448
1288
|
let targetArrow;
|
|
449
1289
|
switch (marker) {
|
|
450
1290
|
case LineMarkerType.openTriangle: {
|
|
@@ -463,16 +1303,27 @@ const getArrow = (element, marker, source, target, options) => {
|
|
|
463
1303
|
targetArrow = drawSharpArrow(source, target, options);
|
|
464
1304
|
break;
|
|
465
1305
|
}
|
|
1306
|
+
case LineMarkerType.oneSideUp: {
|
|
1307
|
+
targetArrow = drawOneSideArrow(source, target, isSource ? 'down' : 'up', options);
|
|
1308
|
+
break;
|
|
1309
|
+
}
|
|
1310
|
+
case LineMarkerType.oneSideDown: {
|
|
1311
|
+
targetArrow = drawOneSideArrow(source, target, isSource ? 'up' : 'down', options);
|
|
1312
|
+
break;
|
|
1313
|
+
}
|
|
1314
|
+
case LineMarkerType.hollowTriangle: {
|
|
1315
|
+
targetArrow = drawHollowTriangleArrow(source, target, options);
|
|
1316
|
+
break;
|
|
1317
|
+
}
|
|
1318
|
+
case LineMarkerType.singleSlash: {
|
|
1319
|
+
targetArrow = drawSingleSlash(source, target, isSource, options);
|
|
1320
|
+
break;
|
|
1321
|
+
}
|
|
466
1322
|
}
|
|
467
1323
|
return targetArrow;
|
|
468
1324
|
};
|
|
469
1325
|
const drawSharpArrow = (source, target, options) => {
|
|
470
|
-
const directionFactor = getFactorByPoints(source, target);
|
|
471
1326
|
const startPoint = target;
|
|
472
|
-
// const startPoint: Point = [
|
|
473
|
-
// target[0],
|
|
474
|
-
// target[1]
|
|
475
|
-
// ];
|
|
476
1327
|
const { pointLeft, pointRight } = arrowPoints(source, target, 12, 20);
|
|
477
1328
|
const g = createG();
|
|
478
1329
|
const path = createPath();
|
|
@@ -487,10 +1338,7 @@ const drawSharpArrow = (source, target, options) => {
|
|
|
487
1338
|
const drawArrow = (element, source, target, options) => {
|
|
488
1339
|
const directionFactor = getFactorByPoints(source, target);
|
|
489
1340
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
490
|
-
const endPoint = [
|
|
491
|
-
target[0] + strokeWidth * directionFactor.x / 2,
|
|
492
|
-
target[1] + strokeWidth * directionFactor.y / 2
|
|
493
|
-
];
|
|
1341
|
+
const endPoint = [target[0] + (strokeWidth * directionFactor.x) / 2, target[1] + (strokeWidth * directionFactor.y) / 2];
|
|
494
1342
|
const middlePoint = [endPoint[0] - 8 * directionFactor.x, endPoint[1] - 8 * directionFactor.y];
|
|
495
1343
|
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 12, 30);
|
|
496
1344
|
const arrowG = drawLinearPath([pointLeft, endPoint, pointRight, middlePoint], { ...options, fill: options.stroke }, true);
|
|
@@ -506,13 +1354,26 @@ const drawSolidTriangle = (source, target, options) => {
|
|
|
506
1354
|
const drawOpenTriangle = (element, source, target, options) => {
|
|
507
1355
|
const directionFactor = getFactorByPoints(source, target);
|
|
508
1356
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
509
|
-
const endPoint = [
|
|
510
|
-
target[0] + strokeWidth * directionFactor.x / 2,
|
|
511
|
-
target[1] + strokeWidth * directionFactor.y / 2
|
|
512
|
-
];
|
|
1357
|
+
const endPoint = [target[0] + (strokeWidth * directionFactor.x) / 2, target[1] + (strokeWidth * directionFactor.y) / 2];
|
|
513
1358
|
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 12, 40);
|
|
514
1359
|
return drawLinearPath([pointLeft, endPoint, pointRight], options);
|
|
515
1360
|
};
|
|
1361
|
+
const drawOneSideArrow = (source, target, side, options) => {
|
|
1362
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 12, 40);
|
|
1363
|
+
return drawLinearPath([side === 'up' ? pointRight : pointLeft, target], options);
|
|
1364
|
+
};
|
|
1365
|
+
const drawSingleSlash = (source, target, isSource, options) => {
|
|
1366
|
+
source = getExtendPoint(target, source, 12);
|
|
1367
|
+
const middlePoint = getExtendPoint(target, source, 6);
|
|
1368
|
+
const angle = isSource ? 120 : 60;
|
|
1369
|
+
const start = rotate(...source, ...middlePoint, (angle * Math.PI) / 180);
|
|
1370
|
+
const end = rotate(...target, ...middlePoint, (angle * Math.PI) / 180);
|
|
1371
|
+
return drawLinearPath([start, end], options);
|
|
1372
|
+
};
|
|
1373
|
+
const drawHollowTriangleArrow = (source, target, options) => {
|
|
1374
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 12, 30);
|
|
1375
|
+
return drawLinearPath([pointLeft, pointRight, target], { ...options, fill: 'white' }, true);
|
|
1376
|
+
};
|
|
516
1377
|
|
|
517
1378
|
const createLineElement = (shape, points, source, target, options) => {
|
|
518
1379
|
return {
|
|
@@ -528,28 +1389,127 @@ const createLineElement = (shape, points, source, target, options) => {
|
|
|
528
1389
|
};
|
|
529
1390
|
};
|
|
530
1391
|
const getLinePoints = (board, element) => {
|
|
531
|
-
|
|
1392
|
+
switch (element.shape) {
|
|
1393
|
+
case LineShape.elbow: {
|
|
1394
|
+
return getElbowPoints(board, element);
|
|
1395
|
+
}
|
|
1396
|
+
case LineShape.curve: {
|
|
1397
|
+
return getCurvePoints(board, element);
|
|
1398
|
+
}
|
|
1399
|
+
default: {
|
|
1400
|
+
return PlaitLine.getPoints(board, element);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
532
1403
|
};
|
|
533
|
-
const
|
|
534
|
-
|
|
1404
|
+
const getLineHandleRefPair = (board, element) => {
|
|
1405
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1406
|
+
const sourceBoundElement = element.source.boundId ? getElementById(board, element.source.boundId) : undefined;
|
|
1407
|
+
const targetBoundElement = element.target.boundId ? getElementById(board, element.target.boundId) : undefined;
|
|
1408
|
+
let sourcePoint = sourceBoundElement ? getConnectionPoint(sourceBoundElement, element.source.connection) : element.points[0];
|
|
1409
|
+
let targetPoint = targetBoundElement
|
|
1410
|
+
? getConnectionPoint(targetBoundElement, element.target.connection)
|
|
1411
|
+
: element.points[element.points.length - 1];
|
|
1412
|
+
let sourceDirection = getDirectionByVector([targetPoint[0] - sourcePoint[0], targetPoint[1] - sourcePoint[1]]);
|
|
1413
|
+
let targetDirection = getOppositeDirection(sourceDirection);
|
|
1414
|
+
const sourceFactor = getDirectionFactor(sourceDirection);
|
|
1415
|
+
const targetFactor = getDirectionFactor(targetDirection);
|
|
1416
|
+
const sourceHandleRef = {
|
|
1417
|
+
key: LineHandleKey.source,
|
|
1418
|
+
point: sourcePoint,
|
|
1419
|
+
direction: sourceDirection,
|
|
1420
|
+
vector: [sourceFactor.x, sourceFactor.y]
|
|
1421
|
+
};
|
|
1422
|
+
const targetHandleRef = {
|
|
1423
|
+
key: LineHandleKey.target,
|
|
1424
|
+
point: targetPoint,
|
|
1425
|
+
direction: targetDirection,
|
|
1426
|
+
vector: [targetFactor.x, targetFactor.y]
|
|
1427
|
+
};
|
|
1428
|
+
if (sourceBoundElement) {
|
|
1429
|
+
const connectionOffset = PlaitLine.isSourceMarkOrTargetMark(element, LineMarkerType.none, LineHandleKey.source) ? 0 : strokeWidth;
|
|
1430
|
+
const sourceVector = getVectorByConnection(sourceBoundElement, element.source.connection);
|
|
1431
|
+
const direction = getDirectionByVector(sourceVector);
|
|
1432
|
+
sourceDirection = direction ? direction : sourceDirection;
|
|
1433
|
+
sourcePoint = getConnectionPoint(sourceBoundElement, element.source.connection, sourceDirection, connectionOffset);
|
|
1434
|
+
sourceHandleRef.boundElement = sourceBoundElement;
|
|
1435
|
+
sourceHandleRef.direction = sourceDirection;
|
|
1436
|
+
sourceHandleRef.point = sourcePoint;
|
|
1437
|
+
sourceHandleRef.vector = sourceVector;
|
|
1438
|
+
}
|
|
1439
|
+
if (targetBoundElement) {
|
|
1440
|
+
const connectionOffset = PlaitLine.isSourceMarkOrTargetMark(element, LineMarkerType.none, LineHandleKey.target) ? 0 : strokeWidth;
|
|
1441
|
+
const targetVector = getVectorByConnection(targetBoundElement, element.target.connection);
|
|
1442
|
+
const direction = getDirectionByVector(targetVector);
|
|
1443
|
+
targetDirection = direction ? direction : targetDirection;
|
|
1444
|
+
targetPoint = getConnectionPoint(targetBoundElement, element.target.connection, targetDirection, connectionOffset);
|
|
1445
|
+
targetHandleRef.boundElement = targetBoundElement;
|
|
1446
|
+
targetHandleRef.direction = targetDirection;
|
|
1447
|
+
targetHandleRef.point = targetPoint;
|
|
1448
|
+
targetHandleRef.vector = targetVector;
|
|
1449
|
+
}
|
|
1450
|
+
return { source: sourceHandleRef, target: targetHandleRef };
|
|
535
1451
|
};
|
|
536
1452
|
const getElbowPoints = (board, element) => {
|
|
537
1453
|
if (element.points.length === 2) {
|
|
538
|
-
const
|
|
539
|
-
const
|
|
540
|
-
let
|
|
541
|
-
|
|
542
|
-
if (element.source.connection) {
|
|
543
|
-
sourceDirection = getDirectionByPoint(element.source.connection, sourceDirection);
|
|
544
|
-
}
|
|
545
|
-
if (element.target.connection) {
|
|
546
|
-
targetDirection = getDirectionByPoint(element.target.connection, targetDirection);
|
|
547
|
-
}
|
|
548
|
-
const points = getPoints(source, sourceDirection, target, targetDirection, 30);
|
|
1454
|
+
const handleRefPair = getLineHandleRefPair(board, element);
|
|
1455
|
+
const offset = element.source.boundId || element.target.boundId ? 30 : 0;
|
|
1456
|
+
let points = getPoints(handleRefPair.source.point, handleRefPair.source.direction, handleRefPair.target.point, handleRefPair.target.direction, offset);
|
|
1457
|
+
points = removeDuplicatePoints(points);
|
|
549
1458
|
return points;
|
|
550
1459
|
}
|
|
551
1460
|
return element.points;
|
|
552
1461
|
};
|
|
1462
|
+
const getCurvePoints = (board, element) => {
|
|
1463
|
+
if (element.points.length === 2) {
|
|
1464
|
+
const handleRefPair = getLineHandleRefPair(board, element);
|
|
1465
|
+
const { source, target } = handleRefPair;
|
|
1466
|
+
const sourceBoundElement = handleRefPair.source.boundElement;
|
|
1467
|
+
const targetBoundElement = handleRefPair.target.boundElement;
|
|
1468
|
+
let curvePoints = [source.point];
|
|
1469
|
+
const sumDistance = distanceBetweenPointAndPoint(...source.point, ...target.point);
|
|
1470
|
+
const offset = 12 + sumDistance / 3;
|
|
1471
|
+
if (sourceBoundElement) {
|
|
1472
|
+
curvePoints.push(getPointByVector(source.point, source.vector, offset));
|
|
1473
|
+
}
|
|
1474
|
+
if (targetBoundElement) {
|
|
1475
|
+
curvePoints.push(getPointByVector(target.point, target.vector, offset));
|
|
1476
|
+
}
|
|
1477
|
+
const isSingleBound = (sourceBoundElement && !targetBoundElement) || (!sourceBoundElement && targetBoundElement);
|
|
1478
|
+
if (isSingleBound) {
|
|
1479
|
+
curvePoints.push(target.point);
|
|
1480
|
+
const points = Q2C(curvePoints);
|
|
1481
|
+
return pointsOnBezierCurves(points);
|
|
1482
|
+
}
|
|
1483
|
+
if (!sourceBoundElement && !targetBoundElement) {
|
|
1484
|
+
curvePoints.push(getPointByVector(source.point, source.vector, offset));
|
|
1485
|
+
curvePoints.push(getPointByVector(target.point, target.vector, offset));
|
|
1486
|
+
}
|
|
1487
|
+
curvePoints.push(target.point);
|
|
1488
|
+
return pointsOnBezierCurves(curvePoints);
|
|
1489
|
+
}
|
|
1490
|
+
else {
|
|
1491
|
+
//TODO 直接获取贝塞尔曲线上高密度点
|
|
1492
|
+
const points = PlaitLine.getPoints(board, element);
|
|
1493
|
+
const draw = PlaitBoard.getRoughSVG(board).generator.curve(points);
|
|
1494
|
+
let bezierPoints = transformOpsToPoints(draw.sets[0].ops);
|
|
1495
|
+
bezierPoints = removeDuplicatePoints(bezierPoints);
|
|
1496
|
+
return pointsOnBezierCurves(bezierPoints);
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
const transformOpsToPoints = (ops) => {
|
|
1500
|
+
const result = [];
|
|
1501
|
+
for (let item of ops) {
|
|
1502
|
+
if (item.op === 'move') {
|
|
1503
|
+
result.push([item.data[0], item.data[1]]);
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
result.push([item.data[0], item.data[1]]);
|
|
1507
|
+
result.push([item.data[2], item.data[3]]);
|
|
1508
|
+
result.push([item.data[4], item.data[5]]);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
return result;
|
|
1512
|
+
};
|
|
553
1513
|
const isHitPolyLine = (pathPoints, point, strokeWidth, expand = 0) => {
|
|
554
1514
|
const distance = distanceBetweenPointAndSegments(pathPoints, point);
|
|
555
1515
|
return distance <= strokeWidth + expand;
|
|
@@ -579,20 +1539,28 @@ const drawLine = (board, element) => {
|
|
|
579
1539
|
const strokeLineDash = getLineDashByElement(element);
|
|
580
1540
|
const options = { stroke: strokeColor, strokeWidth, strokeLineDash };
|
|
581
1541
|
const lineG = createG();
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
1542
|
+
let points = getLinePoints(board, element);
|
|
1543
|
+
let line;
|
|
1544
|
+
if (element.shape === LineShape.curve) {
|
|
1545
|
+
//TODO element.points 应为曲线拐点
|
|
1546
|
+
line = PlaitBoard.getRoughSVG(board).curve(points, options);
|
|
1547
|
+
}
|
|
1548
|
+
else {
|
|
1549
|
+
line = drawLinearPath(points, options);
|
|
1550
|
+
}
|
|
1551
|
+
const id = idCreator();
|
|
1552
|
+
line.setAttribute('mask', `url(#${id})`);
|
|
585
1553
|
lineG.appendChild(line);
|
|
586
|
-
const { mask, maskTargetFillRect } = drawMask(board, element);
|
|
1554
|
+
const { mask, maskTargetFillRect } = drawMask(board, element, id);
|
|
587
1555
|
lineG.appendChild(mask);
|
|
588
1556
|
line.appendChild(maskTargetFillRect);
|
|
589
1557
|
const arrow = drawLineArrow(element, points, { stroke: strokeColor, strokeWidth });
|
|
590
1558
|
arrow && lineG.appendChild(arrow);
|
|
591
1559
|
return lineG;
|
|
592
1560
|
};
|
|
593
|
-
function drawMask(board, element) {
|
|
1561
|
+
function drawMask(board, element, id) {
|
|
594
1562
|
const mask = createMask();
|
|
595
|
-
mask.setAttribute('id',
|
|
1563
|
+
mask.setAttribute('id', id);
|
|
596
1564
|
const points = getLinePoints(board, element);
|
|
597
1565
|
let rectangle = getRectangleByPoints(points);
|
|
598
1566
|
rectangle = RectangleClient.getOutlineRectangle(rectangle, -30);
|
|
@@ -613,33 +1581,16 @@ function drawMask(board, element) {
|
|
|
613
1581
|
maskTargetFillRect.setAttribute('opacity', '0');
|
|
614
1582
|
return { mask, maskTargetFillRect };
|
|
615
1583
|
}
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const
|
|
620
|
-
const
|
|
621
|
-
return
|
|
1584
|
+
const getConnectionPoint = (geometry, connection, direction, delta) => {
|
|
1585
|
+
const rectangle = getRectangleByPoints(geometry.points);
|
|
1586
|
+
if (direction && delta) {
|
|
1587
|
+
const directionFactor = getDirectionFactor(direction);
|
|
1588
|
+
const point = RectangleClient.getConnectionPoint(rectangle, connection);
|
|
1589
|
+
return [point[0] + directionFactor.x * delta, point[1] + directionFactor.y * delta];
|
|
622
1590
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
const getTargetPoint = (board, element) => {
|
|
626
|
-
if (element.target.boundId) {
|
|
627
|
-
const strokeWidth = getStrokeWidthByElement(element);
|
|
628
|
-
const connectionOffset = PlaitLine.isTargetMark(element, LineMarkerType.none) ? 0 : strokeWidth;
|
|
629
|
-
const boundElement = getElementById(board, element.target.boundId);
|
|
630
|
-
return boundElement
|
|
631
|
-
? getConnectionPoint(boundElement, element.target.connection, connectionOffset)
|
|
632
|
-
: element.points[element.points.length - 1];
|
|
1591
|
+
else {
|
|
1592
|
+
return RectangleClient.getConnectionPoint(rectangle, connection);
|
|
633
1593
|
}
|
|
634
|
-
return element.points[element.points.length - 1];
|
|
635
|
-
};
|
|
636
|
-
const getConnectionPoint = (geometry, connection, offset) => {
|
|
637
|
-
const rectangle = getRectangleByPoints(geometry.points);
|
|
638
|
-
const directionFactor = getDirectionFactor(getDirectionByPoint(connection, Direction.bottom));
|
|
639
|
-
return [
|
|
640
|
-
rectangle.x + rectangle.width * connection[0] + directionFactor.x * offset,
|
|
641
|
-
rectangle.y + rectangle.height * connection[1] + directionFactor.y * offset
|
|
642
|
-
];
|
|
643
1594
|
};
|
|
644
1595
|
const transformPointToConnection = (board, point, hitElement) => {
|
|
645
1596
|
let rectangle = getRectangleByPoints(hitElement.points);
|
|
@@ -650,7 +1601,8 @@ const transformPointToConnection = (board, point, hitElement) => {
|
|
|
650
1601
|
return [(nearestPoint[0] - rectangle.x) / rectangle.width, (nearestPoint[1] - rectangle.y) / rectangle.height];
|
|
651
1602
|
};
|
|
652
1603
|
const getHitConnectorPoint = (movingPoint, hitElement, rectangle) => {
|
|
653
|
-
const
|
|
1604
|
+
const shape = getShape(hitElement);
|
|
1605
|
+
const connector = getEngine(shape).getConnectorPoints(rectangle);
|
|
654
1606
|
const points = getPointsByCenterPoint(movingPoint, 5, 5);
|
|
655
1607
|
const pointRectangle = getRectangleByPoints(points);
|
|
656
1608
|
return connector.find(point => {
|
|
@@ -674,6 +1626,64 @@ const getBoardLines = (board) => {
|
|
|
674
1626
|
recursion: (element) => PlaitDrawElement.isDrawElement(element)
|
|
675
1627
|
});
|
|
676
1628
|
};
|
|
1629
|
+
const removeDuplicatePoints = (points) => {
|
|
1630
|
+
const newArray = [];
|
|
1631
|
+
points.forEach(point => {
|
|
1632
|
+
const index = newArray.findIndex(otherPoint => {
|
|
1633
|
+
return point[0] === otherPoint[0] && point[1] === otherPoint[1];
|
|
1634
|
+
});
|
|
1635
|
+
if (index === -1)
|
|
1636
|
+
newArray.push(point);
|
|
1637
|
+
});
|
|
1638
|
+
return newArray;
|
|
1639
|
+
};
|
|
1640
|
+
const getExtendPoint = (source, target, extendDistance) => {
|
|
1641
|
+
const distance = distanceBetweenPointAndPoint(...source, ...target);
|
|
1642
|
+
const sin = (target[1] - source[1]) / distance;
|
|
1643
|
+
const cos = (target[0] - source[0]) / distance;
|
|
1644
|
+
return [source[0] + extendDistance * cos, source[1] + extendDistance * sin];
|
|
1645
|
+
};
|
|
1646
|
+
// quadratic Bezier to cubic Bezier
|
|
1647
|
+
const Q2C = (points) => {
|
|
1648
|
+
const result = [];
|
|
1649
|
+
const numSegments = points.length / 3;
|
|
1650
|
+
for (let i = 0; i < numSegments; i++) {
|
|
1651
|
+
const start = points[i];
|
|
1652
|
+
const qControl = points[i + 1];
|
|
1653
|
+
const end = points[i + 2];
|
|
1654
|
+
const startDistance = distanceBetweenPointAndPoint(...start, ...qControl);
|
|
1655
|
+
const endDistance = distanceBetweenPointAndPoint(...end, ...qControl);
|
|
1656
|
+
const cControl1 = getExtendPoint(start, qControl, (startDistance * 2) / 3);
|
|
1657
|
+
const cControl2 = getExtendPoint(end, qControl, (endDistance * 2) / 3);
|
|
1658
|
+
result.push(start, cControl1, cControl2, end);
|
|
1659
|
+
}
|
|
1660
|
+
return result;
|
|
1661
|
+
};
|
|
1662
|
+
const getVectorByConnection = (boundElement, connection) => {
|
|
1663
|
+
const rectangle = getRectangleByPoints(boundElement.points);
|
|
1664
|
+
const shape = getShape(boundElement);
|
|
1665
|
+
const engine = getEngine(shape);
|
|
1666
|
+
let vector = [0, 0];
|
|
1667
|
+
const direction = getDirectionByPointOfRectangle(connection);
|
|
1668
|
+
if (direction) {
|
|
1669
|
+
const factor = getDirectionFactor(direction);
|
|
1670
|
+
return [factor.x, factor.y];
|
|
1671
|
+
}
|
|
1672
|
+
if (engine.getEdgeByConnectionPoint) {
|
|
1673
|
+
const edge = engine.getEdgeByConnectionPoint(rectangle, connection);
|
|
1674
|
+
if (edge) {
|
|
1675
|
+
const lineVector = [edge[1][0] - edge[0][0], edge[1][1] - edge[0][1]];
|
|
1676
|
+
return rotateVectorAnti90(lineVector);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
if (engine.getTangentVectorByConnectionPoint) {
|
|
1680
|
+
const lineVector = engine.getTangentVectorByConnectionPoint(rectangle, connection);
|
|
1681
|
+
if (lineVector) {
|
|
1682
|
+
return rotateVectorAnti90(lineVector);
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
return vector;
|
|
1686
|
+
};
|
|
677
1687
|
|
|
678
1688
|
const getSelectedDrawElements = (board) => {
|
|
679
1689
|
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isDrawElement(value));
|
|
@@ -687,6 +1697,117 @@ const getSelectedLineElements = (board) => {
|
|
|
687
1697
|
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isLine(value));
|
|
688
1698
|
return selectedElements;
|
|
689
1699
|
};
|
|
1700
|
+
const getSelectedImageElements = (board) => {
|
|
1701
|
+
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isImage(value));
|
|
1702
|
+
return selectedElements;
|
|
1703
|
+
};
|
|
1704
|
+
|
|
1705
|
+
var LineMarkerType;
|
|
1706
|
+
(function (LineMarkerType) {
|
|
1707
|
+
LineMarkerType["arrow"] = "arrow";
|
|
1708
|
+
LineMarkerType["none"] = "none";
|
|
1709
|
+
LineMarkerType["openTriangle"] = "open-triangle";
|
|
1710
|
+
LineMarkerType["solidTriangle"] = "solid-triangle";
|
|
1711
|
+
LineMarkerType["sharpArrow"] = "sharp-arrow";
|
|
1712
|
+
LineMarkerType["oneSideUp"] = "one-side-up";
|
|
1713
|
+
LineMarkerType["oneSideDown"] = "one-side-down";
|
|
1714
|
+
LineMarkerType["hollowTriangle"] = "hollow-triangle";
|
|
1715
|
+
LineMarkerType["singleSlash"] = "single-slash";
|
|
1716
|
+
})(LineMarkerType || (LineMarkerType = {}));
|
|
1717
|
+
var LineShape;
|
|
1718
|
+
(function (LineShape) {
|
|
1719
|
+
LineShape["straight"] = "straight";
|
|
1720
|
+
LineShape["curve"] = "curve";
|
|
1721
|
+
LineShape["elbow"] = "elbow";
|
|
1722
|
+
})(LineShape || (LineShape = {}));
|
|
1723
|
+
var LineHandleKey;
|
|
1724
|
+
(function (LineHandleKey) {
|
|
1725
|
+
LineHandleKey["source"] = "source";
|
|
1726
|
+
LineHandleKey["target"] = "target";
|
|
1727
|
+
})(LineHandleKey || (LineHandleKey = {}));
|
|
1728
|
+
const PlaitLine = {
|
|
1729
|
+
getTextEditors(element) {
|
|
1730
|
+
const component = PlaitElement.getComponent(element);
|
|
1731
|
+
if (component) {
|
|
1732
|
+
const manage = component.textManages.find(manage => manage.isEditing);
|
|
1733
|
+
if (manage) {
|
|
1734
|
+
return [manage.componentRef.instance.editor];
|
|
1735
|
+
}
|
|
1736
|
+
else {
|
|
1737
|
+
return component.textManages.map(manage => manage.componentRef.instance.editor);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
throw new Error('can not get correctly component in get text editor');
|
|
1741
|
+
},
|
|
1742
|
+
isSourceMarkOrTargetMark(line, markType, handleKey) {
|
|
1743
|
+
if (handleKey === LineHandleKey.source) {
|
|
1744
|
+
return line.source.marker === markType;
|
|
1745
|
+
}
|
|
1746
|
+
else {
|
|
1747
|
+
return line.target.marker === markType;
|
|
1748
|
+
}
|
|
1749
|
+
},
|
|
1750
|
+
isSourceMark(line, markType) {
|
|
1751
|
+
return PlaitLine.isSourceMarkOrTargetMark(line, markType, LineHandleKey.source);
|
|
1752
|
+
},
|
|
1753
|
+
isTargetMark(line, markType) {
|
|
1754
|
+
return PlaitLine.isSourceMarkOrTargetMark(line, markType, LineHandleKey.target);
|
|
1755
|
+
},
|
|
1756
|
+
isBoundElementOfSource(line, element) {
|
|
1757
|
+
return line.source.boundId === element.id;
|
|
1758
|
+
},
|
|
1759
|
+
isBoundElementOfTarget(line, element) {
|
|
1760
|
+
return line.target.boundId === element.id;
|
|
1761
|
+
},
|
|
1762
|
+
getPoints(board, line) {
|
|
1763
|
+
let sourcePoint = line.source.boundId
|
|
1764
|
+
? getConnectionPoint(getElementById(board, line.source.boundId), line.source.connection)
|
|
1765
|
+
: line.points[0];
|
|
1766
|
+
let targetPoint = line.target.boundId
|
|
1767
|
+
? getConnectionPoint(getElementById(board, line.target.boundId), line.target.connection)
|
|
1768
|
+
: line.points[line.points.length - 1];
|
|
1769
|
+
const restPoints = line.points.length > 2 ? line.points.slice(1, line.points.length - 1) : [];
|
|
1770
|
+
return [sourcePoint, ...restPoints, targetPoint];
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1773
|
+
|
|
1774
|
+
var StrokeStyle;
|
|
1775
|
+
(function (StrokeStyle) {
|
|
1776
|
+
StrokeStyle["solid"] = "solid";
|
|
1777
|
+
StrokeStyle["dashed"] = "dashed";
|
|
1778
|
+
})(StrokeStyle || (StrokeStyle = {}));
|
|
1779
|
+
|
|
1780
|
+
const PlaitDrawElement = {
|
|
1781
|
+
isGeometry: (value) => {
|
|
1782
|
+
return value.type === 'geometry';
|
|
1783
|
+
},
|
|
1784
|
+
isLine: (value) => {
|
|
1785
|
+
return value.type === 'line';
|
|
1786
|
+
},
|
|
1787
|
+
isText: (value) => {
|
|
1788
|
+
return value.type === 'geometry' && value.shape === BasicShapes.text;
|
|
1789
|
+
},
|
|
1790
|
+
isImage: (value) => {
|
|
1791
|
+
return value.type === 'image';
|
|
1792
|
+
},
|
|
1793
|
+
isDrawElement: (value) => {
|
|
1794
|
+
if (PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isLine(value) || PlaitDrawElement.isImage(value)) {
|
|
1795
|
+
return true;
|
|
1796
|
+
}
|
|
1797
|
+
else {
|
|
1798
|
+
return false;
|
|
1799
|
+
}
|
|
1800
|
+
},
|
|
1801
|
+
isShape: (value) => {
|
|
1802
|
+
return PlaitDrawElement.isImage(value) || PlaitDrawElement.isGeometry(value);
|
|
1803
|
+
},
|
|
1804
|
+
isBaseShape: (value) => {
|
|
1805
|
+
return Object.keys(BasicShapes).includes(value.type);
|
|
1806
|
+
},
|
|
1807
|
+
isFlowchart: (value) => {
|
|
1808
|
+
return Object.keys(FlowchartSymbols).includes(value.type);
|
|
1809
|
+
}
|
|
1810
|
+
};
|
|
690
1811
|
|
|
691
1812
|
class GeometryShapeGenerator extends Generator {
|
|
692
1813
|
canDraw(element, data) {
|
|
@@ -695,28 +1816,33 @@ class GeometryShapeGenerator extends Generator {
|
|
|
695
1816
|
baseDraw(element, data) {
|
|
696
1817
|
const rectangle = getRectangleByPoints(element.points);
|
|
697
1818
|
const shape = element.shape;
|
|
698
|
-
if (shape ===
|
|
1819
|
+
if (shape === BasicShapes.text) {
|
|
699
1820
|
return;
|
|
700
1821
|
}
|
|
701
1822
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
702
1823
|
const strokeColor = getStrokeColorByElement(element);
|
|
703
1824
|
const fill = getFillByElement(element);
|
|
704
1825
|
const strokeLineDash = getLineDashByElement(element);
|
|
705
|
-
return drawGeometry(this.board, RectangleClient.inflate(rectangle, -strokeWidth), shape, {
|
|
1826
|
+
return drawGeometry(this.board, RectangleClient.inflate(rectangle, -strokeWidth), shape, {
|
|
1827
|
+
stroke: strokeColor,
|
|
1828
|
+
strokeWidth,
|
|
1829
|
+
fill,
|
|
1830
|
+
strokeLineDash
|
|
1831
|
+
});
|
|
706
1832
|
}
|
|
707
1833
|
}
|
|
708
1834
|
|
|
709
1835
|
const insertGeometry = (board, points, shape) => {
|
|
710
1836
|
let newElement = createGeometryElement(shape, points, '', {
|
|
711
|
-
strokeColor:
|
|
712
|
-
strokeWidth:
|
|
1837
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1838
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
713
1839
|
});
|
|
714
1840
|
Transforms.insertNode(board, newElement, [board.children.length]);
|
|
715
1841
|
clearSelectedElement(board);
|
|
716
1842
|
addSelectedElement(board, newElement);
|
|
717
1843
|
};
|
|
718
1844
|
const insertText = (board, points, text = '文本') => {
|
|
719
|
-
let newElement = createGeometryElement(
|
|
1845
|
+
let newElement = createGeometryElement(BasicShapes.text, points, text);
|
|
720
1846
|
Transforms.insertNode(board, newElement, [board.children.length]);
|
|
721
1847
|
clearSelectedElement(board);
|
|
722
1848
|
addSelectedElement(board, newElement);
|
|
@@ -782,6 +1908,28 @@ const setTextSize = (board, element, textWidth, textHeight) => {
|
|
|
782
1908
|
}
|
|
783
1909
|
};
|
|
784
1910
|
|
|
1911
|
+
const insertImage = (board, imageItem, startPoint) => {
|
|
1912
|
+
const { width, height, url } = imageItem;
|
|
1913
|
+
const host = BOARD_TO_HOST.get(board);
|
|
1914
|
+
const viewportWidth = PlaitBoard.getComponent(board).nativeElement.clientWidth;
|
|
1915
|
+
const viewportHeight = PlaitBoard.getComponent(board).nativeElement.clientHeight;
|
|
1916
|
+
const point = transformPoint(board, toPoint(viewportWidth / 2, viewportHeight / 2, host));
|
|
1917
|
+
const points = startPoint
|
|
1918
|
+
? [startPoint, [startPoint[0] + width, startPoint[1] + height]]
|
|
1919
|
+
: [
|
|
1920
|
+
[point[0] - width / 2, point[1] - height / 2],
|
|
1921
|
+
[point[0] + width / 2, point[1] + height / 2]
|
|
1922
|
+
];
|
|
1923
|
+
const imageElement = {
|
|
1924
|
+
id: idCreator(),
|
|
1925
|
+
type: 'image',
|
|
1926
|
+
points,
|
|
1927
|
+
url
|
|
1928
|
+
};
|
|
1929
|
+
Transforms.insertNode(board, imageElement, [board.children.length]);
|
|
1930
|
+
Transforms.addSelectionWithTemporaryElements(board, [imageElement]);
|
|
1931
|
+
};
|
|
1932
|
+
|
|
785
1933
|
const resizeLine = (board, options, path) => {
|
|
786
1934
|
Transforms.setNode(board, options, path);
|
|
787
1935
|
};
|
|
@@ -812,7 +1960,8 @@ const DrawTransforms = {
|
|
|
812
1960
|
resizeLine,
|
|
813
1961
|
setLineTexts,
|
|
814
1962
|
removeLineText,
|
|
815
|
-
setLineMark
|
|
1963
|
+
setLineMark,
|
|
1964
|
+
insertImage
|
|
816
1965
|
};
|
|
817
1966
|
|
|
818
1967
|
class GeometryComponent extends CommonPluginElement {
|
|
@@ -830,10 +1979,10 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
830
1979
|
getStrokeWidth: () => {
|
|
831
1980
|
const selectedElements = getSelectedElements(this.board);
|
|
832
1981
|
if (selectedElements.length === 1 && !isSelectionMoving(this.board)) {
|
|
833
|
-
return
|
|
1982
|
+
return ACTIVE_STROKE_WIDTH;
|
|
834
1983
|
}
|
|
835
1984
|
else {
|
|
836
|
-
return
|
|
1985
|
+
return ACTIVE_STROKE_WIDTH;
|
|
837
1986
|
}
|
|
838
1987
|
},
|
|
839
1988
|
getStrokeOpacity: () => {
|
|
@@ -896,6 +2045,10 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
896
2045
|
const plugins = this.board.getPluginOptions(WithTextPluginKey).textPlugins;
|
|
897
2046
|
const manage = new TextManage(this.board, this.viewContainerRef, {
|
|
898
2047
|
getRectangle: () => {
|
|
2048
|
+
const getRectangle = getEngine(this.element.shape).getTextRectangle;
|
|
2049
|
+
if (getRectangle) {
|
|
2050
|
+
return getRectangle(this.element);
|
|
2051
|
+
}
|
|
899
2052
|
return getTextRectangle(this.element);
|
|
900
2053
|
},
|
|
901
2054
|
onValueChangeHandle: (textManageRef) => {
|
|
@@ -909,7 +2062,11 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
909
2062
|
}
|
|
910
2063
|
},
|
|
911
2064
|
getMaxWidth: () => {
|
|
912
|
-
|
|
2065
|
+
let width = getTextRectangle(this.element).width;
|
|
2066
|
+
const getRectangle = getEngine(this.element.shape).getTextRectangle;
|
|
2067
|
+
if (getRectangle) {
|
|
2068
|
+
width = getRectangle(this.element).width;
|
|
2069
|
+
}
|
|
913
2070
|
return this.element?.autoSize ? GeometryThreshold.defaultTextMaxWidth : width;
|
|
914
2071
|
},
|
|
915
2072
|
textPlugins: plugins
|
|
@@ -922,15 +2079,16 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
922
2079
|
this.destroy$.next();
|
|
923
2080
|
this.destroy$.complete();
|
|
924
2081
|
}
|
|
925
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.
|
|
926
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.
|
|
2082
|
+
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 }); }
|
|
2083
|
+
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 }); }
|
|
927
2084
|
}
|
|
928
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.
|
|
2085
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GeometryComponent, decorators: [{
|
|
929
2086
|
type: Component,
|
|
930
2087
|
args: [{
|
|
931
2088
|
selector: 'plait-draw-geometry',
|
|
932
2089
|
template: ``,
|
|
933
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
2090
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2091
|
+
standalone: true
|
|
934
2092
|
}]
|
|
935
2093
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
936
2094
|
|
|
@@ -939,21 +2097,17 @@ class LineShapeGenerator extends Generator {
|
|
|
939
2097
|
return true;
|
|
940
2098
|
}
|
|
941
2099
|
baseDraw(element, data) {
|
|
942
|
-
const shape = element.shape;
|
|
943
2100
|
let lineG;
|
|
944
|
-
|
|
945
|
-
case LineShape.elbow:
|
|
946
|
-
case LineShape.straight:
|
|
947
|
-
lineG = drawLine(this.board, element);
|
|
948
|
-
break;
|
|
949
|
-
default:
|
|
950
|
-
break;
|
|
951
|
-
}
|
|
2101
|
+
lineG = drawLine(this.board, element);
|
|
952
2102
|
return lineG;
|
|
953
2103
|
}
|
|
954
2104
|
}
|
|
955
2105
|
|
|
956
2106
|
class LineActiveGenerator extends Generator {
|
|
2107
|
+
constructor() {
|
|
2108
|
+
super(...arguments);
|
|
2109
|
+
this.hasResizeHandle = false;
|
|
2110
|
+
}
|
|
957
2111
|
canDraw(element, data) {
|
|
958
2112
|
if (data.selected) {
|
|
959
2113
|
return true;
|
|
@@ -964,27 +2118,70 @@ class LineActiveGenerator extends Generator {
|
|
|
964
2118
|
}
|
|
965
2119
|
baseDraw(element, data) {
|
|
966
2120
|
const activeG = createG();
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
2121
|
+
if (this.hasResizeHandle) {
|
|
2122
|
+
activeG.classList.add('active');
|
|
2123
|
+
activeG.classList.add('line-handle');
|
|
2124
|
+
const points = PlaitLine.getPoints(this.board, element);
|
|
2125
|
+
points.forEach(point => {
|
|
2126
|
+
const circle = drawCircle(PlaitBoard.getRoughSVG(this.board), point, RESIZE_HANDLE_DIAMETER, {
|
|
2127
|
+
stroke: '#999999',
|
|
2128
|
+
strokeWidth: 1,
|
|
2129
|
+
fill: '#FFF',
|
|
2130
|
+
fillStyle: 'solid'
|
|
2131
|
+
});
|
|
2132
|
+
activeG.appendChild(circle);
|
|
2133
|
+
});
|
|
2134
|
+
getMiddlePoints(this.board, element).forEach(point => {
|
|
2135
|
+
const circle = drawCircle(PlaitBoard.getRoughSVG(this.board), point, RESIZE_HANDLE_DIAMETER, {
|
|
2136
|
+
stroke: '#FFFFFF80',
|
|
2137
|
+
strokeWidth: 1,
|
|
2138
|
+
fill: `${PRIMARY_COLOR}80`,
|
|
2139
|
+
fillStyle: 'solid'
|
|
2140
|
+
});
|
|
2141
|
+
activeG.appendChild(circle);
|
|
2142
|
+
});
|
|
2143
|
+
}
|
|
2144
|
+
else {
|
|
2145
|
+
const points = getLinePoints(this.board, element);
|
|
2146
|
+
const activeRectangle = getRectangleByPoints(points);
|
|
2147
|
+
const strokeG = drawRectangle(this.board, activeRectangle, {
|
|
2148
|
+
stroke: PRIMARY_COLOR,
|
|
2149
|
+
strokeWidth: DefaultGeometryActiveStyle.selectionStrokeWidth
|
|
2150
|
+
});
|
|
2151
|
+
activeG.appendChild(strokeG);
|
|
2152
|
+
}
|
|
985
2153
|
return activeG;
|
|
986
2154
|
}
|
|
987
2155
|
}
|
|
2156
|
+
function getMiddlePoints(board, element) {
|
|
2157
|
+
const result = [];
|
|
2158
|
+
const shape = element.shape;
|
|
2159
|
+
if (shape === LineShape.straight) {
|
|
2160
|
+
const points = PlaitLine.getPoints(board, element);
|
|
2161
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
2162
|
+
result.push([(points[i][0] + points[i + 1][0]) / 2, (points[i][1] + points[i + 1][1]) / 2]);
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
if (shape === LineShape.curve) {
|
|
2166
|
+
const points = PlaitLine.getPoints(board, element);
|
|
2167
|
+
const pointsOnBezier = getCurvePoints(board, element);
|
|
2168
|
+
if (points.length === 2) {
|
|
2169
|
+
const start = 0;
|
|
2170
|
+
const endIndex = pointsOnBezier.length - 1;
|
|
2171
|
+
const middleIndex = Math.round((start + endIndex) / 2);
|
|
2172
|
+
result.push(pointsOnBezier[middleIndex]);
|
|
2173
|
+
}
|
|
2174
|
+
else {
|
|
2175
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
2176
|
+
const startIndex = pointsOnBezier.findIndex(point => point[0] === points[i][0] && point[1] === points[i][1]);
|
|
2177
|
+
const endIndex = pointsOnBezier.findIndex(point => point[0] === points[i + 1][0] && point[1] === points[i + 1][1]);
|
|
2178
|
+
const middleIndex = Math.round((startIndex + endIndex) / 2);
|
|
2179
|
+
result.push(pointsOnBezier[middleIndex]);
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
return result;
|
|
2184
|
+
}
|
|
988
2185
|
|
|
989
2186
|
class LineComponent extends PlaitPluginElementComponent {
|
|
990
2187
|
constructor(viewContainerRef, cdr) {
|
|
@@ -1040,11 +2237,18 @@ class LineComponent extends PlaitPluginElementComponent {
|
|
|
1040
2237
|
this.updateTextRectangle();
|
|
1041
2238
|
return;
|
|
1042
2239
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
2240
|
+
if (!isSelectionMoving(this.board)) {
|
|
2241
|
+
this.activeGenerator.hasResizeHandle = this.hasResizeHandle();
|
|
1045
2242
|
this.activeGenerator.draw(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
1046
2243
|
}
|
|
1047
2244
|
}
|
|
2245
|
+
hasResizeHandle() {
|
|
2246
|
+
const selectedElements = getSelectedElements(this.board);
|
|
2247
|
+
if (PlaitBoard.hasBeenTextEditing(this.board) && PlaitDrawElement.isText(this.element)) {
|
|
2248
|
+
return false;
|
|
2249
|
+
}
|
|
2250
|
+
return selectedElements.length === 1 && !isSelectionMoving(this.board);
|
|
2251
|
+
}
|
|
1048
2252
|
initializeTextManages() {
|
|
1049
2253
|
if (this.element.texts?.length) {
|
|
1050
2254
|
this.element.texts.forEach((text, index) => {
|
|
@@ -1116,15 +2320,16 @@ class LineComponent extends PlaitPluginElementComponent {
|
|
|
1116
2320
|
this.destroy$.next();
|
|
1117
2321
|
this.destroy$.complete();
|
|
1118
2322
|
}
|
|
1119
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.
|
|
1120
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.
|
|
2323
|
+
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 }); }
|
|
2324
|
+
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 }); }
|
|
1121
2325
|
}
|
|
1122
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.
|
|
2326
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LineComponent, decorators: [{
|
|
1123
2327
|
type: Component,
|
|
1124
2328
|
args: [{
|
|
1125
2329
|
selector: 'plait-draw-line',
|
|
1126
2330
|
template: ``,
|
|
1127
|
-
changeDetection: ChangeDetectionStrategy.OnPush
|
|
2331
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2332
|
+
standalone: true
|
|
1128
2333
|
}]
|
|
1129
2334
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
1130
2335
|
|
|
@@ -1164,21 +2369,22 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
1164
2369
|
geometryShapeG?.remove();
|
|
1165
2370
|
geometryShapeG = createG();
|
|
1166
2371
|
const geometryGenerator = new GeometryShapeGenerator(board);
|
|
1167
|
-
const
|
|
2372
|
+
const geometryPointers = getGeometryPointers();
|
|
2373
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1168
2374
|
const dragMode = isGeometryPointer && isDndMode(board);
|
|
1169
2375
|
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1170
2376
|
const pointer = PlaitBoard.getPointer(board);
|
|
1171
2377
|
if (dragMode) {
|
|
1172
2378
|
const points = getDefaultGeometryPoints(pointer, movingPoint);
|
|
1173
|
-
if (pointer ===
|
|
2379
|
+
if (pointer === BasicShapes.text) {
|
|
1174
2380
|
const textG = getTemporaryTextG(movingPoint);
|
|
1175
2381
|
geometryShapeG.appendChild(textG);
|
|
1176
2382
|
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
1177
2383
|
}
|
|
1178
2384
|
else {
|
|
1179
2385
|
const temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1180
|
-
strokeColor:
|
|
1181
|
-
strokeWidth:
|
|
2386
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
2387
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1182
2388
|
});
|
|
1183
2389
|
geometryGenerator.draw(temporaryElement, geometryShapeG);
|
|
1184
2390
|
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
@@ -1188,12 +2394,13 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
1188
2394
|
};
|
|
1189
2395
|
board.pointerUp = (event) => {
|
|
1190
2396
|
const pointer = PlaitBoard.getPointer(board);
|
|
1191
|
-
const
|
|
2397
|
+
const geometryPointers = getGeometryPointers();
|
|
2398
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1192
2399
|
const dragMode = isGeometryPointer && isDndMode(board);
|
|
1193
2400
|
if (dragMode) {
|
|
1194
2401
|
const targetPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1195
2402
|
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
1196
|
-
if (pointer ===
|
|
2403
|
+
if (pointer === BasicShapes.text) {
|
|
1197
2404
|
DrawTransforms.insertText(board, points);
|
|
1198
2405
|
}
|
|
1199
2406
|
else {
|
|
@@ -1208,7 +2415,7 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
1208
2415
|
};
|
|
1209
2416
|
return board;
|
|
1210
2417
|
};
|
|
1211
|
-
const
|
|
2418
|
+
const withGeometryCreateByDrawing = (board) => {
|
|
1212
2419
|
const { pointerDown, pointerMove, pointerUp, keydown, keyup } = board;
|
|
1213
2420
|
let start = null;
|
|
1214
2421
|
let geometryShapeG = null;
|
|
@@ -1223,15 +2430,16 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1223
2430
|
keyup(event);
|
|
1224
2431
|
};
|
|
1225
2432
|
board.pointerDown = (event) => {
|
|
1226
|
-
const
|
|
2433
|
+
const geometryPointers = getGeometryPointers();
|
|
2434
|
+
const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
|
|
1227
2435
|
if (isGeometryPointer && isDrawingMode(board)) {
|
|
1228
2436
|
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1229
2437
|
start = point;
|
|
1230
2438
|
const pointer = PlaitBoard.getPointer(board);
|
|
1231
2439
|
preventTouchMove(board, event, true);
|
|
1232
|
-
if (pointer ===
|
|
2440
|
+
if (pointer === BasicShapes.text) {
|
|
1233
2441
|
const points = getDefaultGeometryPoints(pointer, point);
|
|
1234
|
-
const textElement = createGeometryElement(
|
|
2442
|
+
const textElement = createGeometryElement(BasicShapes.text, points, DefaultTextProperty.text);
|
|
1235
2443
|
Transforms.insertNode(board, textElement, [board.children.length]);
|
|
1236
2444
|
clearSelectedElement(board);
|
|
1237
2445
|
addSelectedElement(board, textElement);
|
|
@@ -1248,11 +2456,11 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1248
2456
|
const drawMode = !!start;
|
|
1249
2457
|
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1250
2458
|
const pointer = PlaitBoard.getPointer(board);
|
|
1251
|
-
if (drawMode && pointer !==
|
|
2459
|
+
if (drawMode && pointer !== BasicShapes.text) {
|
|
1252
2460
|
const points = normalizeShapePoints([start, movingPoint], isShift);
|
|
1253
2461
|
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1254
|
-
strokeColor:
|
|
1255
|
-
strokeWidth:
|
|
2462
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
2463
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1256
2464
|
});
|
|
1257
2465
|
geometryGenerator.draw(temporaryElement, geometryShapeG);
|
|
1258
2466
|
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
@@ -1267,10 +2475,10 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1267
2475
|
if (Math.hypot(width, height) === 0) {
|
|
1268
2476
|
const pointer = PlaitBoard.getPointer(board);
|
|
1269
2477
|
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
1270
|
-
if (pointer !==
|
|
2478
|
+
if (pointer !== BasicShapes.text) {
|
|
1271
2479
|
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1272
|
-
strokeColor:
|
|
1273
|
-
strokeWidth:
|
|
2480
|
+
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
2481
|
+
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1274
2482
|
});
|
|
1275
2483
|
}
|
|
1276
2484
|
}
|
|
@@ -1291,9 +2499,21 @@ const withGeometryCreateByDraw = (board) => {
|
|
|
1291
2499
|
return board;
|
|
1292
2500
|
};
|
|
1293
2501
|
const getDefaultGeometryPoints = (pointer, targetPoint) => {
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
2502
|
+
const defaultProperty = getGeometryDefaultProperty(pointer);
|
|
2503
|
+
return getPointsByCenterPoint(targetPoint, defaultProperty.width, defaultProperty.height);
|
|
2504
|
+
};
|
|
2505
|
+
const getGeometryDefaultProperty = (pointer) => {
|
|
2506
|
+
const isText = pointer === BasicShapes.text;
|
|
2507
|
+
const isFlowChart = getFlowchartPointers().includes(pointer);
|
|
2508
|
+
if (isText) {
|
|
2509
|
+
return DefaultTextProperty;
|
|
2510
|
+
}
|
|
2511
|
+
else if (isFlowChart) {
|
|
2512
|
+
return getDefaultFlowchartProperty(pointer);
|
|
2513
|
+
}
|
|
2514
|
+
else {
|
|
2515
|
+
return DefaultBasicShapeProperty;
|
|
2516
|
+
}
|
|
1297
2517
|
};
|
|
1298
2518
|
const getTemporaryTextG = (movingPoint) => {
|
|
1299
2519
|
const textG = createG();
|
|
@@ -1310,7 +2530,7 @@ const getTemporaryTextG = (movingPoint) => {
|
|
|
1310
2530
|
|
|
1311
2531
|
const buildClipboardData = (board, elements, startPoint) => {
|
|
1312
2532
|
return elements.map(element => {
|
|
1313
|
-
if (PlaitDrawElement.isGeometry(element)) {
|
|
2533
|
+
if (PlaitDrawElement.isGeometry(element) || PlaitDrawElement.isImage(element)) {
|
|
1314
2534
|
const points = element.points.map(point => [point[0] - startPoint[0], point[1] - startPoint[1]]);
|
|
1315
2535
|
return { ...element, points };
|
|
1316
2536
|
}
|
|
@@ -1333,7 +2553,7 @@ const buildClipboardData = (board, elements, startPoint) => {
|
|
|
1333
2553
|
};
|
|
1334
2554
|
const insertClipboardData = (board, elements, startPoint) => {
|
|
1335
2555
|
const lines = elements.filter(value => PlaitDrawElement.isLine(value));
|
|
1336
|
-
const geometries = elements.filter(value => PlaitDrawElement.isGeometry(value));
|
|
2556
|
+
const geometries = elements.filter(value => PlaitDrawElement.isGeometry(value) || PlaitDrawElement.isImage(value));
|
|
1337
2557
|
geometries.forEach(element => {
|
|
1338
2558
|
const sourceLines = [];
|
|
1339
2559
|
const targetLines = [];
|
|
@@ -1357,6 +2577,7 @@ const insertClipboardData = (board, elements, startPoint) => {
|
|
|
1357
2577
|
element.points = element.points.map(point => [startPoint[0] + point[0], startPoint[1] + point[1]]);
|
|
1358
2578
|
Transforms.insertNode(board, element, [board.children.length]);
|
|
1359
2579
|
});
|
|
2580
|
+
Transforms.addSelectionWithTemporaryElements(board, elements);
|
|
1360
2581
|
};
|
|
1361
2582
|
|
|
1362
2583
|
const withDrawFragment = (baseBoard) => {
|
|
@@ -1365,21 +2586,35 @@ const withDrawFragment = (baseBoard) => {
|
|
|
1365
2586
|
board.getDeletedFragment = (data) => {
|
|
1366
2587
|
const drawElements = getSelectedDrawElements(board);
|
|
1367
2588
|
if (drawElements.length) {
|
|
1368
|
-
const lines = getBoardLines(board);
|
|
1369
2589
|
const geometryElements = drawElements.filter(value => PlaitDrawElement.isGeometry(value));
|
|
1370
2590
|
const lineElements = drawElements.filter(value => PlaitDrawElement.isLine(value));
|
|
1371
|
-
const
|
|
1372
|
-
|
|
2591
|
+
const imageElements = drawElements.filter(value => PlaitDrawElement.isImage(value));
|
|
2592
|
+
const boundLineElements = [
|
|
2593
|
+
...getBoundedLineElements(board, geometryElements),
|
|
2594
|
+
...getBoundedLineElements(board, imageElements)
|
|
2595
|
+
].filter(line => !lineElements.includes(line));
|
|
2596
|
+
data.push(...[
|
|
2597
|
+
...geometryElements,
|
|
2598
|
+
...lineElements,
|
|
2599
|
+
...imageElements,
|
|
2600
|
+
...boundLineElements.filter(line => !lineElements.includes(line))
|
|
2601
|
+
]);
|
|
1373
2602
|
}
|
|
1374
2603
|
return getDeletedFragment(data);
|
|
1375
2604
|
};
|
|
1376
|
-
board.setFragment = (data, rectangle) => {
|
|
2605
|
+
board.setFragment = (data, rectangle, type) => {
|
|
1377
2606
|
const targetDrawElements = getSelectedDrawElements(board);
|
|
2607
|
+
let boundLineElements = [];
|
|
1378
2608
|
if (targetDrawElements.length) {
|
|
1379
|
-
|
|
2609
|
+
if (type === 'cut') {
|
|
2610
|
+
const geometryElements = targetDrawElements.filter(value => PlaitDrawElement.isGeometry(value));
|
|
2611
|
+
const lineElements = targetDrawElements.filter(value => PlaitDrawElement.isLine(value));
|
|
2612
|
+
boundLineElements = getBoundedLineElements(board, geometryElements).filter(line => !lineElements.includes(line));
|
|
2613
|
+
}
|
|
2614
|
+
const elements = buildClipboardData(board, [...targetDrawElements, ...boundLineElements], rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
|
|
1380
2615
|
setClipboardData(data, elements);
|
|
1381
2616
|
}
|
|
1382
|
-
setFragment(data, rectangle);
|
|
2617
|
+
setFragment(data, rectangle, type);
|
|
1383
2618
|
};
|
|
1384
2619
|
board.insertFragment = (data, targetPoint) => {
|
|
1385
2620
|
const elements = getDataFromClipboard(data);
|
|
@@ -1399,10 +2634,24 @@ const withDrawFragment = (baseBoard) => {
|
|
|
1399
2634
|
return;
|
|
1400
2635
|
}
|
|
1401
2636
|
}
|
|
2637
|
+
if (data?.files.length) {
|
|
2638
|
+
const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
|
|
2639
|
+
if (acceptImageArray.includes(data?.files[0].type)) {
|
|
2640
|
+
const imageFile = data.files[0];
|
|
2641
|
+
buildImage(board, imageFile, DEFAULT_IMAGE_WIDTH, imageItem => {
|
|
2642
|
+
DrawTransforms.insertImage(board, imageItem, targetPoint);
|
|
2643
|
+
});
|
|
2644
|
+
return;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
1402
2647
|
insertFragment(data, targetPoint);
|
|
1403
2648
|
};
|
|
1404
2649
|
return board;
|
|
1405
2650
|
};
|
|
2651
|
+
const getBoundedLineElements = (board, plaitShapes) => {
|
|
2652
|
+
const lines = getBoardLines(board);
|
|
2653
|
+
return lines.filter(line => plaitShapes.find(shape => PlaitLine.isBoundElementOfSource(line, shape) || PlaitLine.isBoundElementOfTarget(line, shape)));
|
|
2654
|
+
};
|
|
1406
2655
|
|
|
1407
2656
|
const DefaultLineStyle = {
|
|
1408
2657
|
strokeWidth: 2,
|
|
@@ -1420,10 +2669,10 @@ const getHitGeometryResizeHandleRef = (board, element, point) => {
|
|
|
1420
2669
|
const getHitOutlineGeometry = (board, point, offset = 0) => {
|
|
1421
2670
|
let geometry = null;
|
|
1422
2671
|
depthFirstRecursion(board, node => {
|
|
1423
|
-
if (PlaitDrawElement.isGeometry(node)) {
|
|
1424
|
-
const shape = node.shape;
|
|
2672
|
+
if (PlaitDrawElement.isGeometry(node) || PlaitDrawElement.isImage(node)) {
|
|
1425
2673
|
let client = getRectangleByPoints(node.points);
|
|
1426
2674
|
client = RectangleClient.getOutlineRectangle(client, offset);
|
|
2675
|
+
const shape = getShape(node);
|
|
1427
2676
|
const isHit = getEngine(shape).isHit(client, point);
|
|
1428
2677
|
if (isHit) {
|
|
1429
2678
|
geometry = node;
|
|
@@ -1441,7 +2690,8 @@ const withLineCreateByDraw = (board) => {
|
|
|
1441
2690
|
let lineShapeG = null;
|
|
1442
2691
|
let temporaryElement = null;
|
|
1443
2692
|
board.pointerDown = (event) => {
|
|
1444
|
-
const
|
|
2693
|
+
const linePointers = getLinePointers();
|
|
2694
|
+
const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
|
|
1445
2695
|
if (isLinePointer && isDrawingMode(board)) {
|
|
1446
2696
|
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1447
2697
|
start = point;
|
|
@@ -1463,7 +2713,8 @@ const withLineCreateByDraw = (board) => {
|
|
|
1463
2713
|
targetRef.connection = hitElement ? transformPointToConnection(board, movingPoint, hitElement) : undefined;
|
|
1464
2714
|
targetRef.boundId = hitElement ? hitElement.id : undefined;
|
|
1465
2715
|
const lineGenerator = new LineShapeGenerator(board);
|
|
1466
|
-
|
|
2716
|
+
const lineShape = PlaitBoard.getPointer(board);
|
|
2717
|
+
temporaryElement = createLineElement(lineShape, [start, movingPoint], { marker: LineMarkerType.none, connection: sourceRef.connection, boundId: sourceRef?.boundId }, { marker: LineMarkerType.arrow, connection: targetRef.connection, boundId: targetRef?.boundId }, {
|
|
1467
2718
|
strokeColor: DefaultLineStyle.strokeColor,
|
|
1468
2719
|
strokeWidth: DefaultLineStyle.strokeWidth
|
|
1469
2720
|
});
|
|
@@ -1508,12 +2759,12 @@ const withGeometryResize = (board) => {
|
|
|
1508
2759
|
return true;
|
|
1509
2760
|
},
|
|
1510
2761
|
detect: (point) => {
|
|
1511
|
-
const
|
|
1512
|
-
if (
|
|
2762
|
+
const selectedElements = [...getSelectedGeometryElements(board), ...getSelectedImageElements(board)];
|
|
2763
|
+
if (selectedElements.length !== 1 || getSelectedElements(board).length !== 1) {
|
|
1513
2764
|
return null;
|
|
1514
2765
|
}
|
|
1515
|
-
const target =
|
|
1516
|
-
const targetComponent = PlaitElement.getComponent(
|
|
2766
|
+
const target = selectedElements[0];
|
|
2767
|
+
const targetComponent = PlaitElement.getComponent(selectedElements[0]);
|
|
1517
2768
|
if (targetComponent.activeGenerator.hasResizeHandle) {
|
|
1518
2769
|
const handleRef = getHitGeometryResizeHandleRef(board, target, point);
|
|
1519
2770
|
if (handleRef) {
|
|
@@ -1528,27 +2779,34 @@ const withGeometryResize = (board) => {
|
|
|
1528
2779
|
},
|
|
1529
2780
|
onResize: (resizeRef, resizeState) => {
|
|
1530
2781
|
let points = [...resizeRef.element.points];
|
|
2782
|
+
const rectangle = getRectangleByPoints(resizeRef.element.points);
|
|
2783
|
+
const ratio = rectangle.height / rectangle.width;
|
|
1531
2784
|
if (resizeRef.handle === ResizeHandle.nw) {
|
|
1532
2785
|
points = [resizeState.endTransformPoint, resizeRef.element.points[1]];
|
|
1533
2786
|
}
|
|
1534
2787
|
if (resizeRef.handle === ResizeHandle.ne) {
|
|
1535
|
-
points = [
|
|
1536
|
-
[resizeRef.element.points[0][0], resizeState.endTransformPoint[1]],
|
|
1537
|
-
[resizeState.endTransformPoint[0], resizeRef.element.points[1][1]]
|
|
1538
|
-
];
|
|
2788
|
+
points = [resizeState.endTransformPoint, [resizeRef.element.points[0][0], resizeRef.element.points[1][1]]];
|
|
1539
2789
|
}
|
|
1540
2790
|
if (resizeRef.handle === ResizeHandle.se) {
|
|
1541
|
-
points = [resizeRef.element.points[0]
|
|
2791
|
+
points = [resizeState.endTransformPoint, resizeRef.element.points[0]];
|
|
1542
2792
|
}
|
|
1543
2793
|
if (resizeRef.handle === ResizeHandle.sw) {
|
|
1544
|
-
points = [
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
2794
|
+
points = [resizeState.endTransformPoint, [resizeRef.element.points[1][0], resizeRef.element.points[0][1]]];
|
|
2795
|
+
}
|
|
2796
|
+
if (isShift || PlaitDrawElement.isImage(resizeRef.element)) {
|
|
2797
|
+
const rectangle = getRectangleByPoints(points);
|
|
2798
|
+
const factor = points[0][1] > points[1][1] ? 1 : -1;
|
|
2799
|
+
const height = rectangle.width * ratio * factor;
|
|
2800
|
+
points = [[resizeState.endTransformPoint[0], points[1][1] + height], points[1]];
|
|
2801
|
+
}
|
|
2802
|
+
if (PlaitDrawElement.isGeometry(resizeRef.element)) {
|
|
2803
|
+
const { height: textHeight } = PlaitGeometry.getTextManage(resizeRef.element).getSize();
|
|
2804
|
+
DrawTransforms.resizeGeometry(board, points, textHeight, resizeRef.path);
|
|
2805
|
+
}
|
|
2806
|
+
else {
|
|
2807
|
+
points = normalizeShapePoints(points);
|
|
2808
|
+
Transforms.setNode(board, { points }, resizeRef.path);
|
|
1548
2809
|
}
|
|
1549
|
-
points = normalizeShapePoints(points, isShift);
|
|
1550
|
-
const { height: textHeight } = PlaitGeometry.getTextManage(resizeRef.element).getSize();
|
|
1551
|
-
DrawTransforms.resizeGeometry(board, points, textHeight, resizeRef.path);
|
|
1552
2810
|
}
|
|
1553
2811
|
};
|
|
1554
2812
|
withResize(board, options);
|
|
@@ -1559,34 +2817,44 @@ var LineResizeHandle;
|
|
|
1559
2817
|
(function (LineResizeHandle) {
|
|
1560
2818
|
LineResizeHandle["source"] = "source";
|
|
1561
2819
|
LineResizeHandle["target"] = "target";
|
|
2820
|
+
LineResizeHandle["addHandle"] = "addHandle";
|
|
1562
2821
|
})(LineResizeHandle || (LineResizeHandle = {}));
|
|
1563
2822
|
const getHitLineResizeHandleRef = (board, element, point) => {
|
|
1564
|
-
const
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
y: targetPoint[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
1575
|
-
width: RESIZE_HANDLE_DIAMETER,
|
|
1576
|
-
height: RESIZE_HANDLE_DIAMETER
|
|
1577
|
-
};
|
|
1578
|
-
const isHitSourceRectangle = RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), sourceRectangle);
|
|
1579
|
-
const isHitTargetRectangle = RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), targetRectangle);
|
|
1580
|
-
if (isHitSourceRectangle) {
|
|
1581
|
-
return { rectangle: sourceRectangle, handle: LineResizeHandle.source };
|
|
2823
|
+
const points = PlaitLine.getPoints(board, element);
|
|
2824
|
+
const index = getHitPointIndex(points, point);
|
|
2825
|
+
if (index !== -1) {
|
|
2826
|
+
if (index === 0) {
|
|
2827
|
+
return { handle: LineResizeHandle.source, index };
|
|
2828
|
+
}
|
|
2829
|
+
if (index === points.length - 1) {
|
|
2830
|
+
return { handle: LineResizeHandle.target, index };
|
|
2831
|
+
}
|
|
2832
|
+
return { index };
|
|
1582
2833
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
2834
|
+
const middlePoints = getMiddlePoints(board, element);
|
|
2835
|
+
const middleIndex = getHitPointIndex(middlePoints, point);
|
|
2836
|
+
if (middleIndex !== -1) {
|
|
2837
|
+
return { handle: LineResizeHandle.addHandle, index: middleIndex };
|
|
1585
2838
|
}
|
|
1586
2839
|
return undefined;
|
|
1587
2840
|
};
|
|
2841
|
+
function getHitPointIndex(points, movingPoint) {
|
|
2842
|
+
const rectangles = points.map(point => {
|
|
2843
|
+
return {
|
|
2844
|
+
x: point[0] - RESIZE_HANDLE_DIAMETER / 2,
|
|
2845
|
+
y: point[1] - RESIZE_HANDLE_DIAMETER / 2,
|
|
2846
|
+
width: RESIZE_HANDLE_DIAMETER,
|
|
2847
|
+
height: RESIZE_HANDLE_DIAMETER
|
|
2848
|
+
};
|
|
2849
|
+
});
|
|
2850
|
+
const rectangle = rectangles.find(rectangle => {
|
|
2851
|
+
return RectangleClient.isHit(RectangleClient.toRectangleClient([movingPoint, movingPoint]), rectangle);
|
|
2852
|
+
});
|
|
2853
|
+
return rectangle ? rectangles.indexOf(rectangle) : -1;
|
|
2854
|
+
}
|
|
1588
2855
|
|
|
1589
2856
|
const withLineResize = (board) => {
|
|
2857
|
+
let pointIndex = 0;
|
|
1590
2858
|
const options = {
|
|
1591
2859
|
key: 'draw-line',
|
|
1592
2860
|
canResize: () => {
|
|
@@ -1603,6 +2871,7 @@ const withLineResize = (board) => {
|
|
|
1603
2871
|
element: value,
|
|
1604
2872
|
handle: handleRef.handle
|
|
1605
2873
|
};
|
|
2874
|
+
pointIndex = handleRef.index;
|
|
1606
2875
|
}
|
|
1607
2876
|
});
|
|
1608
2877
|
return result;
|
|
@@ -1614,17 +2883,23 @@ const withLineResize = (board) => {
|
|
|
1614
2883
|
let source = { ...resizeRef.element.source };
|
|
1615
2884
|
let target = { ...resizeRef.element.target };
|
|
1616
2885
|
if (resizeRef.handle === LineResizeHandle.source) {
|
|
1617
|
-
points[
|
|
2886
|
+
points[pointIndex] = resizeState.endTransformPoint;
|
|
1618
2887
|
const hitElement = getHitOutlineGeometry(board, resizeState.endTransformPoint, -4);
|
|
1619
2888
|
source.connection = hitElement ? transformPointToConnection(board, resizeState.endTransformPoint, hitElement) : undefined;
|
|
1620
2889
|
source.boundId = hitElement ? hitElement.id : undefined;
|
|
1621
2890
|
}
|
|
1622
|
-
if (resizeRef.handle === LineResizeHandle.target) {
|
|
1623
|
-
points[
|
|
2891
|
+
else if (resizeRef.handle === LineResizeHandle.target) {
|
|
2892
|
+
points[pointIndex] = resizeState.endTransformPoint;
|
|
1624
2893
|
const hitElement = getHitOutlineGeometry(board, resizeState.endTransformPoint, -4);
|
|
1625
2894
|
target.connection = hitElement ? transformPointToConnection(board, resizeState.endTransformPoint, hitElement) : undefined;
|
|
1626
2895
|
target.boundId = hitElement ? hitElement.id : undefined;
|
|
1627
2896
|
}
|
|
2897
|
+
else if (resizeRef.handle === LineResizeHandle.addHandle) {
|
|
2898
|
+
points.splice(pointIndex + 1, 0, resizeState.endTransformPoint);
|
|
2899
|
+
}
|
|
2900
|
+
else {
|
|
2901
|
+
points[pointIndex] = resizeState.endTransformPoint;
|
|
2902
|
+
}
|
|
1628
2903
|
DrawTransforms.resizeLine(board, { points, source, target }, resizeRef.path);
|
|
1629
2904
|
}
|
|
1630
2905
|
};
|
|
@@ -1637,9 +2912,14 @@ const withLineBoundReaction = (board) => {
|
|
|
1637
2912
|
let boundShapeG = null;
|
|
1638
2913
|
board.pointerMove = (event) => {
|
|
1639
2914
|
boundShapeG?.remove();
|
|
1640
|
-
const
|
|
2915
|
+
const linePointers = Object.keys(LineShape);
|
|
2916
|
+
const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
|
|
1641
2917
|
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
1642
|
-
const isLineResizing = isResizingByCondition(board,
|
|
2918
|
+
const isLineResizing = isResizingByCondition(board, resizeRef => {
|
|
2919
|
+
const { element, handle } = resizeRef;
|
|
2920
|
+
const isSourceOrTarget = handle === LineResizeHandle.target || handle === LineResizeHandle.source;
|
|
2921
|
+
return PlaitDrawElement.isLine(element) && isSourceOrTarget;
|
|
2922
|
+
});
|
|
1643
2923
|
if (isLinePointer || isLineResizing) {
|
|
1644
2924
|
const hitElement = getHitOutlineGeometry(board, movingPoint, -4);
|
|
1645
2925
|
if (hitElement) {
|
|
@@ -1717,8 +2997,74 @@ function editHandle(board, element, manageIndex, isFirstEdit = false) {
|
|
|
1717
2997
|
});
|
|
1718
2998
|
}
|
|
1719
2999
|
|
|
3000
|
+
class ImageComponent extends CommonPluginElement {
|
|
3001
|
+
get activeGenerator() {
|
|
3002
|
+
return this.imageGenerator.componentRef.instance.activeGenerator;
|
|
3003
|
+
}
|
|
3004
|
+
constructor(viewContainerRef, cdr) {
|
|
3005
|
+
super(cdr);
|
|
3006
|
+
this.viewContainerRef = viewContainerRef;
|
|
3007
|
+
this.cdr = cdr;
|
|
3008
|
+
this.destroy$ = new Subject();
|
|
3009
|
+
}
|
|
3010
|
+
initializeGenerator() {
|
|
3011
|
+
this.imageGenerator = new ImageGenerator(this.board, {
|
|
3012
|
+
getRectangle: (element) => {
|
|
3013
|
+
return {
|
|
3014
|
+
x: element.points[0][0],
|
|
3015
|
+
y: element.points[0][1],
|
|
3016
|
+
width: element.points[1][0] - element.points[0][0],
|
|
3017
|
+
height: element.points[1][1] - element.points[0][1]
|
|
3018
|
+
};
|
|
3019
|
+
},
|
|
3020
|
+
getImageItem: element => {
|
|
3021
|
+
return {
|
|
3022
|
+
url: element.url,
|
|
3023
|
+
width: element.points[1][0] - element.points[0][0],
|
|
3024
|
+
height: element.points[1][1] - element.points[0][1]
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
});
|
|
3028
|
+
}
|
|
3029
|
+
ngOnInit() {
|
|
3030
|
+
super.ngOnInit();
|
|
3031
|
+
this.initializeGenerator();
|
|
3032
|
+
this.imageGenerator.draw(this.element, this.g, this.viewContainerRef);
|
|
3033
|
+
}
|
|
3034
|
+
onContextChanged(value, previous) {
|
|
3035
|
+
if (value.element !== previous.element) {
|
|
3036
|
+
this.imageGenerator.updateImage(this.g, previous.element, value.element);
|
|
3037
|
+
this.imageGenerator.componentRef.instance.isFocus = this.selected;
|
|
3038
|
+
}
|
|
3039
|
+
else {
|
|
3040
|
+
const hasSameSelected = value.selected === previous.selected;
|
|
3041
|
+
const hasSameHandleState = this.activeGenerator.options.hasResizeHandle() === this.activeGenerator.hasResizeHandle;
|
|
3042
|
+
if (!hasSameSelected || !hasSameHandleState) {
|
|
3043
|
+
this.imageGenerator.componentRef.instance.isFocus = this.selected;
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
ngOnDestroy() {
|
|
3048
|
+
super.ngOnDestroy();
|
|
3049
|
+
this.destroy$.next();
|
|
3050
|
+
this.destroy$.complete();
|
|
3051
|
+
this.imageGenerator.destroy();
|
|
3052
|
+
}
|
|
3053
|
+
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 }); }
|
|
3054
|
+
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 }); }
|
|
3055
|
+
}
|
|
3056
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ImageComponent, decorators: [{
|
|
3057
|
+
type: Component,
|
|
3058
|
+
args: [{
|
|
3059
|
+
selector: 'plait-draw-geometry',
|
|
3060
|
+
template: ``,
|
|
3061
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3062
|
+
standalone: true
|
|
3063
|
+
}]
|
|
3064
|
+
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
3065
|
+
|
|
1720
3066
|
const withDraw = (board) => {
|
|
1721
|
-
const { drawElement, getRectangle, isHitSelection, isMovable,
|
|
3067
|
+
const { drawElement, getRectangle, isHitSelection, isMovable, isAlign } = board;
|
|
1722
3068
|
board.drawElement = (context) => {
|
|
1723
3069
|
if (PlaitDrawElement.isGeometry(context.element)) {
|
|
1724
3070
|
return GeometryComponent;
|
|
@@ -1726,6 +3072,9 @@ const withDraw = (board) => {
|
|
|
1726
3072
|
else if (PlaitDrawElement.isLine(context.element)) {
|
|
1727
3073
|
return LineComponent;
|
|
1728
3074
|
}
|
|
3075
|
+
else if (PlaitDrawElement.isImage(context.element)) {
|
|
3076
|
+
return ImageComponent;
|
|
3077
|
+
}
|
|
1729
3078
|
return drawElement(context);
|
|
1730
3079
|
};
|
|
1731
3080
|
board.getRectangle = (element) => {
|
|
@@ -1733,9 +3082,11 @@ const withDraw = (board) => {
|
|
|
1733
3082
|
return getRectangleByPoints(element.points);
|
|
1734
3083
|
}
|
|
1735
3084
|
if (PlaitDrawElement.isLine(element)) {
|
|
1736
|
-
const
|
|
1737
|
-
|
|
1738
|
-
|
|
3085
|
+
const points = getLinePoints(board, element);
|
|
3086
|
+
return getRectangleByPoints(points);
|
|
3087
|
+
}
|
|
3088
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
3089
|
+
return getRectangleByPoints(element.points);
|
|
1739
3090
|
}
|
|
1740
3091
|
return getRectangle(element);
|
|
1741
3092
|
};
|
|
@@ -1749,6 +3100,11 @@ const withDraw = (board) => {
|
|
|
1749
3100
|
}
|
|
1750
3101
|
return RectangleClient.isHit(rangeRectangle, client);
|
|
1751
3102
|
}
|
|
3103
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
3104
|
+
const client = getRectangleByPoints(element.points);
|
|
3105
|
+
const rangeRectangle = RectangleClient.toRectangleClient([range.anchor, range.focus]);
|
|
3106
|
+
return RectangleClient.isHit(rangeRectangle, client);
|
|
3107
|
+
}
|
|
1752
3108
|
if (PlaitDrawElement.isLine(element)) {
|
|
1753
3109
|
const points = getLinePoints(board, element);
|
|
1754
3110
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
@@ -1767,17 +3123,34 @@ const withDraw = (board) => {
|
|
|
1767
3123
|
if (PlaitDrawElement.isGeometry(element)) {
|
|
1768
3124
|
return true;
|
|
1769
3125
|
}
|
|
3126
|
+
if (PlaitDrawElement.isImage(element)) {
|
|
3127
|
+
return true;
|
|
3128
|
+
}
|
|
1770
3129
|
if (PlaitDrawElement.isLine(element)) {
|
|
1771
|
-
|
|
3130
|
+
const selectedElements = getSelectedElements(board);
|
|
3131
|
+
const isSelected = (boundId) => {
|
|
3132
|
+
return !!selectedElements.find(value => value.id === boundId);
|
|
3133
|
+
};
|
|
3134
|
+
if ((element.source.boundId && !isSelected(element.source.boundId)) ||
|
|
3135
|
+
(element.target.boundId && !isSelected(element.target.boundId))) {
|
|
3136
|
+
return false;
|
|
3137
|
+
}
|
|
3138
|
+
return true;
|
|
1772
3139
|
}
|
|
1773
3140
|
return isMovable(element);
|
|
1774
3141
|
};
|
|
1775
|
-
|
|
3142
|
+
board.isAlign = (element) => {
|
|
3143
|
+
if (PlaitDrawElement.isGeometry(element) || PlaitDrawElement.isImage(element)) {
|
|
3144
|
+
return true;
|
|
3145
|
+
}
|
|
3146
|
+
return isAlign(element);
|
|
3147
|
+
};
|
|
3148
|
+
return withLineText(withLineBoundReaction(withLineResize(withGeometryResize(withLineCreateByDraw(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board)))))))));
|
|
1776
3149
|
};
|
|
1777
3150
|
|
|
1778
3151
|
/**
|
|
1779
3152
|
* Generated bundle index. Do not edit.
|
|
1780
3153
|
*/
|
|
1781
3154
|
|
|
1782
|
-
export {
|
|
3155
|
+
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, 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, isHitLineText, isHitPolyLine, removeDuplicatePoints, transformOpsToPoints, transformPointToConnection, withDraw };
|
|
1783
3156
|
//# sourceMappingURL=plait-draw.mjs.map
|