@plait/draw 0.31.0 → 0.33.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 +1 -0
- package/constants/index.d.ts +1 -0
- package/constants/line.d.ts +1 -0
- package/constants/theme.d.ts +26 -0
- package/esm2022/constants/geometry.mjs +2 -1
- package/esm2022/constants/index.mjs +2 -1
- package/esm2022/constants/line.mjs +2 -1
- package/esm2022/constants/theme.mjs +28 -0
- package/esm2022/generators/auto-complete.generator.mjs +44 -0
- package/esm2022/generators/geometry-shape.generator.mjs +4 -4
- package/esm2022/generators/line-active.generator.mjs +2 -2
- package/esm2022/generators/line.generator.mjs +2 -2
- package/esm2022/geometry.component.mjs +14 -8
- package/esm2022/image.component.mjs +2 -2
- package/esm2022/interfaces/index.mjs +3 -3
- package/esm2022/line.component.mjs +10 -9
- package/esm2022/plugins/with-auto-complete-reaction.mjs +35 -0
- package/esm2022/plugins/with-auto-complete.mjs +61 -0
- package/esm2022/plugins/with-draw.mjs +10 -6
- package/esm2022/plugins/with-geometry-create.mjs +3 -6
- package/esm2022/plugins/with-line-create.mjs +9 -24
- package/esm2022/plugins/with-line-resize.mjs +7 -16
- package/esm2022/transforms/geometry.mjs +6 -3
- package/esm2022/transforms/index.mjs +4 -3
- package/esm2022/utils/geometry.mjs +24 -9
- package/esm2022/utils/hit.mjs +22 -8
- package/esm2022/utils/line-arrow.mjs +22 -17
- package/esm2022/utils/line.mjs +42 -18
- package/esm2022/utils/style/stroke.mjs +10 -5
- package/fesm2022/plait-draw.mjs +355 -148
- package/fesm2022/plait-draw.mjs.map +1 -1
- package/generators/auto-complete.generator.d.ts +13 -0
- package/generators/geometry-shape.generator.d.ts +1 -1
- package/generators/line-active.generator.d.ts +1 -1
- package/generators/line.generator.d.ts +1 -1
- package/geometry.component.d.ts +2 -0
- package/package.json +1 -1
- package/plugins/with-auto-complete-reaction.d.ts +2 -0
- package/plugins/with-auto-complete.d.ts +7 -0
- package/transforms/geometry.d.ts +2 -1
- package/transforms/index.d.ts +1 -0
- package/utils/clipboard.d.ts +1 -1
- package/utils/geometry.d.ts +6 -2
- package/utils/hit.d.ts +2 -0
- package/utils/line.d.ts +2 -1
- package/utils/style/stroke.d.ts +3 -2
package/fesm2022/plait-draw.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PlaitElement, ACTIVE_STROKE_WIDTH, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Point, BOARD_TO_HOST, transformPoint, toPoint, idCreator, createG, BoardTransforms, PlaitPointerType, preventTouchMove, createForeignObject, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, distanceBetweenPointAndSegment, arrowPoints, createPath, drawLinearPath, rotate, getElementById,
|
|
2
|
-
import { getRectangleByPoints, Generator, normalizeShapePoints, isDndMode, isDrawingMode, getFactorByPoints, getDirectionByVector, getOppositeDirection, getDirectionFactor, DEFAULT_ROUTE_MARGIN, reduceRouteMargin, getNextPoint, generateElbowLineRoute, getPoints, removeDuplicatePoints, getPointByVector, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90, TRANSPARENT, CommonPluginElement, ActiveGenerator, WithTextPluginKey,
|
|
1
|
+
import { PlaitElement, ACTIVE_STROKE_WIDTH, ThemeColorMode, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Point, BOARD_TO_HOST, transformPoint, toPoint, idCreator, createG, BoardTransforms, PlaitPointerType, preventTouchMove, createForeignObject, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, distanceBetweenPointAndSegment, arrowPoints, createPath, drawLinearPath, distanceBetweenPointAndPoint, rotate, depthFirstRecursion, getIsRecursionFunc, getElementById, Direction, catmullRomFitting, distanceBetweenPointAndSegments, createMask, createRect, findElements, getSelectedElements, isPolylineHitRectangle, isSelectionMoving, PlaitPluginElementComponent, setClipboardData, getDataFromClipboard, getHitElementByPoint, temporaryDisableSelection } from '@plait/core';
|
|
2
|
+
import { getRectangleByPoints, Generator, normalizeShapePoints, isDndMode, isDrawingMode, RESIZE_HANDLE_DIAMETER, getExtendPoint, getFactorByPoints, getRectangleResizeHandleRefs, getDirectionByVector, getOppositeDirection, getDirectionFactor, DEFAULT_ROUTE_MARGIN, reduceRouteMargin, getNextPoint, generateElbowLineRoute, getPoints, removeDuplicatePoints, getPointByVector, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90, TRANSPARENT, CommonPluginElement, ActiveGenerator, WithTextPluginKey, PRIMARY_COLOR, isVirtualKey, isDelete, isSpaceHotkey, acceptImageTypes, getElementOfFocusedImage, buildImage, ResizeHandle, withResize, isResizingByCondition, getRatioByPoint, ImageGenerator } from '@plait/common';
|
|
3
3
|
import { AlignEditor, Alignment, DEFAULT_FONT_SIZE, buildText, TextManage, getTextFromClipboard, getTextSize } from '@plait/text';
|
|
4
4
|
import { isKeyHotkey } from 'is-hotkey';
|
|
5
5
|
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
@@ -122,6 +122,7 @@ const DefaultFlowchartPropertyMap = {
|
|
|
122
122
|
[FlowchartSymbols.delay]: DefaultFlowchartProperty,
|
|
123
123
|
[FlowchartSymbols.storedData]: DefaultFlowchartProperty
|
|
124
124
|
};
|
|
125
|
+
const REACTION_MARGIN = -4;
|
|
125
126
|
|
|
126
127
|
const getGeometryPointers = () => {
|
|
127
128
|
return [...Object.keys(BasicShapes), ...Object.keys(FlowchartSymbols)];
|
|
@@ -138,6 +139,33 @@ const getLinePointers = () => {
|
|
|
138
139
|
|
|
139
140
|
const DEFAULT_IMAGE_WIDTH = 1000;
|
|
140
141
|
|
|
142
|
+
const DrawThemeColors = {
|
|
143
|
+
[ThemeColorMode.default]: {
|
|
144
|
+
strokeColor: '#333333',
|
|
145
|
+
fill: '#FFFFFF'
|
|
146
|
+
},
|
|
147
|
+
[ThemeColorMode.colorful]: {
|
|
148
|
+
strokeColor: '#06ADBF',
|
|
149
|
+
fill: '#CDEFF2'
|
|
150
|
+
},
|
|
151
|
+
[ThemeColorMode.soft]: {
|
|
152
|
+
strokeColor: '#6D89C1',
|
|
153
|
+
fill: '#DADFEB'
|
|
154
|
+
},
|
|
155
|
+
[ThemeColorMode.retro]: {
|
|
156
|
+
strokeColor: '#E9C358',
|
|
157
|
+
fill: '#F6EDCF'
|
|
158
|
+
},
|
|
159
|
+
[ThemeColorMode.dark]: {
|
|
160
|
+
strokeColor: '#FFFFFF',
|
|
161
|
+
fill: '#434343'
|
|
162
|
+
},
|
|
163
|
+
[ThemeColorMode.starry]: {
|
|
164
|
+
strokeColor: '#42ABE5',
|
|
165
|
+
fill: '#163F5A'
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
141
169
|
const getStrokeWidthByElement = (element) => {
|
|
142
170
|
if (PlaitDrawElement.isText(element)) {
|
|
143
171
|
return 0;
|
|
@@ -145,12 +173,16 @@ const getStrokeWidthByElement = (element) => {
|
|
|
145
173
|
const strokeWidth = element.strokeWidth || DefaultGeometryStyle.strokeWidth;
|
|
146
174
|
return strokeWidth;
|
|
147
175
|
};
|
|
148
|
-
const getStrokeColorByElement = (element) => {
|
|
149
|
-
const
|
|
176
|
+
const getStrokeColorByElement = (board, element) => {
|
|
177
|
+
const defaultColor = getDrawDefaultStrokeColor(board.theme.themeColorMode);
|
|
178
|
+
const strokeColor = element.strokeColor || defaultColor;
|
|
150
179
|
return strokeColor;
|
|
151
180
|
};
|
|
152
|
-
const getFillByElement = (element) => {
|
|
153
|
-
const
|
|
181
|
+
const getFillByElement = (board, element) => {
|
|
182
|
+
const defaultFill = PlaitDrawElement.isFlowchart(element)
|
|
183
|
+
? getFlowchartDefaultFill(board.theme.themeColorMode)
|
|
184
|
+
: DefaultGeometryStyle.fill;
|
|
185
|
+
const fill = element.fill || defaultFill;
|
|
154
186
|
return fill;
|
|
155
187
|
};
|
|
156
188
|
const getLineDashByElement = (element) => {
|
|
@@ -1172,15 +1204,15 @@ class GeometryShapeGenerator extends Generator {
|
|
|
1172
1204
|
canDraw(element, data) {
|
|
1173
1205
|
return true;
|
|
1174
1206
|
}
|
|
1175
|
-
|
|
1207
|
+
draw(element, data) {
|
|
1176
1208
|
const rectangle = getRectangleByPoints(element.points);
|
|
1177
1209
|
const shape = element.shape;
|
|
1178
1210
|
if (shape === BasicShapes.text) {
|
|
1179
1211
|
return;
|
|
1180
1212
|
}
|
|
1181
1213
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
1182
|
-
const strokeColor = getStrokeColorByElement(element);
|
|
1183
|
-
const fill = getFillByElement(element);
|
|
1214
|
+
const strokeColor = getStrokeColorByElement(this.board, element);
|
|
1215
|
+
const fill = getFillByElement(this.board, element);
|
|
1184
1216
|
const strokeLineDash = getLineDashByElement(element);
|
|
1185
1217
|
return drawGeometry(this.board, RectangleClient.inflate(rectangle, -strokeWidth), shape, {
|
|
1186
1218
|
stroke: strokeColor,
|
|
@@ -1193,7 +1225,6 @@ class GeometryShapeGenerator extends Generator {
|
|
|
1193
1225
|
|
|
1194
1226
|
const insertGeometry = (board, points, shape) => {
|
|
1195
1227
|
let newElement = createGeometryElement(shape, points, '', {
|
|
1196
|
-
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1197
1228
|
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1198
1229
|
});
|
|
1199
1230
|
Transforms.insertNode(board, newElement, [board.children.length]);
|
|
@@ -1216,6 +1247,10 @@ const resizeGeometry = (board, points, textHeight, path) => {
|
|
|
1216
1247
|
}
|
|
1217
1248
|
Transforms.setNode(board, newProperties, path);
|
|
1218
1249
|
};
|
|
1250
|
+
const transformShape = (board, element, shape) => {
|
|
1251
|
+
const path = PlaitBoard.findPath(board, element);
|
|
1252
|
+
Transforms.setNode(board, { shape }, path);
|
|
1253
|
+
};
|
|
1219
1254
|
|
|
1220
1255
|
const normalizePoints = (board, element, width, textHeight) => {
|
|
1221
1256
|
let points = element.points;
|
|
@@ -1320,7 +1355,8 @@ const DrawTransforms = {
|
|
|
1320
1355
|
setLineTexts,
|
|
1321
1356
|
removeLineText,
|
|
1322
1357
|
setLineMark,
|
|
1323
|
-
insertImage
|
|
1358
|
+
insertImage,
|
|
1359
|
+
transformShape
|
|
1324
1360
|
};
|
|
1325
1361
|
|
|
1326
1362
|
const withGeometryCreateByDrag = (board) => {
|
|
@@ -1344,10 +1380,9 @@ const withGeometryCreateByDrag = (board) => {
|
|
|
1344
1380
|
}
|
|
1345
1381
|
else {
|
|
1346
1382
|
const temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1347
|
-
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1348
1383
|
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1349
1384
|
});
|
|
1350
|
-
geometryGenerator.
|
|
1385
|
+
geometryGenerator.processDrawing(temporaryElement, geometryShapeG);
|
|
1351
1386
|
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
1352
1387
|
}
|
|
1353
1388
|
}
|
|
@@ -1420,10 +1455,9 @@ const withGeometryCreateByDrawing = (board) => {
|
|
|
1420
1455
|
if (drawMode && pointer !== BasicShapes.text) {
|
|
1421
1456
|
const points = normalizeShapePoints([start, movingPoint], isShift);
|
|
1422
1457
|
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1423
|
-
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1424
1458
|
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1425
1459
|
});
|
|
1426
|
-
geometryGenerator.
|
|
1460
|
+
geometryGenerator.processDrawing(temporaryElement, geometryShapeG);
|
|
1427
1461
|
PlaitBoard.getElementActiveHost(board).append(geometryShapeG);
|
|
1428
1462
|
}
|
|
1429
1463
|
pointerMove(event);
|
|
@@ -1438,7 +1472,6 @@ const withGeometryCreateByDrawing = (board) => {
|
|
|
1438
1472
|
const points = getDefaultGeometryPoints(pointer, targetPoint);
|
|
1439
1473
|
if (pointer !== BasicShapes.text) {
|
|
1440
1474
|
temporaryElement = createGeometryElement(pointer, points, '', {
|
|
1441
|
-
strokeColor: DefaultBasicShapeProperty.strokeColor,
|
|
1442
1475
|
strokeWidth: DefaultBasicShapeProperty.strokeWidth
|
|
1443
1476
|
});
|
|
1444
1477
|
}
|
|
@@ -1493,6 +1526,7 @@ const DefaultLineStyle = {
|
|
|
1493
1526
|
strokeWidth: 2,
|
|
1494
1527
|
strokeColor: '#000'
|
|
1495
1528
|
};
|
|
1529
|
+
const LINE_TEXT_SPACE = 4;
|
|
1496
1530
|
|
|
1497
1531
|
const createGeometryElement = (shape, points, text, options) => {
|
|
1498
1532
|
let textOptions = {};
|
|
@@ -1501,10 +1535,6 @@ const createGeometryElement = (shape, points, text, options) => {
|
|
|
1501
1535
|
textOptions = { autoSize: true };
|
|
1502
1536
|
alignment = undefined;
|
|
1503
1537
|
}
|
|
1504
|
-
let flowchartOptions = {};
|
|
1505
|
-
if (getFlowchartPointers().includes(shape)) {
|
|
1506
|
-
flowchartOptions = { fill: '#ffffff' };
|
|
1507
|
-
}
|
|
1508
1538
|
return {
|
|
1509
1539
|
id: idCreator(),
|
|
1510
1540
|
type: 'geometry',
|
|
@@ -1515,8 +1545,7 @@ const createGeometryElement = (shape, points, text, options) => {
|
|
|
1515
1545
|
text: buildText(text, alignment),
|
|
1516
1546
|
points,
|
|
1517
1547
|
...textOptions,
|
|
1518
|
-
...options
|
|
1519
|
-
...flowchartOptions
|
|
1548
|
+
...options
|
|
1520
1549
|
};
|
|
1521
1550
|
};
|
|
1522
1551
|
const getPointsByCenterPoint = (point, width, height) => {
|
|
@@ -1648,26 +1677,49 @@ const createDefaultFlowchart = (point) => {
|
|
|
1648
1677
|
], { marker: LineMarkerType.none, connection: [0.5, 1], boundId: processElement2.id }, { marker: LineMarkerType.arrow, connection: [1, 0.5], boundId: endElement.id }, [], lineOptions);
|
|
1649
1678
|
return [startElement, processElement1, decisionElement, processElement2, endElement, line1, line2, line3, line4, line5];
|
|
1650
1679
|
};
|
|
1680
|
+
const getAutoCompletePoints = (element) => {
|
|
1681
|
+
const AutoCompleteMargin = (12 + RESIZE_HANDLE_DIAMETER / 2) * 2;
|
|
1682
|
+
let rectangle = getRectangleByPoints(element.points);
|
|
1683
|
+
rectangle = RectangleClient.inflate(rectangle, AutoCompleteMargin);
|
|
1684
|
+
return RectangleClient.getEdgeCenterPoints(rectangle);
|
|
1685
|
+
};
|
|
1686
|
+
const getHitIndexOfAutoCompletePoint = (movingPoint, points) => {
|
|
1687
|
+
return points.findIndex(point => {
|
|
1688
|
+
const movingRectangle = RectangleClient.toRectangleClient([movingPoint]);
|
|
1689
|
+
let rectangle = RectangleClient.toRectangleClient([point]);
|
|
1690
|
+
rectangle = RectangleClient.inflate(rectangle, RESIZE_HANDLE_DIAMETER);
|
|
1691
|
+
return RectangleClient.isHit(movingRectangle, rectangle);
|
|
1692
|
+
});
|
|
1693
|
+
};
|
|
1694
|
+
const getDrawDefaultStrokeColor = (theme) => {
|
|
1695
|
+
return DrawThemeColors[theme].strokeColor;
|
|
1696
|
+
};
|
|
1697
|
+
const getFlowchartDefaultFill = (theme) => {
|
|
1698
|
+
return DrawThemeColors[theme].fill;
|
|
1699
|
+
};
|
|
1651
1700
|
|
|
1701
|
+
const MAX_LENGTH = 100;
|
|
1652
1702
|
const drawLineArrow = (element, points, options) => {
|
|
1653
1703
|
const arrowG = createG();
|
|
1654
1704
|
if (PlaitLine.isSourceMark(element, LineMarkerType.none) && PlaitLine.isTargetMark(element, LineMarkerType.none)) {
|
|
1655
1705
|
return null;
|
|
1656
1706
|
}
|
|
1707
|
+
const strokeWidth = getStrokeWidthByElement(element);
|
|
1708
|
+
const offset = (strokeWidth * strokeWidth) / 3;
|
|
1657
1709
|
if (!PlaitLine.isSourceMark(element, LineMarkerType.none)) {
|
|
1658
|
-
const source = getExtendPoint(points[0], points[1], 24);
|
|
1710
|
+
const source = getExtendPoint(points[0], points[1], 24 + offset);
|
|
1659
1711
|
const sourceArrow = getArrow(element, { marker: element.source.marker, source, target: points[0], isSource: true }, options);
|
|
1660
1712
|
sourceArrow && arrowG.appendChild(sourceArrow);
|
|
1661
1713
|
}
|
|
1662
1714
|
if (!PlaitLine.isTargetMark(element, LineMarkerType.none)) {
|
|
1663
|
-
const source = getExtendPoint(points[points.length - 1], points[points.length - 2], 24);
|
|
1715
|
+
const source = getExtendPoint(points[points.length - 1], points[points.length - 2], 24 + offset);
|
|
1664
1716
|
const arrow = getArrow(element, { marker: element.target.marker, source, target: points[points.length - 1], isSource: false }, options);
|
|
1665
1717
|
arrow && arrowG.appendChild(arrow);
|
|
1666
1718
|
}
|
|
1667
1719
|
return arrowG;
|
|
1668
1720
|
};
|
|
1669
1721
|
const getArrow = (element, arrowOptions, options) => {
|
|
1670
|
-
const { marker,
|
|
1722
|
+
const { marker, target, source, isSource } = arrowOptions;
|
|
1671
1723
|
let targetArrow;
|
|
1672
1724
|
switch (marker) {
|
|
1673
1725
|
case LineMarkerType.openTriangle: {
|
|
@@ -1707,10 +1759,10 @@ const getArrow = (element, arrowOptions, options) => {
|
|
|
1707
1759
|
};
|
|
1708
1760
|
const drawSharpArrow = (source, target, options) => {
|
|
1709
1761
|
const startPoint = target;
|
|
1710
|
-
const { pointLeft, pointRight } = arrowPoints(source, target,
|
|
1762
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 20);
|
|
1711
1763
|
const g = createG();
|
|
1712
1764
|
const path = createPath();
|
|
1713
|
-
let polylinePath = `M${pointRight[0]},${pointRight[1]}
|
|
1765
|
+
let polylinePath = `M${pointRight[0]},${pointRight[1]}A25,25,20,0,1,${pointLeft[0]},${pointLeft[1]}L${startPoint[0]},${startPoint[1]}Z`;
|
|
1714
1766
|
path.setAttribute('d', polylinePath);
|
|
1715
1767
|
path.setAttribute('stroke', `${options?.stroke}`);
|
|
1716
1768
|
path.setAttribute('stroke-width', `${options?.strokeWidth}`);
|
|
@@ -1722,8 +1774,11 @@ const drawArrow = (element, source, target, options) => {
|
|
|
1722
1774
|
const directionFactor = getFactorByPoints(source, target);
|
|
1723
1775
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
1724
1776
|
const endPoint = [target[0] + (strokeWidth * directionFactor.x) / 2, target[1] + (strokeWidth * directionFactor.y) / 2];
|
|
1725
|
-
const middlePoint = [
|
|
1726
|
-
|
|
1777
|
+
const middlePoint = [
|
|
1778
|
+
endPoint[0] - (8 + strokeWidth / 2) * directionFactor.x,
|
|
1779
|
+
endPoint[1] - (8 + strokeWidth / 2) * directionFactor.y
|
|
1780
|
+
];
|
|
1781
|
+
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 30);
|
|
1727
1782
|
const arrowG = drawLinearPath([pointLeft, endPoint, pointRight, middlePoint], { ...options, fill: options.stroke }, true);
|
|
1728
1783
|
const path = arrowG.querySelector('path');
|
|
1729
1784
|
path.setAttribute('stroke-linejoin', 'round');
|
|
@@ -1731,33 +1786,68 @@ const drawArrow = (element, source, target, options) => {
|
|
|
1731
1786
|
};
|
|
1732
1787
|
const drawSolidTriangle = (source, target, options) => {
|
|
1733
1788
|
const endPoint = target;
|
|
1734
|
-
const { pointLeft, pointRight } = arrowPoints(source, endPoint,
|
|
1789
|
+
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 30);
|
|
1735
1790
|
return drawLinearPath([pointLeft, endPoint, pointRight], { ...options, fill: options.stroke }, true);
|
|
1736
1791
|
};
|
|
1737
1792
|
const drawOpenTriangle = (element, source, target, options) => {
|
|
1738
1793
|
const directionFactor = getFactorByPoints(source, target);
|
|
1739
1794
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
1740
1795
|
const endPoint = [target[0] + (strokeWidth * directionFactor.x) / 2, target[1] + (strokeWidth * directionFactor.y) / 2];
|
|
1741
|
-
const { pointLeft, pointRight } = arrowPoints(source, endPoint,
|
|
1796
|
+
const { pointLeft, pointRight } = arrowPoints(source, endPoint, 40);
|
|
1742
1797
|
return drawLinearPath([pointLeft, endPoint, pointRight], options);
|
|
1743
1798
|
};
|
|
1744
1799
|
const drawOneSideArrow = (source, target, side, options) => {
|
|
1745
|
-
const { pointLeft, pointRight } = arrowPoints(source, target,
|
|
1800
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 40);
|
|
1746
1801
|
return drawLinearPath([side === 'up' ? pointRight : pointLeft, target], options);
|
|
1747
1802
|
};
|
|
1748
1803
|
const drawSingleSlash = (source, target, isSource, options) => {
|
|
1749
|
-
|
|
1750
|
-
const middlePoint = getExtendPoint(target, source,
|
|
1804
|
+
const length = distanceBetweenPointAndPoint(...source, ...target);
|
|
1805
|
+
const middlePoint = getExtendPoint(target, source, length / 2);
|
|
1751
1806
|
const angle = isSource ? 120 : 60;
|
|
1752
1807
|
const start = rotate(...source, ...middlePoint, (angle * Math.PI) / 180);
|
|
1753
1808
|
const end = rotate(...target, ...middlePoint, (angle * Math.PI) / 180);
|
|
1754
1809
|
return drawLinearPath([start, end], options);
|
|
1755
1810
|
};
|
|
1756
1811
|
const drawHollowTriangleArrow = (source, target, options) => {
|
|
1757
|
-
const { pointLeft, pointRight } = arrowPoints(source, target,
|
|
1812
|
+
const { pointLeft, pointRight } = arrowPoints(source, target, 30);
|
|
1758
1813
|
return drawLinearPath([pointLeft, pointRight, target], { ...options, fill: 'white' }, true);
|
|
1759
1814
|
};
|
|
1760
1815
|
|
|
1816
|
+
class LineShapeGenerator extends Generator {
|
|
1817
|
+
canDraw(element, data) {
|
|
1818
|
+
return true;
|
|
1819
|
+
}
|
|
1820
|
+
draw(element, data) {
|
|
1821
|
+
let lineG;
|
|
1822
|
+
lineG = drawLine(this.board, element);
|
|
1823
|
+
return lineG;
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
const getHitGeometryResizeHandleRef = (board, element, point) => {
|
|
1828
|
+
const rectangle = getRectangleByPoints(element.points);
|
|
1829
|
+
const resizeHandleRefs = getRectangleResizeHandleRefs(rectangle, RESIZE_HANDLE_DIAMETER);
|
|
1830
|
+
const result = resizeHandleRefs.find(resizeHandleRef => {
|
|
1831
|
+
return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeHandleRef.rectangle);
|
|
1832
|
+
});
|
|
1833
|
+
return result;
|
|
1834
|
+
};
|
|
1835
|
+
const getHitOutlineGeometry = (board, point, offset = 0) => {
|
|
1836
|
+
let geometry = null;
|
|
1837
|
+
depthFirstRecursion(board, node => {
|
|
1838
|
+
if (PlaitDrawElement.isGeometry(node) || PlaitDrawElement.isImage(node)) {
|
|
1839
|
+
let client = getRectangleByPoints(node.points);
|
|
1840
|
+
client = RectangleClient.getOutlineRectangle(client, offset);
|
|
1841
|
+
const shape = getShape(node);
|
|
1842
|
+
const isHit = getEngine(shape).isHit(client, point);
|
|
1843
|
+
if (isHit) {
|
|
1844
|
+
geometry = node;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
}, getIsRecursionFunc(board), true);
|
|
1848
|
+
return geometry;
|
|
1849
|
+
};
|
|
1850
|
+
|
|
1761
1851
|
const createLineElement = (shape, points, source, target, texts, options) => {
|
|
1762
1852
|
return {
|
|
1763
1853
|
id: idCreator(),
|
|
@@ -1792,7 +1882,7 @@ const getLineHandleRefPair = (board, element) => {
|
|
|
1792
1882
|
let targetPoint = targetBoundElement
|
|
1793
1883
|
? getConnectionPoint(targetBoundElement, element.target.connection)
|
|
1794
1884
|
: element.points[element.points.length - 1];
|
|
1795
|
-
let sourceDirection = getDirectionByVector([targetPoint[0] - sourcePoint[0], targetPoint[1] - sourcePoint[1]]);
|
|
1885
|
+
let sourceDirection = getDirectionByVector([targetPoint[0] - sourcePoint[0], targetPoint[1] - sourcePoint[1]]) || Direction.right;
|
|
1796
1886
|
let targetDirection = getOppositeDirection(sourceDirection);
|
|
1797
1887
|
const sourceFactor = getDirectionFactor(sourceDirection);
|
|
1798
1888
|
const targetFactor = getDirectionFactor(targetDirection);
|
|
@@ -1904,12 +1994,9 @@ const getCurvePoints = (board, element) => {
|
|
|
1904
1994
|
return pointsOnBezierCurves(curvePoints);
|
|
1905
1995
|
}
|
|
1906
1996
|
else {
|
|
1907
|
-
|
|
1908
|
-
const points =
|
|
1909
|
-
|
|
1910
|
-
let bezierPoints = transformOpsToPoints(draw.sets[0].ops);
|
|
1911
|
-
bezierPoints = removeDuplicatePoints(bezierPoints);
|
|
1912
|
-
return pointsOnBezierCurves(bezierPoints);
|
|
1997
|
+
const allPoints = PlaitLine.getPoints(board, element);
|
|
1998
|
+
const points = catmullRomFitting(allPoints);
|
|
1999
|
+
return pointsOnBezierCurves(points);
|
|
1913
2000
|
}
|
|
1914
2001
|
};
|
|
1915
2002
|
const transformOpsToPoints = (ops) => {
|
|
@@ -1951,7 +2038,7 @@ const isHitLineText = (board, element, point) => {
|
|
|
1951
2038
|
};
|
|
1952
2039
|
const drawLine = (board, element) => {
|
|
1953
2040
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
1954
|
-
const strokeColor = getStrokeColorByElement(element);
|
|
2041
|
+
const strokeColor = getStrokeColorByElement(board, element);
|
|
1955
2042
|
const strokeLineDash = getLineDashByElement(element);
|
|
1956
2043
|
const options = { stroke: strokeColor, strokeWidth, strokeLineDash };
|
|
1957
2044
|
const lineG = createG();
|
|
@@ -1986,7 +2073,8 @@ function drawMask(board, element, id) {
|
|
|
1986
2073
|
mask.appendChild(maskFillRect);
|
|
1987
2074
|
const texts = element.texts;
|
|
1988
2075
|
texts.forEach((text, index) => {
|
|
1989
|
-
|
|
2076
|
+
let textRectangle = getLineTextRectangle(board, element, index);
|
|
2077
|
+
textRectangle = RectangleClient.inflate(textRectangle, LINE_TEXT_SPACE * 2);
|
|
1990
2078
|
const rect = createRect(textRectangle, {
|
|
1991
2079
|
fill: 'black'
|
|
1992
2080
|
});
|
|
@@ -1995,6 +2083,7 @@ function drawMask(board, element, id) {
|
|
|
1995
2083
|
//撑开 line
|
|
1996
2084
|
const maskTargetFillRect = createRect(rectangle);
|
|
1997
2085
|
maskTargetFillRect.setAttribute('opacity', '0');
|
|
2086
|
+
maskTargetFillRect.setAttribute('fill', 'none');
|
|
1998
2087
|
return { mask, maskTargetFillRect };
|
|
1999
2088
|
}
|
|
2000
2089
|
const getConnectionPoint = (geometry, connection, direction, delta) => {
|
|
@@ -2042,12 +2131,6 @@ const getBoardLines = (board) => {
|
|
|
2042
2131
|
recursion: (element) => PlaitDrawElement.isDrawElement(element)
|
|
2043
2132
|
});
|
|
2044
2133
|
};
|
|
2045
|
-
const getExtendPoint = (source, target, extendDistance) => {
|
|
2046
|
-
const distance = distanceBetweenPointAndPoint(...source, ...target);
|
|
2047
|
-
const sin = (target[1] - source[1]) / distance;
|
|
2048
|
-
const cos = (target[0] - source[0]) / distance;
|
|
2049
|
-
return [source[0] + extendDistance * cos, source[1] + extendDistance * sin];
|
|
2050
|
-
};
|
|
2051
2134
|
// quadratic Bezier to cubic Bezier
|
|
2052
2135
|
const Q2C = (points) => {
|
|
2053
2136
|
const result = [];
|
|
@@ -2089,6 +2172,33 @@ const getVectorByConnection = (boundElement, connection) => {
|
|
|
2089
2172
|
}
|
|
2090
2173
|
return vector;
|
|
2091
2174
|
};
|
|
2175
|
+
const alignPoints = (basePoint, movingPoint) => {
|
|
2176
|
+
const offset = 3;
|
|
2177
|
+
const newPoint = [...movingPoint];
|
|
2178
|
+
if (Point.isVerticalAlign(newPoint, basePoint, offset)) {
|
|
2179
|
+
newPoint[0] = basePoint[0];
|
|
2180
|
+
}
|
|
2181
|
+
if (Point.isHorizontalAlign(newPoint, basePoint, offset)) {
|
|
2182
|
+
newPoint[1] = basePoint[1];
|
|
2183
|
+
}
|
|
2184
|
+
return newPoint;
|
|
2185
|
+
};
|
|
2186
|
+
const handleLineCreating = (board, lineShape, startPoint, movingPoint, sourceElement, lineShapeG) => {
|
|
2187
|
+
const hitElement = getHitOutlineGeometry(board, movingPoint, REACTION_MARGIN);
|
|
2188
|
+
const targetConnection = hitElement ? transformPointToConnection(board, movingPoint, hitElement) : undefined;
|
|
2189
|
+
const connection = sourceElement ? transformPointToConnection(board, startPoint, sourceElement) : undefined;
|
|
2190
|
+
const targetBoundId = hitElement ? hitElement.id : undefined;
|
|
2191
|
+
const lineGenerator = new LineShapeGenerator(board);
|
|
2192
|
+
const temporaryLineElement = createLineElement(lineShape, [startPoint, movingPoint], { marker: LineMarkerType.none, connection: connection, boundId: sourceElement?.id }, { marker: LineMarkerType.arrow, connection: targetConnection, boundId: targetBoundId }, [], {
|
|
2193
|
+
strokeWidth: DefaultLineStyle.strokeWidth
|
|
2194
|
+
});
|
|
2195
|
+
const linePoints = getLinePoints(board, temporaryLineElement);
|
|
2196
|
+
const otherPoint = linePoints[0];
|
|
2197
|
+
temporaryLineElement.points[1] = alignPoints(otherPoint, movingPoint);
|
|
2198
|
+
lineGenerator.processDrawing(temporaryLineElement, lineShapeG);
|
|
2199
|
+
PlaitBoard.getElementActiveHost(board).append(lineShapeG);
|
|
2200
|
+
return temporaryLineElement;
|
|
2201
|
+
};
|
|
2092
2202
|
|
|
2093
2203
|
const getSelectedDrawElements = (board) => {
|
|
2094
2204
|
const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isDrawElement(value));
|
|
@@ -2107,11 +2217,18 @@ const getSelectedImageElements = (board) => {
|
|
|
2107
2217
|
return selectedElements;
|
|
2108
2218
|
};
|
|
2109
2219
|
|
|
2220
|
+
const isTextExceedingBounds = (geometry) => {
|
|
2221
|
+
const client = getRectangleByPoints(geometry.points);
|
|
2222
|
+
if (geometry.textHeight > client.height) {
|
|
2223
|
+
return true;
|
|
2224
|
+
}
|
|
2225
|
+
return false;
|
|
2226
|
+
};
|
|
2110
2227
|
const isRectangleHitDrawElement = (board, element, selection) => {
|
|
2228
|
+
const rangeRectangle = RectangleClient.toRectangleClient([selection.anchor, selection.focus]);
|
|
2111
2229
|
if (PlaitDrawElement.isGeometry(element)) {
|
|
2112
2230
|
const client = getRectangleByPoints(element.points);
|
|
2113
|
-
|
|
2114
|
-
if (element.textHeight > client.height) {
|
|
2231
|
+
if (isTextExceedingBounds(element)) {
|
|
2115
2232
|
const textClient = getTextRectangle(element);
|
|
2116
2233
|
return RectangleClient.isHit(rangeRectangle, client) || RectangleClient.isHit(rangeRectangle, textClient);
|
|
2117
2234
|
}
|
|
@@ -2119,7 +2236,6 @@ const isRectangleHitDrawElement = (board, element, selection) => {
|
|
|
2119
2236
|
}
|
|
2120
2237
|
if (PlaitDrawElement.isImage(element)) {
|
|
2121
2238
|
const client = getRectangleByPoints(element.points);
|
|
2122
|
-
const rangeRectangle = RectangleClient.toRectangleClient([selection.anchor, selection.focus]);
|
|
2123
2239
|
return RectangleClient.isHit(rangeRectangle, client);
|
|
2124
2240
|
}
|
|
2125
2241
|
if (PlaitDrawElement.isLine(element)) {
|
|
@@ -2127,7 +2243,6 @@ const isRectangleHitDrawElement = (board, element, selection) => {
|
|
|
2127
2243
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
2128
2244
|
const isHitText = isHitLineText(board, element, selection.focus);
|
|
2129
2245
|
const isHit = isHitPolyLine(points, selection.focus, strokeWidth, 3) || isHitText;
|
|
2130
|
-
const rangeRectangle = RectangleClient.toRectangleClient([selection.anchor, selection.focus]);
|
|
2131
2246
|
const isContainPolyLinePoint = points.some(point => {
|
|
2132
2247
|
return RectangleClient.isHit(rangeRectangle, RectangleClient.toRectangleClient([point, point]));
|
|
2133
2248
|
});
|
|
@@ -2138,16 +2253,25 @@ const isRectangleHitDrawElement = (board, element, selection) => {
|
|
|
2138
2253
|
};
|
|
2139
2254
|
const isHitDrawElement = (board, element, point) => {
|
|
2140
2255
|
if (PlaitDrawElement.isGeometry(element)) {
|
|
2141
|
-
const fill = getFillByElement(element);
|
|
2142
|
-
|
|
2256
|
+
const fill = getFillByElement(board, element);
|
|
2257
|
+
// when shape equals text, fill is not allowed
|
|
2258
|
+
if (fill !== DefaultGeometryStyle.fill && fill !== TRANSPARENT && !PlaitDrawElement.isText(element)) {
|
|
2143
2259
|
return isRectangleHitDrawElement(board, element, { anchor: point, focus: point });
|
|
2144
2260
|
}
|
|
2145
2261
|
else {
|
|
2262
|
+
// if shape equals text, only check text rectangle
|
|
2263
|
+
if (PlaitDrawElement.isText(element)) {
|
|
2264
|
+
const textClient = getTextRectangle(element);
|
|
2265
|
+
let isHitText = RectangleClient.isPointInRectangle(textClient, point);
|
|
2266
|
+
return isHitText;
|
|
2267
|
+
}
|
|
2146
2268
|
const strokeWidth = getStrokeWidthByElement(element);
|
|
2147
2269
|
const engine = getEngine(getShape(element));
|
|
2148
2270
|
const corners = engine.getCornerPoints(getRectangleByPoints(element.points));
|
|
2149
2271
|
const isHit = isHitPolyLine(corners, point, strokeWidth, 3);
|
|
2150
|
-
|
|
2272
|
+
const textClient = getTextRectangle(element);
|
|
2273
|
+
let isHitText = RectangleClient.isPointInRectangle(textClient, point);
|
|
2274
|
+
return isHit || isHitText;
|
|
2151
2275
|
}
|
|
2152
2276
|
}
|
|
2153
2277
|
if (PlaitDrawElement.isImage(element) || PlaitDrawElement.isLine(element)) {
|
|
@@ -2256,13 +2380,54 @@ const PlaitDrawElement = {
|
|
|
2256
2380
|
return PlaitDrawElement.isImage(value) || PlaitDrawElement.isGeometry(value);
|
|
2257
2381
|
},
|
|
2258
2382
|
isBaseShape: (value) => {
|
|
2259
|
-
return Object.keys(BasicShapes).includes(value.
|
|
2383
|
+
return Object.keys(BasicShapes).includes(value.shape);
|
|
2260
2384
|
},
|
|
2261
2385
|
isFlowchart: (value) => {
|
|
2262
|
-
return Object.keys(FlowchartSymbols).includes(value.
|
|
2386
|
+
return Object.keys(FlowchartSymbols).includes(value.shape);
|
|
2263
2387
|
}
|
|
2264
2388
|
};
|
|
2265
2389
|
|
|
2390
|
+
class AutoCompleteGenerator extends Generator {
|
|
2391
|
+
constructor(board) {
|
|
2392
|
+
super(board);
|
|
2393
|
+
this.board = board;
|
|
2394
|
+
this.hoverElement = null;
|
|
2395
|
+
}
|
|
2396
|
+
canDraw(element, data) {
|
|
2397
|
+
const selectedElements = getSelectedElements(this.board);
|
|
2398
|
+
if (data.selected && selectedElements.length === 1 && !isSelectionMoving(this.board)) {
|
|
2399
|
+
return true;
|
|
2400
|
+
}
|
|
2401
|
+
else {
|
|
2402
|
+
return false;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
draw(element, data) {
|
|
2406
|
+
this.autoCompleteG = createG();
|
|
2407
|
+
const middlePoints = getAutoCompletePoints(element);
|
|
2408
|
+
middlePoints.forEach((point, index) => {
|
|
2409
|
+
const circle = drawCircle(PlaitBoard.getRoughSVG(this.board), point, RESIZE_HANDLE_DIAMETER, {
|
|
2410
|
+
stroke: 'none',
|
|
2411
|
+
fill: '#6698FF4d',
|
|
2412
|
+
fillStyle: 'solid'
|
|
2413
|
+
});
|
|
2414
|
+
circle.classList.add(`geometry-auto-complete-${index}`);
|
|
2415
|
+
this.autoCompleteG.appendChild(circle);
|
|
2416
|
+
});
|
|
2417
|
+
return this.autoCompleteG;
|
|
2418
|
+
}
|
|
2419
|
+
removeAutoCompleteG(index) {
|
|
2420
|
+
this.hoverElement = this.autoCompleteG.querySelector(`.geometry-auto-complete-${index}`);
|
|
2421
|
+
this.hoverElement.style.visibility = 'hidden';
|
|
2422
|
+
}
|
|
2423
|
+
recoverAutoCompleteG() {
|
|
2424
|
+
if (this.hoverElement) {
|
|
2425
|
+
this.hoverElement.style.visibility = 'visible';
|
|
2426
|
+
this.hoverElement = null;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2266
2431
|
class GeometryComponent extends CommonPluginElement {
|
|
2267
2432
|
get textManage() {
|
|
2268
2433
|
return this.getTextManages()[0];
|
|
@@ -2304,33 +2469,38 @@ class GeometryComponent extends CommonPluginElement {
|
|
|
2304
2469
|
return selectedElements.length === 1 && !isSelectionMoving(this.board);
|
|
2305
2470
|
}
|
|
2306
2471
|
});
|
|
2472
|
+
this.autoCompleteGenerator = new AutoCompleteGenerator(this.board);
|
|
2307
2473
|
this.shapeGenerator = new GeometryShapeGenerator(this.board);
|
|
2308
2474
|
this.initializeTextManage();
|
|
2309
2475
|
}
|
|
2310
2476
|
ngOnInit() {
|
|
2311
2477
|
super.ngOnInit();
|
|
2312
2478
|
this.initializeGenerator();
|
|
2313
|
-
this.shapeGenerator.
|
|
2314
|
-
this.activeGenerator.
|
|
2479
|
+
this.shapeGenerator.processDrawing(this.element, this.g);
|
|
2480
|
+
this.activeGenerator.processDrawing(this.element, this.g, { selected: this.selected });
|
|
2481
|
+
this.autoCompleteGenerator.processDrawing(this.element, this.g, { selected: this.selected });
|
|
2315
2482
|
this.drawText();
|
|
2316
2483
|
}
|
|
2317
2484
|
onContextChanged(value, previous) {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
this.
|
|
2485
|
+
const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
|
|
2486
|
+
if (value.element !== previous.element || isChangeTheme) {
|
|
2487
|
+
this.shapeGenerator.processDrawing(this.element, this.g);
|
|
2488
|
+
this.activeGenerator.processDrawing(this.element, this.g, { selected: this.selected });
|
|
2489
|
+
this.autoCompleteGenerator.processDrawing(this.element, this.g, { selected: this.selected });
|
|
2321
2490
|
this.updateText();
|
|
2322
2491
|
}
|
|
2323
2492
|
else {
|
|
2324
2493
|
const hasSameSelected = value.selected === previous.selected;
|
|
2325
2494
|
const hasSameHandleState = this.activeGenerator.options.hasResizeHandle() === this.activeGenerator.hasResizeHandle;
|
|
2326
2495
|
if (!hasSameSelected || !hasSameHandleState) {
|
|
2327
|
-
this.activeGenerator.
|
|
2496
|
+
this.activeGenerator.processDrawing(this.element, this.g, { selected: this.selected });
|
|
2497
|
+
this.autoCompleteGenerator.processDrawing(this.element, this.g, { selected: this.selected });
|
|
2328
2498
|
}
|
|
2329
2499
|
}
|
|
2330
2500
|
}
|
|
2331
2501
|
editText() {
|
|
2332
2502
|
this.textManage.edit();
|
|
2333
|
-
this.activeGenerator.
|
|
2503
|
+
this.activeGenerator.processDrawing(this.element, this.g, { selected: this.selected });
|
|
2334
2504
|
}
|
|
2335
2505
|
drawText() {
|
|
2336
2506
|
this.textManage.draw(this.element.text);
|
|
@@ -2391,17 +2561,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
2391
2561
|
}]
|
|
2392
2562
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
2393
2563
|
|
|
2394
|
-
class LineShapeGenerator extends Generator {
|
|
2395
|
-
canDraw(element, data) {
|
|
2396
|
-
return true;
|
|
2397
|
-
}
|
|
2398
|
-
baseDraw(element, data) {
|
|
2399
|
-
let lineG;
|
|
2400
|
-
lineG = drawLine(this.board, element);
|
|
2401
|
-
return lineG;
|
|
2402
|
-
}
|
|
2403
|
-
}
|
|
2404
|
-
|
|
2405
2564
|
class LineActiveGenerator extends Generator {
|
|
2406
2565
|
constructor() {
|
|
2407
2566
|
super(...arguments);
|
|
@@ -2415,7 +2574,7 @@ class LineActiveGenerator extends Generator {
|
|
|
2415
2574
|
return false;
|
|
2416
2575
|
}
|
|
2417
2576
|
}
|
|
2418
|
-
|
|
2577
|
+
draw(element, data) {
|
|
2419
2578
|
const activeG = createG();
|
|
2420
2579
|
if (this.hasResizeHandle) {
|
|
2421
2580
|
activeG.classList.add('active');
|
|
@@ -2498,8 +2657,8 @@ class LineComponent extends PlaitPluginElementComponent {
|
|
|
2498
2657
|
}
|
|
2499
2658
|
ngOnInit() {
|
|
2500
2659
|
this.initializeGenerator();
|
|
2501
|
-
this.shapeGenerator.
|
|
2502
|
-
this.activeGenerator.
|
|
2660
|
+
this.shapeGenerator.processDrawing(this.element, this.g);
|
|
2661
|
+
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
2503
2662
|
super.ngOnInit();
|
|
2504
2663
|
this.boundedElements = this.getBoundedElements();
|
|
2505
2664
|
this.drawText();
|
|
@@ -2524,21 +2683,22 @@ class LineComponent extends PlaitPluginElementComponent {
|
|
|
2524
2683
|
const boundedElements = this.getBoundedElements();
|
|
2525
2684
|
const isBoundedElementsChanged = boundedElements.source !== this.boundedElements.source || boundedElements.target !== this.boundedElements.target;
|
|
2526
2685
|
this.boundedElements = boundedElements;
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
this.
|
|
2686
|
+
const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
|
|
2687
|
+
if (value.element !== previous.element || isChangeTheme) {
|
|
2688
|
+
this.shapeGenerator.processDrawing(this.element, this.g);
|
|
2689
|
+
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
2530
2690
|
this.updateText(previous.element.texts, value.element.texts);
|
|
2531
2691
|
this.updateTextRectangle();
|
|
2532
2692
|
}
|
|
2533
2693
|
if (isBoundedElementsChanged) {
|
|
2534
|
-
this.shapeGenerator.
|
|
2535
|
-
this.activeGenerator.
|
|
2694
|
+
this.shapeGenerator.processDrawing(this.element, this.g);
|
|
2695
|
+
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
2536
2696
|
this.updateTextRectangle();
|
|
2537
2697
|
return;
|
|
2538
2698
|
}
|
|
2539
2699
|
if (!isSelectionMoving(this.board)) {
|
|
2540
2700
|
this.activeGenerator.hasResizeHandle = this.hasResizeHandle();
|
|
2541
|
-
this.activeGenerator.
|
|
2701
|
+
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
|
|
2542
2702
|
}
|
|
2543
2703
|
}
|
|
2544
2704
|
hasResizeHandle() {
|
|
@@ -2787,35 +2947,10 @@ const getBoundedLineElements = (board, plaitShapes) => {
|
|
|
2787
2947
|
return lines.filter(line => plaitShapes.find(shape => PlaitLine.isBoundElementOfSource(line, shape) || PlaitLine.isBoundElementOfTarget(line, shape)));
|
|
2788
2948
|
};
|
|
2789
2949
|
|
|
2790
|
-
const getHitGeometryResizeHandleRef = (board, element, point) => {
|
|
2791
|
-
const rectangle = getRectangleByPoints(element.points);
|
|
2792
|
-
const resizeHandleRefs = getRectangleResizeHandleRefs(rectangle, RESIZE_HANDLE_DIAMETER);
|
|
2793
|
-
const result = resizeHandleRefs.find(resizeHandleRef => {
|
|
2794
|
-
return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeHandleRef.rectangle);
|
|
2795
|
-
});
|
|
2796
|
-
return result;
|
|
2797
|
-
};
|
|
2798
|
-
const getHitOutlineGeometry = (board, point, offset = 0) => {
|
|
2799
|
-
let geometry = null;
|
|
2800
|
-
depthFirstRecursion(board, node => {
|
|
2801
|
-
if (PlaitDrawElement.isGeometry(node) || PlaitDrawElement.isImage(node)) {
|
|
2802
|
-
let client = getRectangleByPoints(node.points);
|
|
2803
|
-
client = RectangleClient.getOutlineRectangle(client, offset);
|
|
2804
|
-
const shape = getShape(node);
|
|
2805
|
-
const isHit = getEngine(shape).isHit(client, point);
|
|
2806
|
-
if (isHit) {
|
|
2807
|
-
geometry = node;
|
|
2808
|
-
}
|
|
2809
|
-
}
|
|
2810
|
-
}, getIsRecursionFunc(board), true);
|
|
2811
|
-
return geometry;
|
|
2812
|
-
};
|
|
2813
|
-
|
|
2814
2950
|
const withLineCreateByDraw = (board) => {
|
|
2815
2951
|
const { pointerDown, pointerMove, pointerUp } = board;
|
|
2816
2952
|
let start = null;
|
|
2817
|
-
let
|
|
2818
|
-
let targetRef = {};
|
|
2953
|
+
let sourceElement;
|
|
2819
2954
|
let lineShapeG = null;
|
|
2820
2955
|
let temporaryElement = null;
|
|
2821
2956
|
board.pointerDown = (event) => {
|
|
@@ -2824,10 +2959,9 @@ const withLineCreateByDraw = (board) => {
|
|
|
2824
2959
|
if (isLinePointer && isDrawingMode(board)) {
|
|
2825
2960
|
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2826
2961
|
start = point;
|
|
2827
|
-
const hitElement = getHitOutlineGeometry(board, point,
|
|
2962
|
+
const hitElement = getHitOutlineGeometry(board, point, REACTION_MARGIN);
|
|
2828
2963
|
if (hitElement) {
|
|
2829
|
-
|
|
2830
|
-
sourceRef.boundId = hitElement.id;
|
|
2964
|
+
sourceElement = hitElement;
|
|
2831
2965
|
}
|
|
2832
2966
|
preventTouchMove(board, event, true);
|
|
2833
2967
|
}
|
|
@@ -2836,19 +2970,10 @@ const withLineCreateByDraw = (board) => {
|
|
|
2836
2970
|
board.pointerMove = (event) => {
|
|
2837
2971
|
lineShapeG?.remove();
|
|
2838
2972
|
lineShapeG = createG();
|
|
2839
|
-
|
|
2973
|
+
let movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
2840
2974
|
if (start) {
|
|
2841
|
-
const hitElement = getHitOutlineGeometry(board, movingPoint, -4);
|
|
2842
|
-
targetRef.connection = hitElement ? transformPointToConnection(board, movingPoint, hitElement) : undefined;
|
|
2843
|
-
targetRef.boundId = hitElement ? hitElement.id : undefined;
|
|
2844
|
-
const lineGenerator = new LineShapeGenerator(board);
|
|
2845
2975
|
const lineShape = PlaitBoard.getPointer(board);
|
|
2846
|
-
temporaryElement =
|
|
2847
|
-
strokeColor: DefaultLineStyle.strokeColor,
|
|
2848
|
-
strokeWidth: DefaultLineStyle.strokeWidth
|
|
2849
|
-
});
|
|
2850
|
-
lineGenerator.draw(temporaryElement, lineShapeG);
|
|
2851
|
-
PlaitBoard.getElementActiveHost(board).append(lineShapeG);
|
|
2976
|
+
temporaryElement = handleLineCreating(board, lineShape, start, movingPoint, sourceElement, lineShapeG);
|
|
2852
2977
|
}
|
|
2853
2978
|
pointerMove(event);
|
|
2854
2979
|
};
|
|
@@ -2861,9 +2986,8 @@ const withLineCreateByDraw = (board) => {
|
|
|
2861
2986
|
}
|
|
2862
2987
|
lineShapeG?.remove();
|
|
2863
2988
|
lineShapeG = null;
|
|
2989
|
+
sourceElement = null;
|
|
2864
2990
|
start = null;
|
|
2865
|
-
sourceRef = {};
|
|
2866
|
-
targetRef = {};
|
|
2867
2991
|
temporaryElement = null;
|
|
2868
2992
|
preventTouchMove(board, event, false);
|
|
2869
2993
|
pointerUp(event);
|
|
@@ -3049,7 +3173,7 @@ const withLineResize = (board) => {
|
|
|
3049
3173
|
if (resizeRef.handle === LineResizeHandle.source || resizeRef.handle === LineResizeHandle.target) {
|
|
3050
3174
|
const object = resizeRef.handle === LineResizeHandle.source ? source : target;
|
|
3051
3175
|
points[pointIndex] = resizeState.endTransformPoint;
|
|
3052
|
-
const hitElement = getHitOutlineGeometry(board, resizeState.endTransformPoint,
|
|
3176
|
+
const hitElement = getHitOutlineGeometry(board, resizeState.endTransformPoint, REACTION_MARGIN);
|
|
3053
3177
|
if (hitElement) {
|
|
3054
3178
|
object.connection = transformPointToConnection(board, resizeState.endTransformPoint, hitElement);
|
|
3055
3179
|
object.boundId = hitElement.id;
|
|
@@ -3059,7 +3183,9 @@ const withLineResize = (board) => {
|
|
|
3059
3183
|
object.boundId = undefined;
|
|
3060
3184
|
if (points.length === 2) {
|
|
3061
3185
|
let movingPoint = points[pointIndex];
|
|
3062
|
-
const
|
|
3186
|
+
const drawPoints = getLinePoints(board, resizeRef.element);
|
|
3187
|
+
const index = pointIndex === 0 ? drawPoints.length - 1 : pointIndex;
|
|
3188
|
+
const otherPoint = drawPoints[index];
|
|
3063
3189
|
points[pointIndex] = alignPoints(otherPoint, movingPoint);
|
|
3064
3190
|
}
|
|
3065
3191
|
}
|
|
@@ -3076,17 +3202,6 @@ const withLineResize = (board) => {
|
|
|
3076
3202
|
withResize(board, options);
|
|
3077
3203
|
return board;
|
|
3078
3204
|
};
|
|
3079
|
-
const alignPoints = (basePoint, movingPoint) => {
|
|
3080
|
-
const offset = 3;
|
|
3081
|
-
const newPoint = [...movingPoint];
|
|
3082
|
-
if (Point.isVerticalAlign(newPoint, basePoint, offset)) {
|
|
3083
|
-
newPoint[0] = basePoint[0];
|
|
3084
|
-
}
|
|
3085
|
-
if (Point.isHorizontalAlign(newPoint, basePoint, offset)) {
|
|
3086
|
-
newPoint[1] = basePoint[1];
|
|
3087
|
-
}
|
|
3088
|
-
return newPoint;
|
|
3089
|
-
};
|
|
3090
3205
|
|
|
3091
3206
|
const withLineBoundReaction = (board) => {
|
|
3092
3207
|
const { pointerMove, pointerUp } = board;
|
|
@@ -3210,7 +3325,7 @@ class ImageComponent extends CommonPluginElement {
|
|
|
3210
3325
|
ngOnInit() {
|
|
3211
3326
|
super.ngOnInit();
|
|
3212
3327
|
this.initializeGenerator();
|
|
3213
|
-
this.imageGenerator.
|
|
3328
|
+
this.imageGenerator.processDrawing(this.element, this.g, this.viewContainerRef);
|
|
3214
3329
|
}
|
|
3215
3330
|
onContextChanged(value, previous) {
|
|
3216
3331
|
if (value.element !== previous.element) {
|
|
@@ -3244,6 +3359,96 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
3244
3359
|
}]
|
|
3245
3360
|
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
3246
3361
|
|
|
3362
|
+
const withAutoCompleteReaction = (board) => {
|
|
3363
|
+
const { pointerMove } = board;
|
|
3364
|
+
let reactionG = null;
|
|
3365
|
+
board.pointerMove = (event) => {
|
|
3366
|
+
reactionG?.remove();
|
|
3367
|
+
if (isSelectionMoving(board)) {
|
|
3368
|
+
pointerMove(event);
|
|
3369
|
+
return;
|
|
3370
|
+
}
|
|
3371
|
+
const selectedElements = getSelectedDrawElements(board);
|
|
3372
|
+
const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
3373
|
+
if (selectedElements.length === 1 && PlaitDrawElement.isGeometry(selectedElements[0])) {
|
|
3374
|
+
const points = getAutoCompletePoints(selectedElements[0]);
|
|
3375
|
+
const hitIndex = getHitIndexOfAutoCompletePoint(movingPoint, points);
|
|
3376
|
+
const hitPoint = points[hitIndex];
|
|
3377
|
+
const component = PlaitElement.getComponent(selectedElements[0]);
|
|
3378
|
+
component.autoCompleteGenerator.recoverAutoCompleteG();
|
|
3379
|
+
if (hitPoint) {
|
|
3380
|
+
component.autoCompleteGenerator.removeAutoCompleteG(hitIndex);
|
|
3381
|
+
reactionG = drawCircle(PlaitBoard.getRoughSVG(board), hitPoint, 10, {
|
|
3382
|
+
stroke: 'none',
|
|
3383
|
+
fill: '#6698FF80',
|
|
3384
|
+
fillStyle: 'solid'
|
|
3385
|
+
});
|
|
3386
|
+
PlaitBoard.getElementActiveHost(board).append(reactionG);
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
pointerMove(event);
|
|
3390
|
+
};
|
|
3391
|
+
return board;
|
|
3392
|
+
};
|
|
3393
|
+
|
|
3394
|
+
const withAutoCompletePluginKey = 'plait-auto-complete-plugin-key';
|
|
3395
|
+
const withAutoComplete = (board) => {
|
|
3396
|
+
const { pointerDown, pointerMove, pointerUp } = board;
|
|
3397
|
+
const tolerance = 3;
|
|
3398
|
+
let startPoint = null;
|
|
3399
|
+
let lineShapeG = null;
|
|
3400
|
+
let sourceElement;
|
|
3401
|
+
let temporaryElement;
|
|
3402
|
+
board.pointerDown = (event) => {
|
|
3403
|
+
const selectedElements = getSelectedDrawElements(board);
|
|
3404
|
+
const clickPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
3405
|
+
if (selectedElements.length === 1 && PlaitDrawElement.isGeometry(selectedElements[0])) {
|
|
3406
|
+
const points = getAutoCompletePoints(selectedElements[0]);
|
|
3407
|
+
const index = getHitIndexOfAutoCompletePoint(clickPoint, points);
|
|
3408
|
+
const hitPoint = points[index];
|
|
3409
|
+
if (hitPoint) {
|
|
3410
|
+
temporaryDisableSelection(board);
|
|
3411
|
+
startPoint = clickPoint;
|
|
3412
|
+
sourceElement = selectedElements[0];
|
|
3413
|
+
BoardTransforms.updatePointerType(board, LineShape.elbow);
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
pointerDown(event);
|
|
3417
|
+
};
|
|
3418
|
+
board.pointerMove = (event) => {
|
|
3419
|
+
lineShapeG?.remove();
|
|
3420
|
+
lineShapeG = createG();
|
|
3421
|
+
let movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
3422
|
+
if (startPoint && sourceElement) {
|
|
3423
|
+
const distance = distanceBetweenPointAndPoint(...movingPoint, ...startPoint);
|
|
3424
|
+
if (distance > tolerance) {
|
|
3425
|
+
temporaryElement = handleLineCreating(board, LineShape.elbow, startPoint, movingPoint, sourceElement, lineShapeG);
|
|
3426
|
+
}
|
|
3427
|
+
}
|
|
3428
|
+
pointerMove(event);
|
|
3429
|
+
};
|
|
3430
|
+
board.pointerUp = event => {
|
|
3431
|
+
if (temporaryElement) {
|
|
3432
|
+
Transforms.insertNode(board, temporaryElement, [board.children.length]);
|
|
3433
|
+
clearSelectedElement(board);
|
|
3434
|
+
addSelectedElement(board, temporaryElement);
|
|
3435
|
+
const afterComplete = board.getPluginOptions(withAutoCompletePluginKey)
|
|
3436
|
+
?.afterComplete;
|
|
3437
|
+
afterComplete && afterComplete(temporaryElement);
|
|
3438
|
+
}
|
|
3439
|
+
if (startPoint) {
|
|
3440
|
+
BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
|
|
3441
|
+
startPoint = null;
|
|
3442
|
+
}
|
|
3443
|
+
lineShapeG?.remove();
|
|
3444
|
+
lineShapeG = null;
|
|
3445
|
+
sourceElement = null;
|
|
3446
|
+
temporaryElement = null;
|
|
3447
|
+
pointerUp(event);
|
|
3448
|
+
};
|
|
3449
|
+
return board;
|
|
3450
|
+
};
|
|
3451
|
+
|
|
3247
3452
|
const withDraw = (board) => {
|
|
3248
3453
|
const { drawElement, getRectangle, isRectangleHit, isHit, isMovable, isAlign } = board;
|
|
3249
3454
|
board.drawElement = (context) => {
|
|
@@ -3297,11 +3502,13 @@ const withDraw = (board) => {
|
|
|
3297
3502
|
const isSelected = (boundId) => {
|
|
3298
3503
|
return !!selectedElements.find(value => value.id === boundId);
|
|
3299
3504
|
};
|
|
3300
|
-
if ((
|
|
3301
|
-
(element.
|
|
3302
|
-
|
|
3505
|
+
if ((!element.source.boundId ||
|
|
3506
|
+
(element.source.boundId && isSelected(element.source.boundId) && selectedElements.includes(element))) &&
|
|
3507
|
+
(!element.target.boundId ||
|
|
3508
|
+
(element.source.boundId && isSelected(element.source.boundId) && selectedElements.includes(element)))) {
|
|
3509
|
+
return true;
|
|
3303
3510
|
}
|
|
3304
|
-
return
|
|
3511
|
+
return false;
|
|
3305
3512
|
}
|
|
3306
3513
|
return isMovable(element);
|
|
3307
3514
|
};
|
|
@@ -3311,12 +3518,12 @@ const withDraw = (board) => {
|
|
|
3311
3518
|
}
|
|
3312
3519
|
return isAlign(element);
|
|
3313
3520
|
};
|
|
3314
|
-
return withLineText(withLineBoundReaction(withLineResize(withGeometryResize(withLineCreateByDraw(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board)))))))));
|
|
3521
|
+
return withAutoCompleteReaction(withLineText(withLineBoundReaction(withLineResize(withGeometryResize(withLineCreateByDraw(withAutoComplete(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board)))))))))));
|
|
3315
3522
|
};
|
|
3316
3523
|
|
|
3317
3524
|
/**
|
|
3318
3525
|
* Generated bundle index. Do not edit.
|
|
3319
3526
|
*/
|
|
3320
3527
|
|
|
3321
|
-
export { BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultBasicShapeProperty, DefaultConnectorProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultGeometryActiveStyle, DefaultGeometryStyle, DefaultManualInputProperty, DefaultMergeProperty, DefaultTextProperty, DrawTransforms, FlowchartSymbols, GeometryComponent, GeometryThreshold, LineComponent, LineHandleKey, LineMarkerType, LineShape, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, StrokeStyle, createDefaultFlowchart, createGeometryElement, createLineElement, drawBoundMask, drawGeometry, drawLine, getBasicPointers, getBoardLines, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultFlowchartProperty, getEdgeOnPolygonByPoint, getElbowPoints,
|
|
3528
|
+
export { BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultBasicShapeProperty, DefaultConnectorProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultGeometryActiveStyle, DefaultGeometryStyle, DefaultManualInputProperty, DefaultMergeProperty, DefaultTextProperty, DrawThemeColors, DrawTransforms, FlowchartSymbols, GeometryComponent, GeometryThreshold, LineComponent, LineHandleKey, LineMarkerType, LineShape, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, REACTION_MARGIN, ShapeDefaultSpace, StrokeStyle, alignPoints, createDefaultFlowchart, createGeometryElement, createLineElement, drawBoundMask, drawGeometry, drawLine, getAutoCompletePoints, getBasicPointers, getBoardLines, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultFlowchartProperty, getDrawDefaultStrokeColor, getEdgeOnPolygonByPoint, getElbowPoints, getFillByElement, getFlowchartDefaultFill, getFlowchartPointers, getGeometryPointers, getHitConnectorPoint, getHitIndexOfAutoCompletePoint, getHitLineTextIndex, getLineDashByElement, getLineHandleRefPair, getLinePointers, getLinePoints, getLineTextRectangle, getNearestPoint, getPointsByCenterPoint, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedLineElements, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTextRectangle, getVectorByConnection, handleLineCreating, isHitDrawElement, isHitLineText, isHitPolyLine, isRectangleHitDrawElement, isTextExceedingBounds, transformOpsToPoints, transformPointToConnection, withDraw };
|
|
3322
3529
|
//# sourceMappingURL=plait-draw.mjs.map
|