@plait/common 0.50.0 → 0.51.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/README.md +7 -6
- package/constants/default.d.ts +1 -1
- package/constants/resize.d.ts +8 -8
- package/esm2022/constants/default.mjs +2 -2
- package/esm2022/constants/resize.mjs +9 -9
- package/esm2022/generators/active.generator.mjs +9 -10
- package/esm2022/generators/generator.mjs +6 -1
- package/esm2022/plugins/with-resize.mjs +53 -44
- package/esm2022/public-api.mjs +2 -1
- package/esm2022/types/resize.mjs +2 -0
- package/esm2022/utils/direction.mjs +5 -25
- package/esm2022/utils/drawing/index.mjs +2 -0
- package/esm2022/utils/drawing/resize-handle.mjs +23 -0
- package/esm2022/utils/elbow-line-route.mjs +38 -36
- package/esm2022/utils/index.mjs +4 -2
- package/esm2022/utils/line-path.mjs +23 -12
- package/esm2022/utils/math.mjs +24 -0
- package/esm2022/utils/resize.mjs +36 -23
- package/esm2022/utils/vector.mjs +33 -0
- package/fesm2022/plait-common.mjs +239 -162
- package/fesm2022/plait-common.mjs.map +1 -1
- package/package.json +1 -1
- package/plugins/with-resize.d.ts +3 -21
- package/public-api.d.ts +1 -0
- package/types/resize.d.ts +30 -0
- package/utils/direction.d.ts +2 -7
- package/utils/drawing/index.d.ts +1 -0
- package/utils/drawing/resize-handle.d.ts +4 -0
- package/utils/elbow-line-route.d.ts +17 -2
- package/utils/index.d.ts +3 -1
- package/utils/line-path.d.ts +1 -1
- package/utils/math.d.ts +3 -0
- package/utils/resize.d.ts +10 -8
- package/utils/vector.d.ts +5 -0
- package/esm2022/utils/rectangle.mjs +0 -16
- package/utils/rectangle.d.ts +0 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { setTransformRotate, drawCircle, PlaitBoard, createG, RectangleClient, drawRectangle, createForeignObject, updateForeignObject, ResizeCursorClass, setDragging, Direction, distanceBetweenPointAndPoint, Point, hotkeys, PlaitElement, PlaitContextService, getSelectedElements, Transforms, getRectangleByElements, MERGING, PlaitPointerType, isMainPointer, toViewBoxPoint, toHostPoint, preventTouchMove, PRESS_AND_MOVE_BUFFER, isDragging, throttleRAF, handleTouchTarget, PlaitPluginElementComponent, isSelectionMoving, ACTIVE_STROKE_WIDTH } from '@plait/core';
|
|
2
2
|
import { isKeyHotkey } from 'is-hotkey';
|
|
3
3
|
import { PlaitMarkEditor, MarkTypes, AlignEditor } from '@plait/text';
|
|
4
4
|
import { Node, Transforms as Transforms$1, Editor } from 'slate';
|
|
@@ -7,7 +7,7 @@ import { Directive, Input } from '@angular/core';
|
|
|
7
7
|
|
|
8
8
|
const BASE = 4;
|
|
9
9
|
const PRIMARY_COLOR = '#6698FF';
|
|
10
|
-
const RESIZE_HANDLE_DIAMETER =
|
|
10
|
+
const RESIZE_HANDLE_DIAMETER = 9;
|
|
11
11
|
const WithTextPluginKey = 'plait-text-plugin-key';
|
|
12
12
|
const DEFAULT_ROUTE_MARGIN = 30;
|
|
13
13
|
const TRANSPARENT = 'transparent';
|
|
@@ -22,14 +22,14 @@ const WithCommonPluginKey = 'plait-common-plugin-key';
|
|
|
22
22
|
|
|
23
23
|
var ResizeHandle;
|
|
24
24
|
(function (ResizeHandle) {
|
|
25
|
-
ResizeHandle["
|
|
26
|
-
ResizeHandle["n"] = "
|
|
27
|
-
ResizeHandle["
|
|
28
|
-
ResizeHandle["e"] = "
|
|
29
|
-
ResizeHandle["se"] = "
|
|
30
|
-
ResizeHandle["s"] = "
|
|
31
|
-
ResizeHandle["sw"] = "
|
|
32
|
-
ResizeHandle["w"] = "
|
|
25
|
+
ResizeHandle["nw"] = "0";
|
|
26
|
+
ResizeHandle["n"] = "4";
|
|
27
|
+
ResizeHandle["ne"] = "1";
|
|
28
|
+
ResizeHandle["e"] = "5";
|
|
29
|
+
ResizeHandle["se"] = "2";
|
|
30
|
+
ResizeHandle["s"] = "6";
|
|
31
|
+
ResizeHandle["sw"] = "3";
|
|
32
|
+
ResizeHandle["w"] = "7";
|
|
33
33
|
})(ResizeHandle || (ResizeHandle = {}));
|
|
34
34
|
|
|
35
35
|
class Generator {
|
|
@@ -53,6 +53,10 @@ class Generator {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
this.g = g;
|
|
56
|
+
const rect = this.board.getRectangle(element);
|
|
57
|
+
if (rect && element.angle) {
|
|
58
|
+
setTransformRotate(g, rect, element.angle);
|
|
59
|
+
}
|
|
56
60
|
}
|
|
57
61
|
else {
|
|
58
62
|
this.destroy();
|
|
@@ -79,6 +83,27 @@ function hasAfterDraw(value) {
|
|
|
79
83
|
return false;
|
|
80
84
|
}
|
|
81
85
|
|
|
86
|
+
const drawHandle = (board, centerPoint) => {
|
|
87
|
+
const options = { stroke: '#99999995', strokeWidth: 2, fill: '#FFF', fillStyle: 'solid' };
|
|
88
|
+
return drawCircle(PlaitBoard.getRoughSVG(board), centerPoint, RESIZE_HANDLE_DIAMETER, options);
|
|
89
|
+
};
|
|
90
|
+
function drawFillPrimaryHandle(board, point) {
|
|
91
|
+
return drawCircle(PlaitBoard.getRoughSVG(board), point, RESIZE_HANDLE_DIAMETER, {
|
|
92
|
+
stroke: '#FFFFFF',
|
|
93
|
+
strokeWidth: 1,
|
|
94
|
+
fill: `${PRIMARY_COLOR}`,
|
|
95
|
+
fillStyle: 'solid'
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function drawPrimaryHandle(board, point) {
|
|
99
|
+
return drawCircle(PlaitBoard.getRoughSVG(board), point, RESIZE_HANDLE_DIAMETER, {
|
|
100
|
+
stroke: `${PRIMARY_COLOR}`,
|
|
101
|
+
strokeWidth: 2,
|
|
102
|
+
fill: `#FFFFFF`,
|
|
103
|
+
fillStyle: 'solid'
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
82
107
|
class ActiveGenerator extends Generator {
|
|
83
108
|
constructor(board, options) {
|
|
84
109
|
super(board, options);
|
|
@@ -107,13 +132,11 @@ class ActiveGenerator extends Generator {
|
|
|
107
132
|
strokeG.style.opacity = `${this.options.getStrokeOpacity()}`;
|
|
108
133
|
if (this.options.hasResizeHandle()) {
|
|
109
134
|
this.hasResizeHandle = true;
|
|
110
|
-
// resize handle
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const leftBottomHandleG = drawCircle(PlaitBoard.getRoughSVG(this.board), [activeRectangle.x, activeRectangle.y + activeRectangle.height], RESIZE_HANDLE_DIAMETER, options);
|
|
116
|
-
activeG.append(...[leftTopHandleG, rightTopHandleG, rightBottomHandleG, leftBottomHandleG]);
|
|
135
|
+
// draw resize handle
|
|
136
|
+
RectangleClient.getCornerPoints(activeRectangle).forEach(corner => {
|
|
137
|
+
const cornerHandleG = drawHandle(this.board, corner);
|
|
138
|
+
activeG.append(cornerHandleG);
|
|
139
|
+
});
|
|
117
140
|
}
|
|
118
141
|
else {
|
|
119
142
|
this.hasResizeHandle = false;
|
|
@@ -174,26 +197,18 @@ class ImageGenerator extends Generator {
|
|
|
174
197
|
}
|
|
175
198
|
|
|
176
199
|
const getResizeHandleByIndex = (index) => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return ResizeHandle.n;
|
|
188
|
-
case 5:
|
|
189
|
-
return ResizeHandle.e;
|
|
190
|
-
case 6:
|
|
191
|
-
return ResizeHandle.s;
|
|
192
|
-
case 7:
|
|
193
|
-
return ResizeHandle.w;
|
|
194
|
-
default:
|
|
195
|
-
return null;
|
|
200
|
+
return `${index}`;
|
|
201
|
+
};
|
|
202
|
+
const getIndexByResizeHandle = (resizeHandle) => {
|
|
203
|
+
return Number(resizeHandle);
|
|
204
|
+
};
|
|
205
|
+
const getSymmetricHandleIndex = (board, index) => {
|
|
206
|
+
const originIndex = isEdgeHandle(board, getResizeHandleByIndex(index)) ? index - 4 : index;
|
|
207
|
+
let originSymmetricHandleIndex = originIndex + 2;
|
|
208
|
+
if (originSymmetricHandleIndex >= 4) {
|
|
209
|
+
originSymmetricHandleIndex = originSymmetricHandleIndex - 4;
|
|
196
210
|
}
|
|
211
|
+
return isEdgeHandle(board, getResizeHandleByIndex(index)) ? originSymmetricHandleIndex + 4 : originSymmetricHandleIndex;
|
|
197
212
|
};
|
|
198
213
|
const getResizeCursorClassByIndex = (index) => {
|
|
199
214
|
switch (index) {
|
|
@@ -237,10 +252,20 @@ const getRectangleResizeHandleRefs = (rectangle, diameter) => {
|
|
|
237
252
|
}));
|
|
238
253
|
return refs;
|
|
239
254
|
};
|
|
255
|
+
const getResizeHandlePointByIndex = (rectangle, index) => {
|
|
256
|
+
if (index <= 3) {
|
|
257
|
+
const corners = RectangleClient.getCornerPoints(rectangle);
|
|
258
|
+
return corners[index];
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
const edgeCenterPoints = RectangleClient.getEdgeCenterPoints(rectangle);
|
|
262
|
+
return edgeCenterPoints[index - 4];
|
|
263
|
+
}
|
|
264
|
+
};
|
|
240
265
|
const getResizeSideRectangles = (cornerPoints, offset) => {
|
|
241
266
|
const result = [];
|
|
242
267
|
for (let i = 0; i < cornerPoints.length; i++) {
|
|
243
|
-
let rectangle = RectangleClient.
|
|
268
|
+
let rectangle = RectangleClient.getRectangleByPoints([cornerPoints[i], cornerPoints[(i + 1) % 4]]);
|
|
244
269
|
const arr = new Array(2).fill(0);
|
|
245
270
|
arr[(i + 1) % 2] = offset / 2;
|
|
246
271
|
rectangle = RectangleClient.expand(rectangle, arr[0], arr[1]);
|
|
@@ -265,6 +290,18 @@ const removeResizing = (board, key) => {
|
|
|
265
290
|
IS_RESIZING.delete(board);
|
|
266
291
|
setDragging(board, false);
|
|
267
292
|
};
|
|
293
|
+
const isEdgeHandle = (board, handle) => {
|
|
294
|
+
const index = getIndexByResizeHandle(handle);
|
|
295
|
+
if (index >= 4) {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
const isCornerHandle = (board, handle) => {
|
|
303
|
+
return !isEdgeHandle(board, handle);
|
|
304
|
+
};
|
|
268
305
|
|
|
269
306
|
const handleDirectionFactors = {
|
|
270
307
|
[Direction.left]: { x: -1, y: 0 },
|
|
@@ -319,17 +356,6 @@ function getDirectionByVector(vector) {
|
|
|
319
356
|
return Direction.left;
|
|
320
357
|
}
|
|
321
358
|
}
|
|
322
|
-
function getPointByVector(point, vector, offset) {
|
|
323
|
-
const distance = Math.hypot(vector[0], vector[1]);
|
|
324
|
-
return [point[0] + (vector[0] / distance) * offset, point[1] + (vector[1] / distance) * offset];
|
|
325
|
-
}
|
|
326
|
-
function rotateVectorAnti90(vector) {
|
|
327
|
-
const x = vector[0];
|
|
328
|
-
const y = vector[1];
|
|
329
|
-
const rotatedX = y;
|
|
330
|
-
const rotatedY = -x;
|
|
331
|
-
return [rotatedX, rotatedY];
|
|
332
|
-
}
|
|
333
359
|
function getDirectionBetweenPointAndPoint(source, target) {
|
|
334
360
|
if (source[0] === target[0]) {
|
|
335
361
|
if (source[1] >= target[1]) {
|
|
@@ -352,19 +378,65 @@ function getDirectionBetweenPointAndPoint(source, target) {
|
|
|
352
378
|
function getDirectionFactor(direction) {
|
|
353
379
|
return handleDirectionFactors[direction];
|
|
354
380
|
}
|
|
355
|
-
function
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
381
|
+
function getDirectionFactorByVectorComponent(vectorComponent) {
|
|
382
|
+
const directionFactor = vectorComponent === 0 ? vectorComponent : vectorComponent / Math.abs(vectorComponent);
|
|
383
|
+
return directionFactor;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function getUnitVectorByPointAndPoint(point1, point2) {
|
|
387
|
+
const deltaX = point2[0] - point1[0];
|
|
388
|
+
const deltaY = point2[1] - point1[1];
|
|
389
|
+
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
390
|
+
// Avoid division by zero if the points are the same
|
|
391
|
+
if (distance === 0) {
|
|
392
|
+
throw new Error('Points must not be the same for a unit vector calculation.');
|
|
393
|
+
}
|
|
394
|
+
// Calculate the unit vector components
|
|
395
|
+
const unitX = deltaX / distance;
|
|
396
|
+
const unitY = deltaY / distance;
|
|
397
|
+
return [unitX, unitY];
|
|
398
|
+
}
|
|
399
|
+
function getPointByVector(point, vector, component) {
|
|
400
|
+
const distance = Math.hypot(vector[0], vector[1]);
|
|
401
|
+
return [point[0] + (vector[0] / distance) * component, point[1] + (vector[1] / distance) * component];
|
|
402
|
+
}
|
|
403
|
+
function getPointByUnitVectorAndVectorComponent(point, unitVector, vectorComponent, isHorizontal) {
|
|
404
|
+
if (isHorizontal) {
|
|
405
|
+
return [point[0] + vectorComponent, point[1] + (vectorComponent / unitVector[0]) * unitVector[1]];
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
return [point[0] + (vectorComponent / unitVector[1]) * unitVector[0], point[1] + vectorComponent];
|
|
362
409
|
}
|
|
363
|
-
return {
|
|
364
|
-
x: (target[0] - source[0]) / distance,
|
|
365
|
-
y: (target[1] - source[1]) / distance
|
|
366
|
-
};
|
|
367
410
|
}
|
|
411
|
+
function rotateVectorAnti90(vector) {
|
|
412
|
+
const x = vector[0];
|
|
413
|
+
const y = vector[1];
|
|
414
|
+
const rotatedX = y;
|
|
415
|
+
const rotatedY = -x;
|
|
416
|
+
return [rotatedX, rotatedY];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function isPointOnSegment(point, startPoint, endPoint) {
|
|
420
|
+
const distanceToStart = distanceBetweenPointAndPoint(point[0], point[1], startPoint[0], startPoint[1]);
|
|
421
|
+
const distanceToEnd = distanceBetweenPointAndPoint(point[0], point[1], endPoint[0], endPoint[1]);
|
|
422
|
+
const segmentLength = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
|
|
423
|
+
return Math.abs(distanceToStart + distanceToEnd - segmentLength) < 0.1;
|
|
424
|
+
}
|
|
425
|
+
const getCrossingPointsBetweenPointAndSegment = (point, startPoint, endPoint) => {
|
|
426
|
+
const result = [];
|
|
427
|
+
const xRange = [Math.min(startPoint[0], endPoint[0]), Math.max(startPoint[0], endPoint[0])];
|
|
428
|
+
const yRange = [Math.min(startPoint[1], endPoint[1]), Math.max(startPoint[1], endPoint[1])];
|
|
429
|
+
const unitVector = getUnitVectorByPointAndPoint(startPoint, endPoint);
|
|
430
|
+
if (point[0] >= xRange[0] && point[0] <= xRange[1]) {
|
|
431
|
+
const crossingPoint = getPointByUnitVectorAndVectorComponent(startPoint, unitVector, point[0] - startPoint[0], true);
|
|
432
|
+
result.push(crossingPoint);
|
|
433
|
+
}
|
|
434
|
+
else if (point[1] >= yRange[0] && point[1] <= yRange[1]) {
|
|
435
|
+
const crossingPoint = getPointByUnitVectorAndVectorComponent(startPoint, unitVector, point[1] - startPoint[1], false);
|
|
436
|
+
result.push(crossingPoint);
|
|
437
|
+
}
|
|
438
|
+
return result;
|
|
439
|
+
};
|
|
368
440
|
|
|
369
441
|
function getOppositeDirection(direction) {
|
|
370
442
|
switch (direction) {
|
|
@@ -435,11 +507,11 @@ const getPoints = (source, sourcePosition, target, targetPosition, offset) => {
|
|
|
435
507
|
if (sourcePosition !== targetPosition) {
|
|
436
508
|
const dirAccessorOpposite = dirAccessor === 'x' ? 1 : 0;
|
|
437
509
|
const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessor === 'x' ? 'y' : 'x'];
|
|
438
|
-
const
|
|
439
|
-
const
|
|
510
|
+
const sourceGtTarget = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];
|
|
511
|
+
const sourceLtTarget = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];
|
|
440
512
|
flipSourceTarget =
|
|
441
|
-
(sourceDir[dirAccessor] === 1 && ((!isSameDir &&
|
|
442
|
-
(sourceDir[dirAccessor] !== 1 && ((!isSameDir &&
|
|
513
|
+
(sourceDir[dirAccessor] === 1 && ((!isSameDir && sourceGtTarget) || (isSameDir && sourceLtTarget))) ||
|
|
514
|
+
(sourceDir[dirAccessor] !== 1 && ((!isSameDir && sourceLtTarget) || (isSameDir && sourceGtTarget)));
|
|
443
515
|
if (flipSourceTarget) {
|
|
444
516
|
points = dirAccessor === 'x' ? sourceTarget : targetSource;
|
|
445
517
|
}
|
|
@@ -492,7 +564,7 @@ function getRatioByPoint(points, point) {
|
|
|
492
564
|
const totalLength = calculatePolylineLength(points);
|
|
493
565
|
let distance = 0;
|
|
494
566
|
for (let i = 0; i < points.length - 1; i++) {
|
|
495
|
-
const isOverlap =
|
|
567
|
+
const isOverlap = isPointOnSegment(point, points[i], points[i + 1]);
|
|
496
568
|
if (isOverlap) {
|
|
497
569
|
distance += distanceBetweenPointAndPoint(point[0], point[1], points[i][0], points[i][1]);
|
|
498
570
|
return distance / totalLength;
|
|
@@ -503,12 +575,6 @@ function getRatioByPoint(points, point) {
|
|
|
503
575
|
}
|
|
504
576
|
throw new Error('Cannot get ratio by point');
|
|
505
577
|
}
|
|
506
|
-
function isPointOnLineSegment(point, startPoint, endPoint) {
|
|
507
|
-
const distanceToStart = distanceBetweenPointAndPoint(point[0], point[1], startPoint[0], startPoint[1]);
|
|
508
|
-
const distanceToEnd = distanceBetweenPointAndPoint(point[0], point[1], endPoint[0], endPoint[1]);
|
|
509
|
-
const segmentLength = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
|
|
510
|
-
return Math.abs(distanceToStart + distanceToEnd - segmentLength) < 0.1;
|
|
511
|
-
}
|
|
512
578
|
const removeDuplicatePoints = (points) => {
|
|
513
579
|
const newArray = [];
|
|
514
580
|
points.forEach(point => {
|
|
@@ -520,6 +586,22 @@ const removeDuplicatePoints = (points) => {
|
|
|
520
586
|
});
|
|
521
587
|
return newArray;
|
|
522
588
|
};
|
|
589
|
+
function simplifyOrthogonalPoints(points) {
|
|
590
|
+
if (points.length <= 2)
|
|
591
|
+
return points;
|
|
592
|
+
let simplifiedPoints = [points[0]];
|
|
593
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
594
|
+
const previous = points[i - 1];
|
|
595
|
+
const current = points[i];
|
|
596
|
+
const next = points[i + 1];
|
|
597
|
+
const isTurn = !(Point.isOverHorizontal([previous, current, next]) || Point.isOverVertical([previous, current, next]));
|
|
598
|
+
if (isTurn) {
|
|
599
|
+
simplifiedPoints.push(current);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
simplifiedPoints.push(points[points.length - 1]);
|
|
603
|
+
return simplifiedPoints;
|
|
604
|
+
}
|
|
523
605
|
const getExtendPoint = (source, target, extendDistance) => {
|
|
524
606
|
const distance = distanceBetweenPointAndPoint(...source, ...target);
|
|
525
607
|
const isEqual = Point.isEquals(source, target);
|
|
@@ -555,22 +637,6 @@ const isDelete = (event) => {
|
|
|
555
637
|
return hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event);
|
|
556
638
|
};
|
|
557
639
|
|
|
558
|
-
const getRectangleByPoints = (points) => {
|
|
559
|
-
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
560
|
-
points.forEach(point => {
|
|
561
|
-
minX = Math.min(point[0], minX);
|
|
562
|
-
maxX = Math.max(point[0], maxX);
|
|
563
|
-
minY = Math.min(point[1], minY);
|
|
564
|
-
maxY = Math.max(point[1], maxY);
|
|
565
|
-
});
|
|
566
|
-
return {
|
|
567
|
-
x: minX,
|
|
568
|
-
y: minY,
|
|
569
|
-
width: maxX - minX,
|
|
570
|
-
height: maxY - minY
|
|
571
|
-
};
|
|
572
|
-
};
|
|
573
|
-
|
|
574
640
|
var BoardCreationMode;
|
|
575
641
|
(function (BoardCreationMode) {
|
|
576
642
|
BoardCreationMode["dnd"] = "dnd";
|
|
@@ -825,30 +891,30 @@ const generateElbowLineRoute = (options) => {
|
|
|
825
891
|
let route = aStar.getRoute(nextSourcePoint, nextTargetPoint);
|
|
826
892
|
route = [options.sourcePoint, ...route, nextTargetPoint, options.targetPoint];
|
|
827
893
|
// Centerline correction: Correct the shortest path route based on the horizontal centerline/vertical centerline
|
|
828
|
-
// 1. Find the horizontal center line (
|
|
829
|
-
// 2. Find the point that intersects
|
|
894
|
+
// 1. Find the horizontal center line (centerX)/vertical center line (centerY)
|
|
895
|
+
// 2. Find the point that intersects centerX/centerY in route, and find the line segment parallel to centerX/centerY in route
|
|
830
896
|
// 3. Construct a rectangle based on the intersection points and parallel lines found in the previous step.
|
|
831
897
|
// 4. Determine whether the rectangle intersects with the element. If it does not intersect, the center line can be mapped based on the rectangle constructed in the previous step.
|
|
832
898
|
// 5. Determine whether the path after mapping the center line meets the constraints (inflection point cannot be increased)
|
|
833
899
|
const isHitX = RectangleClient.isHitX(options.sourceOuterRectangle, options.targetOuterRectangle);
|
|
834
900
|
const isHitY = RectangleClient.isHitY(options.sourceOuterRectangle, options.targetOuterRectangle);
|
|
835
|
-
const
|
|
836
|
-
const
|
|
837
|
-
route = routeAdjust(route, {
|
|
901
|
+
const centerX = isHitX ? undefined : RectangleClient.getGapCenter(options.sourceOuterRectangle, options.targetOuterRectangle, true);
|
|
902
|
+
const centerY = isHitY ? undefined : RectangleClient.getGapCenter(options.sourceOuterRectangle, options.targetOuterRectangle, false);
|
|
903
|
+
route = routeAdjust(route, { centerX, centerY, sourceRectangle: options.sourceRectangle, targetRectangle: options.targetRectangle });
|
|
838
904
|
return route;
|
|
839
905
|
};
|
|
840
906
|
const routeAdjust = (path, options) => {
|
|
841
|
-
const { sourceRectangle, targetRectangle,
|
|
842
|
-
if (
|
|
843
|
-
const optionsX = getAdjustOptions(path,
|
|
907
|
+
const { sourceRectangle, targetRectangle, centerX, centerY } = options;
|
|
908
|
+
if (centerX !== undefined) {
|
|
909
|
+
const optionsX = getAdjustOptions(path, centerX, true);
|
|
844
910
|
const resultX = optionsX.pointOfHit &&
|
|
845
911
|
adjust(path, { parallelPaths: optionsX.parallelPaths, pointOfHit: optionsX.pointOfHit, sourceRectangle, targetRectangle });
|
|
846
912
|
if (resultX) {
|
|
847
913
|
path = resultX;
|
|
848
914
|
}
|
|
849
915
|
}
|
|
850
|
-
if (
|
|
851
|
-
const optionsY = getAdjustOptions(path,
|
|
916
|
+
if (centerY !== undefined) {
|
|
917
|
+
const optionsY = getAdjustOptions(path, centerY, false);
|
|
852
918
|
const resultY = optionsY.pointOfHit &&
|
|
853
919
|
adjust(path, { parallelPaths: optionsY.parallelPaths, pointOfHit: optionsY.pointOfHit, sourceRectangle, targetRectangle });
|
|
854
920
|
if (resultY) {
|
|
@@ -862,29 +928,15 @@ const adjust = (route, options) => {
|
|
|
862
928
|
let result = null;
|
|
863
929
|
parallelPaths.forEach(parallelPath => {
|
|
864
930
|
// Construct a rectangle
|
|
865
|
-
const
|
|
931
|
+
const tempRectPoints = [pointOfHit, parallelPath[0], parallelPath[1]];
|
|
932
|
+
// directly use getCornerPoints will bring the precision issue (eg: 263.6923375175286 - 57.130859375)
|
|
933
|
+
const tempRect = RectangleClient.getRectangleByPoints(tempRectPoints);
|
|
866
934
|
if (!RectangleClient.isHit(tempRect, sourceRectangle) && !RectangleClient.isHit(tempRect, targetRectangle)) {
|
|
867
|
-
const getCornerCount = (path) => {
|
|
868
|
-
let cornerCount = 0;
|
|
869
|
-
for (let index = 1; index < path.length - 1; index++) {
|
|
870
|
-
const pre = path[index - 1];
|
|
871
|
-
const current = path[index];
|
|
872
|
-
const next = path[index + 1];
|
|
873
|
-
if (pre &&
|
|
874
|
-
current &&
|
|
875
|
-
next &&
|
|
876
|
-
!((downScale(current[0]) === downScale(pre[0]) && downScale(current[0]) === downScale(next[0])) ||
|
|
877
|
-
(downScale(current[1]) === downScale(pre[1]) && downScale(current[1]) === downScale(next[1])))) {
|
|
878
|
-
cornerCount++;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
return cornerCount;
|
|
882
|
-
};
|
|
883
935
|
const tempCorners = RectangleClient.getCornerPoints(tempRect);
|
|
884
936
|
const indexRangeInPath = [];
|
|
885
937
|
const indexRangeInCorner = [];
|
|
886
938
|
route.forEach((point, index) => {
|
|
887
|
-
const cornerResult = tempCorners.findIndex(corner =>
|
|
939
|
+
const cornerResult = tempCorners.findIndex(corner => Point.isEquals(point, corner));
|
|
888
940
|
if (cornerResult !== -1) {
|
|
889
941
|
indexRangeInPath.push(index);
|
|
890
942
|
indexRangeInCorner.push(cornerResult);
|
|
@@ -894,9 +946,9 @@ const adjust = (route, options) => {
|
|
|
894
946
|
const missCorner = tempCorners.find((c, index) => !indexRangeInCorner.includes(index));
|
|
895
947
|
const removeLength = Math.abs(indexRangeInPath[0] - indexRangeInPath[indexRangeInPath.length - 1]) + 1;
|
|
896
948
|
newPath.splice(indexRangeInPath[0] + 1, removeLength - 2, missCorner);
|
|
897
|
-
const
|
|
898
|
-
const
|
|
899
|
-
if (
|
|
949
|
+
const turnCount = simplifyOrthogonalPoints([...route]).length - 1;
|
|
950
|
+
const newTurnCount = simplifyOrthogonalPoints([...newPath]).length - 1;
|
|
951
|
+
if (newTurnCount <= turnCount) {
|
|
900
952
|
result = newPath;
|
|
901
953
|
}
|
|
902
954
|
}
|
|
@@ -904,7 +956,7 @@ const adjust = (route, options) => {
|
|
|
904
956
|
});
|
|
905
957
|
return result;
|
|
906
958
|
};
|
|
907
|
-
const getAdjustOptions = (path,
|
|
959
|
+
const getAdjustOptions = (path, centerOfAxis, isHorizontal) => {
|
|
908
960
|
const parallelPaths = [];
|
|
909
961
|
let start = null;
|
|
910
962
|
let pointOfHit = null;
|
|
@@ -921,7 +973,7 @@ const getAdjustOptions = (path, middle, isHorizontal) => {
|
|
|
921
973
|
start = null;
|
|
922
974
|
}
|
|
923
975
|
}
|
|
924
|
-
if (current[axis] ===
|
|
976
|
+
if (current[axis] === centerOfAxis) {
|
|
925
977
|
pointOfHit = current;
|
|
926
978
|
}
|
|
927
979
|
}
|
|
@@ -1054,6 +1106,22 @@ const getNextPoint = (point, outerRectangle, direction) => {
|
|
|
1054
1106
|
}
|
|
1055
1107
|
}
|
|
1056
1108
|
};
|
|
1109
|
+
const getSourceAndTargetOuterRectangle = (sourceRectangle, targetRectangle) => {
|
|
1110
|
+
const { sourceOffset, targetOffset } = reduceRouteMargin(sourceRectangle, targetRectangle);
|
|
1111
|
+
const sourceOuterRectangle = RectangleClient.expand(sourceRectangle, sourceOffset[3], sourceOffset[0], sourceOffset[1], sourceOffset[2]);
|
|
1112
|
+
const targetOuterRectangle = RectangleClient.expand(targetRectangle, targetOffset[3], targetOffset[0], targetOffset[1], targetOffset[2]);
|
|
1113
|
+
return {
|
|
1114
|
+
sourceOuterRectangle,
|
|
1115
|
+
targetOuterRectangle
|
|
1116
|
+
};
|
|
1117
|
+
};
|
|
1118
|
+
const isSourceAndTargetIntersect = (options) => {
|
|
1119
|
+
const { sourcePoint, nextSourcePoint, sourceRectangle, sourceOuterRectangle, targetPoint, nextTargetPoint, targetRectangle, targetOuterRectangle } = options;
|
|
1120
|
+
return (RectangleClient.isPointInRectangle(targetRectangle, sourcePoint) ||
|
|
1121
|
+
RectangleClient.isPointInRectangle(targetOuterRectangle, nextSourcePoint) ||
|
|
1122
|
+
RectangleClient.isPointInRectangle(sourceOuterRectangle, nextTargetPoint) ||
|
|
1123
|
+
RectangleClient.isPointInRectangle(sourceRectangle, targetPoint));
|
|
1124
|
+
};
|
|
1057
1125
|
|
|
1058
1126
|
const map = new Map();
|
|
1059
1127
|
const memorizeLatest = (memorizedKey, propertyKey, propertyValue) => {
|
|
@@ -1287,26 +1355,31 @@ const generalCanResize = (board, event) => {
|
|
|
1287
1355
|
};
|
|
1288
1356
|
const withResize = (board, options) => {
|
|
1289
1357
|
const { pointerDown, pointerMove, globalPointerUp } = board;
|
|
1290
|
-
let
|
|
1358
|
+
let resizeHitTestRef = null;
|
|
1291
1359
|
let resizeRef = null;
|
|
1292
1360
|
let startPoint = null;
|
|
1293
|
-
let
|
|
1361
|
+
let hoverHitTestRef = null;
|
|
1294
1362
|
board.pointerDown = (event) => {
|
|
1295
1363
|
if (!options.canResize() || !generalCanResize(board, event) || !isMainPointer(event)) {
|
|
1296
1364
|
pointerDown(event);
|
|
1297
1365
|
return;
|
|
1298
1366
|
}
|
|
1299
1367
|
const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
1300
|
-
|
|
1301
|
-
if (
|
|
1302
|
-
if (
|
|
1303
|
-
PlaitBoard.getBoardContainer(board).classList.add(`${
|
|
1368
|
+
resizeHitTestRef = options.hitTest(point);
|
|
1369
|
+
if (resizeHitTestRef) {
|
|
1370
|
+
if (resizeHitTestRef.cursorClass) {
|
|
1371
|
+
PlaitBoard.getBoardContainer(board).classList.add(`${resizeHitTestRef.cursorClass}`);
|
|
1304
1372
|
}
|
|
1305
1373
|
startPoint = [event.x, event.y];
|
|
1374
|
+
const path = Array.isArray(resizeHitTestRef.element)
|
|
1375
|
+
? resizeHitTestRef.element.map(el => PlaitBoard.findPath(board, el))
|
|
1376
|
+
: PlaitBoard.findPath(board, resizeHitTestRef.element);
|
|
1306
1377
|
resizeRef = {
|
|
1307
|
-
path
|
|
1308
|
-
element:
|
|
1309
|
-
handle:
|
|
1378
|
+
path,
|
|
1379
|
+
element: resizeHitTestRef.element,
|
|
1380
|
+
handle: resizeHitTestRef.handle,
|
|
1381
|
+
handleIndex: resizeHitTestRef.handleIndex,
|
|
1382
|
+
rectangle: resizeHitTestRef.rectangle
|
|
1310
1383
|
};
|
|
1311
1384
|
preventTouchMove(board, event, true);
|
|
1312
1385
|
// prevent text from being selected when user pressed shift and pointer down
|
|
@@ -1320,7 +1393,7 @@ const withResize = (board, options) => {
|
|
|
1320
1393
|
pointerMove(event);
|
|
1321
1394
|
return;
|
|
1322
1395
|
}
|
|
1323
|
-
if (startPoint &&
|
|
1396
|
+
if (startPoint && resizeHitTestRef && !isResizing(board)) {
|
|
1324
1397
|
// prevent text from being selected
|
|
1325
1398
|
event.preventDefault();
|
|
1326
1399
|
const endPoint = [event.x, event.y];
|
|
@@ -1331,51 +1404,55 @@ const withResize = (board, options) => {
|
|
|
1331
1404
|
options.beforeResize && options.beforeResize(resizeRef);
|
|
1332
1405
|
}
|
|
1333
1406
|
}
|
|
1334
|
-
if (isResizing(board) &&
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1407
|
+
if (!isResizing(board) && !isDragging(board)) {
|
|
1408
|
+
const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
1409
|
+
throttleRAF(board, options.key + '-common-resize-hit-test', () => {
|
|
1410
|
+
const hitTestRef = options.hitTest(point);
|
|
1411
|
+
if (hitTestRef) {
|
|
1412
|
+
if (hoverHitTestRef && hitTestRef.cursorClass !== hoverHitTestRef.cursorClass) {
|
|
1413
|
+
PlaitBoard.getBoardContainer(board).classList.remove(`${hoverHitTestRef.cursorClass}`);
|
|
1414
|
+
}
|
|
1415
|
+
hoverHitTestRef = hitTestRef;
|
|
1416
|
+
if (hoverHitTestRef.cursorClass) {
|
|
1417
|
+
PlaitBoard.getBoardContainer(board).classList.add(`${hoverHitTestRef.cursorClass}`);
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
else {
|
|
1421
|
+
if (hoverHitTestRef) {
|
|
1422
|
+
if (hoverHitTestRef.cursorClass) {
|
|
1423
|
+
PlaitBoard.getBoardContainer(board).classList.remove(`${hoverHitTestRef.cursorClass}`);
|
|
1424
|
+
}
|
|
1425
|
+
hoverHitTestRef = null;
|
|
1426
|
+
}
|
|
1345
1427
|
}
|
|
1346
1428
|
});
|
|
1347
|
-
return;
|
|
1348
1429
|
}
|
|
1349
1430
|
else {
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
else {
|
|
1362
|
-
if (hoveDetectResult) {
|
|
1363
|
-
if (hoveDetectResult.cursorClass) {
|
|
1364
|
-
PlaitBoard.getBoardContainer(board).classList.remove(`${hoveDetectResult.cursorClass}`);
|
|
1431
|
+
if (startPoint && isResizing(board)) {
|
|
1432
|
+
event.preventDefault();
|
|
1433
|
+
const endPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
1434
|
+
throttleRAF(board, 'with-common-resize', () => {
|
|
1435
|
+
if (startPoint && resizeRef) {
|
|
1436
|
+
handleTouchTarget(board);
|
|
1437
|
+
options.onResize(resizeRef, {
|
|
1438
|
+
startPoint: toViewBoxPoint(board, toHostPoint(board, startPoint[0], startPoint[1])),
|
|
1439
|
+
endPoint,
|
|
1440
|
+
isShift: !!event.shiftKey
|
|
1441
|
+
});
|
|
1365
1442
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1443
|
+
});
|
|
1444
|
+
return;
|
|
1368
1445
|
}
|
|
1369
1446
|
}
|
|
1370
1447
|
pointerMove(event);
|
|
1371
1448
|
};
|
|
1372
1449
|
board.globalPointerUp = (event) => {
|
|
1373
1450
|
globalPointerUp(event);
|
|
1374
|
-
if (isResizing(board) ||
|
|
1375
|
-
options.
|
|
1451
|
+
if (isResizing(board) || resizeHitTestRef) {
|
|
1452
|
+
options.afterResize && options.afterResize(resizeRef);
|
|
1376
1453
|
removeResizing(board, options.key);
|
|
1377
1454
|
startPoint = null;
|
|
1378
|
-
|
|
1455
|
+
resizeHitTestRef = null;
|
|
1379
1456
|
resizeRef = null;
|
|
1380
1457
|
MERGING.set(board, false);
|
|
1381
1458
|
preventTouchMove(board, event, false);
|
|
@@ -1503,5 +1580,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1503
1580
|
* Generated bundle index. Do not edit.
|
|
1504
1581
|
*/
|
|
1505
1582
|
|
|
1506
|
-
export { AStar, ActiveGenerator, AlignTransform, BASE, BoardCreationMode, CommonPluginElement, DEFAULT_ROUTE_MARGIN, Generator, IS_RESIZING, ImageBaseComponent, ImageGenerator, MediaKeys, PICTURE_ACCEPTED_UPLOAD_SIZE, PRIMARY_COLOR, PointGraph, PointNode, PriorityQueue, PropertyTransforms, RESIZE_HANDLE_DIAMETER, ResizeHandle, TRANSPARENT, TextTransforms, WithCommonPluginKey, WithTextPluginKey, acceptImageTypes, addElementOfFocusedImage, addResizing, alignBottom, alignHorizontalCenter, alignLeft, alignRight, alignTop, alignVerticalCenter, buildImage, calculatePolylineLength, createGraph, distributeHorizontal, distributeVertical, generateElbowLineRoute, getCreationMode, getDirection, getDirectionBetweenPointAndPoint, getDirectionByPointOfRectangle, getDirectionByVector, getDirectionFactor, getEdgeCenter, getElementOfFocusedImage, getElementsText, getExtendPoint,
|
|
1583
|
+
export { AStar, ActiveGenerator, AlignTransform, BASE, BoardCreationMode, CommonPluginElement, DEFAULT_ROUTE_MARGIN, Generator, IS_RESIZING, ImageBaseComponent, ImageGenerator, MediaKeys, PICTURE_ACCEPTED_UPLOAD_SIZE, PRIMARY_COLOR, PointGraph, PointNode, PriorityQueue, PropertyTransforms, RESIZE_HANDLE_DIAMETER, ResizeHandle, TRANSPARENT, TextTransforms, WithCommonPluginKey, WithTextPluginKey, acceptImageTypes, addElementOfFocusedImage, addResizing, alignBottom, alignHorizontalCenter, alignLeft, alignRight, alignTop, alignVerticalCenter, buildImage, calculatePolylineLength, createGraph, distributeHorizontal, distributeVertical, drawFillPrimaryHandle, drawHandle, drawPrimaryHandle, generateElbowLineRoute, getCreationMode, getCrossingPointsBetweenPointAndSegment, getDirection, getDirectionBetweenPointAndPoint, getDirectionByPointOfRectangle, getDirectionByVector, getDirectionFactor, getDirectionFactorByVectorComponent, getEdgeCenter, getElementOfFocusedImage, getElementsText, getExtendPoint, getFirstTextEditor, getFirstTextManage, getGraphPoints, getIndexByResizeHandle, getMemorizedLatest, getNextPoint, getOppositeDirection, getPointByUnitVectorAndVectorComponent, getPointByVector, getPointOnPolyline, getPoints, getRatioByPoint, getRectangleResizeHandleRefs, getResizeHandleByIndex, getResizeHandlePointByIndex, getSourceAndTargetOuterRectangle, getSymmetricHandleIndex, getTextEditors, getTextManages, getTextMarksByElement, getUnitVectorByPointAndPoint, hasAfterDraw, isCornerHandle, isDelete, isDndMode, isDrawingMode, isEdgeHandle, isEnterHotkey, isExpandHotkey, isPointOnSegment, isResizing, isResizingByCondition, isSourceAndTargetIntersect, isSpaceHotkey, isTabHotkey, isVirtualKey, memorizeLatest, normalizeShapePoints, reduceRouteMargin, removeDuplicatePoints, removeElementOfFocusedImage, removeResizing, rotateVectorAnti90, routeAdjust, selectImage, setCreationMode, setProperty, simplifyOrthogonalPoints, withResize };
|
|
1507
1584
|
//# sourceMappingURL=plait-common.mjs.map
|