Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/olive-streets-follow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@plait/draw': patch
---

fix multiple points align problem
fix straight line points align problem
fix connector point align problem
8 changes: 5 additions & 3 deletions packages/draw/src/constants/geometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,13 @@ export const MultipleTextGeometryTextKeys: { [key in GeometryShapes]?: string[]
[UMLSymbols.combinedFragment]: Object.keys(GeometryCommonTextKeys)
};

export const LINE_HIT_GEOMETRY_BUFFER = 10;
export const LINE_HIT_GEOMETRY_BUFFER = 4;

export const LINE_SNAPPING_BUFFER = 6;
export const LINE_SNAPPING_BUFFER = 4;

export const LINE_SNAPPING_CONNECTOR_BUFFER = 8;
export const LINE_SNAPPING_CONNECTOR_BUFFER = 4;

export const LINE_ALIGN_TOLERANCE = 4;

export const GEOMETRY_WITHOUT_TEXT = [
FlowchartSymbols.or,
Expand Down
2 changes: 0 additions & 2 deletions packages/draw/src/constants/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,4 @@ export const LINE_AUTO_COMPLETE_HOVERED_OPACITY = 1;

export const LINE_AUTO_COMPLETE_HOVERED_DIAMETER = 12;

export const LINE_ALIGN_TOLERANCE = 3;

export const LINE_TEXT = '文本';
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ArrowLineShape, PlaitArrowLine, PlaitShapeElement } from '../../interfa
import { getArrowLinePointers } from '../../constants';
import { isDrawingMode } from '@plait/common';
import { handleArrowLineCreating } from '../../utils/arrow-line/arrow-line-basic';
import { getSnappingShape } from '../../utils';
import { getSnappingRef, getSnappingShape } from '../../utils';

export const withArrowLineCreateByDraw = (board: PlaitBoard) => {
const { pointerDown, pointerMove, globalPointerUp, touchStart } = board;
Expand Down Expand Up @@ -45,6 +45,8 @@ export const withArrowLineCreateByDraw = (board: PlaitBoard) => {
const hitElement = getSnappingShape(board, point);
if (hitElement) {
sourceElement = hitElement;
const ref = getSnappingRef(board, hitElement, point);
start = ref.connectorPoint || ref.edgePoint;
}
}
pointerDown(event);
Expand Down
58 changes: 27 additions & 31 deletions packages/draw/src/plugins/arrow-line/with-arrow-line-resize.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Path, PlaitBoard, PlaitNode, Point } from '@plait/core';
import { createDebugGenerator, Path, PlaitBoard, PlaitNode, Point } from '@plait/core';
import { ResizeRef, ResizeState, WithResizeOptions, simplifyOrthogonalPoints, withResize } from '@plait/common';
import { getSelectedArrowLineElements } from '../../utils/selected';
import { getHitLineResizeHandleRef, LineResizeHandle } from '../../utils/position/line';
Expand All @@ -16,6 +16,8 @@ import { getHitConnection, getArrowLinePoints } from '../../utils/arrow-line/arr
import { getElbowLineRouteOptions } from '../../utils/arrow-line';
import { getSnappingShape } from '../../utils';

const debugGenerator = createDebugGenerator('debug:plait:arrow-line-resize');

export const withArrowLineResize = (board: PlaitBoard) => {
let elbowLineIndex: number | null;
let elbowLineDeleteCount: number | null;
Expand Down Expand Up @@ -62,50 +64,38 @@ export const withArrowLineResize = (board: PlaitBoard) => {
elbowSourcePoint = pointsOnElbow[0];
elbowTargetPoint = pointsOnElbow[pointsOnElbow.length - 1];
elbowNextRenderPoints = getNextRenderPoints(board, resizeRef.element, pointsOnElbow);

const value = getIndexAndDeleteCountByKeyPoint(board, resizeRef.element, [...points], elbowNextRenderPoints, handleIndex);
elbowLineIndex = value.index;
elbowLineDeleteCount = value.deleteCount;
}
},
onResize: (resizeRef: ResizeRef<PlaitArrowLine, LineResizeHandle>, resizeState: ResizeState) => {
const drawPoints = getArrowLinePoints(board, resizeRef.element);
let points: Point[] = [...resizeRef.element.points];
points[0] = drawPoints[0];
points[points.length - 1] = drawPoints[drawPoints.length - 1];
let source: ArrowLineHandle = { ...resizeRef.element.source };
let target: ArrowLineHandle = { ...resizeRef.element.target };
let handleIndex = resizeRef.handleIndex!;
const hitElement = getSnappingShape(board, resizeState.endPoint);
if (resizeRef.handle === LineResizeHandle.source || resizeRef.handle === LineResizeHandle.target) {
const object = resizeRef.handle === LineResizeHandle.source ? source : target;
// axis alignment relative to adjacent point, even when snapping to a shape
const neighborPoint = handleIndex === 0 ? points[1] : points[points.length - 2];
// TODO: need handle the neighbor point is not key point(it will moving along moving point)
// such as below case
// [
// [
// 341.2536906953894,
// 83.94690212817761
// ],
// [
// 492.8570148670465,
// 43.86424319286277
// ],
// [
// 492.8570148670465,
// 175.99593084572632
// ],
// [
// 661.8118177564218,
// 175.99593084572632
// ]
// ]
const alignedEndPoint = neighborPoint ? alignPoints(neighborPoint, resizeState.endPoint) : resizeState.endPoint;
points[handleIndex] = alignedEndPoint;
const handleObject = resizeRef.handle === LineResizeHandle.source ? source : target;
if (debugGenerator.isDebug()) {
debugGenerator.clear();
debugGenerator.drawCircles(board, points, 3, false);
debugGenerator.drawCircles(board, [resizeState.endPoint], 4, false, { fill: 'yellow' });
}
points[handleIndex] = resizeState.endPoint;
points[handleIndex] = alignPoints(points, points[handleIndex], handleIndex);
if (debugGenerator.isDebug()) {
debugGenerator.drawCircles(board, [points[handleIndex]], 2, false, { fill: 'green' });
}
if (hitElement) {
object.connection = getHitConnection(board, alignedEndPoint, hitElement);
object.boundId = hitElement.id;
handleObject.connection = getHitConnection(board, points[handleIndex], hitElement);
handleObject.boundId = hitElement.id;
} else {
object.connection = undefined;
object.boundId = undefined;
handleObject.connection = undefined;
handleObject.boundId = undefined;
}
} else {
if (resizeRef.element.shape === ArrowLineShape.elbow) {
Expand Down Expand Up @@ -141,6 +131,12 @@ export const withArrowLineResize = (board: PlaitBoard) => {
points[handleIndex] = resizeState.endPoint;
}
}
if (
resizeRef.element.shape !== ArrowLineShape.elbow ||
(resizeRef.element.shape === ArrowLineShape.elbow && points.length === 2)
) {
points[handleIndex] = alignPoints(points, points[handleIndex], handleIndex);
}
}
DrawTransforms.resizeArrowLine(board, { points, source, target }, resizeRef.path as Path);
},
Expand Down
15 changes: 11 additions & 4 deletions packages/draw/src/utils/arrow-line/arrow-line-basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
createRect,
distanceBetweenPointAndPoint,
catmullRomFitting,
setStrokeLinecap
setStrokeLinecap,
createDebugGenerator
} from '@plait/core';
import { pointsOnBezierCurves } from 'points-on-curve';
import {
Expand All @@ -37,7 +38,7 @@ import { getElementShape } from '../shape';
import { DefaultLineStyle, LINE_TEXT_SPACE } from '../../constants/line';
import { LINE_SNAPPING_CONNECTOR_BUFFER } from '../../constants';
import { getLineMemorizedLatest } from '../memorize';
import { alignPoints } from './arrow-line-resize';
import { alignPoint } from './arrow-line-resize';
import { getArrowLineHandleRefPair } from './arrow-line-common';
import { getElbowPoints } from './elbow';
import { drawArrowLineArrow } from './arrow-line-arrow';
Expand Down Expand Up @@ -205,6 +206,8 @@ export const Q2C = (points: Point[]) => {
return result;
};

const debugGenerator = createDebugGenerator('debug:plait:arrow-line-resize');

export const handleArrowLineCreating = (
board: PlaitBoard,
lineShape: ArrowLineShape,
Expand All @@ -214,7 +217,11 @@ export const handleArrowLineCreating = (
lineShapeG: SVGGElement,
options?: Pick<PlaitArrowLine, 'strokeColor' | 'strokeWidth'>
) => {
const alignedMovingPoint = alignPoints(sourcePoint, movingPoint);
if (debugGenerator.isDebug()) {
debugGenerator.clear();
debugGenerator.drawCircles(board, [sourcePoint], 3, false);
}
const alignedMovingPoint = alignPoint(sourcePoint, movingPoint);
const hitElement = getSnappingShape(board, alignedMovingPoint);
const targetConnection = hitElement ? getHitConnection(board, alignedMovingPoint, hitElement) : undefined;
const sourceConnection = sourceElement ? getHitConnection(board, sourcePoint, sourceElement) : undefined;
Expand All @@ -240,7 +247,7 @@ export const handleArrowLineCreating = (
);
const linePoints = getArrowLinePoints(board, temporaryLineElement);
const otherPoint = linePoints[0];
temporaryLineElement.points[1] = alignPoints(otherPoint, alignedMovingPoint);
temporaryLineElement.points[1] = alignPoint(otherPoint, alignedMovingPoint);
lineGenerator.processDrawing(temporaryLineElement, lineShapeG);
PlaitBoard.getElementTopHost(board).append(lineShapeG);
return temporaryLineElement;
Expand Down
21 changes: 16 additions & 5 deletions packages/draw/src/utils/arrow-line/arrow-line-resize.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ElbowLineRouteOptions, ResizeState, generateElbowLineRoute, removeDuplicatePoints, simplifyOrthogonalPoints } from '@plait/common';
import { PlaitBoard, Point, RectangleClient, createDebugGenerator } from '@plait/core';
import { LINE_ALIGN_TOLERANCE } from '../../constants/line';
import { getElbowLineRouteOptions, getArrowLineHandleRefPair } from './arrow-line-common';
import { PlaitArrowLine } from '../../interfaces';
import { LINE_ALIGN_TOLERANCE } from '../../constants/geometry';

const debugKey = 'debug:plait:line-mirror';
const debugGenerator = createDebugGenerator(debugKey);

export const alignPoints = (basePoint: Point, movingPoint: Point) => {
export const alignPoint = (basePoint: Point, movingPoint: Point) => {
const newPoint: Point = [...movingPoint];
if (Point.isVertical(newPoint, basePoint, LINE_ALIGN_TOLERANCE)) {
newPoint[0] = basePoint[0];
Expand All @@ -18,6 +18,17 @@ export const alignPoints = (basePoint: Point, movingPoint: Point) => {
return newPoint;
};

export const alignPoints = (basePoints: Point[], movingPoint: Point, targetIndex?: number) => {
let newMovingPoint: Point = [...movingPoint];
basePoints.forEach((basePoint, index) => {
if (index === targetIndex) {
return;
}
newMovingPoint = alignPoint(basePoint, newMovingPoint);
});
return newMovingPoint as Point;
};

export function getResizedPreviousAndNextPoint(nextRenderPoints: Point[], sourcePoint: Point, targetPoint: Point, handleIndex: number) {
const referencePoint: { previous: Point | null; next: Point | null } = {
previous: null,
Expand Down Expand Up @@ -97,8 +108,8 @@ export function getIndexAndDeleteCountByKeyPoint(
};
}
const midDataPoints = dataPoints.slice(1, -1);
const startIndex = midDataPoints.findIndex(item => Point.isEquals(item, startKeyPoint));
const endIndex = midDataPoints.findIndex(item => Point.isEquals(item, endKeyPoint));
const startIndex = midDataPoints.findIndex((item) => Point.isEquals(item, startKeyPoint));
const endIndex = midDataPoints.findIndex((item) => Point.isEquals(item, endKeyPoint));

if (Math.max(startIndex, endIndex) > -1) {
if (startIndex > -1 && endIndex > -1) {
Expand Down Expand Up @@ -167,7 +178,7 @@ export function getIndexAndDeleteCountByKeyPoint(
const nextDataPoints = [nextRenderPoints[0], ...midDataPoints, nextRenderPoints[nextRenderPoints.length - 1]];
const mirrorDataPoints = getMirrorDataPoints(board, nextDataPoints, nextKeyPoints, params);
for (let i = handleIndex - 1; i >= 0; i--) {
const previousIndex = mirrorDataPoints.slice(1, -1).findIndex(item => Point.isEquals(item, nextRenderPoints[i]));
const previousIndex = mirrorDataPoints.slice(1, -1).findIndex((item) => Point.isEquals(item, nextRenderPoints[i]));
if (previousIndex > -1) {
index = previousIndex + 1;
break;
Expand Down
22 changes: 3 additions & 19 deletions packages/draw/src/utils/position/geometry.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
import {
Ancestor,
PlaitBoard,
Point,
RectangleClient,
depthFirstRecursion,
getIsRecursionFunc,
rotatePoints,
rotateAntiPointsByElement,
ResizeCursorClass
} from '@plait/core';
import { PlaitBoard, Point, RectangleClient, rotatePoints, ResizeCursorClass } from '@plait/core';
import {
RESIZE_HANDLE_DIAMETER,
getRectangleResizeHandleRefs,
Expand All @@ -17,12 +7,6 @@ import {
ROTATE_HANDLE_DISTANCE_TO_ELEMENT,
ResizeHandle
} from '@plait/common';
import { PlaitDrawElement, PlaitGeometry, PlaitShapeElement } from '../../interfaces';
import { isHitEdgeOfShape, isInsideOfShape } from '../hit';
import { LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER } from '../../constants/geometry';
import { getNearestPoint } from '../geometry';
import { getHitConnectorPoint } from '../arrow-line/arrow-line-basic';
import { getHitShape } from '../common';

export interface ResizeHandleRef {
rectangle: RectangleClient;
Expand All @@ -40,15 +24,15 @@ export const getHitRectangleResizeHandleRef = (
const resizeHandleRefs = getRectangleResizeHandleRefs(rectangle, RESIZE_HANDLE_DIAMETER);
if (angle) {
const rotatedPoint = rotatePoints([point], centerPoint, -angle)[0];
let result = resizeHandleRefs.find(resizeHandleRef => {
let result = resizeHandleRefs.find((resizeHandleRef) => {
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([rotatedPoint, rotatedPoint]), resizeHandleRef.rectangle);
});
if (result) {
result.cursorClass = getRotatedResizeCursorClassByAngle(result.cursorClass, angle);
}
return result;
} else {
return resizeHandleRefs.find(resizeHandleRef => {
return resizeHandleRefs.find((resizeHandleRef) => {
return RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), resizeHandleRef.rectangle);
});
}
Expand Down
4 changes: 2 additions & 2 deletions packages/draw/src/utils/vector-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PlaitBoard, Point, catmullRomFitting, createG, drawLinearPath, idCreato
import { PlaitVectorLine, VectorLineShape } from '../interfaces';
import { getLineMemorizedLatest } from './memorize';
import { DefaultLineStyle } from '../constants/line';
import { alignPoints } from './arrow-line';
import { alignPoint } from './arrow-line';
import { getStrokeWidthByElement } from './common';
import { getFillByElement, getStrokeColorByElement, getStrokeStyleByElement } from './style';
import { VectorLineShapeGenerator } from '../generators/vector-line-generator';
Expand Down Expand Up @@ -58,7 +58,7 @@ export const vectorLineCreating = (
...memorizedLatest
});
const otherPoint = points[points.length - 1];
temporaryLineElement.points[temporaryLineElement.points.length - 1] = alignPoints(otherPoint, movingPoint);
temporaryLineElement.points[temporaryLineElement.points.length - 1] = alignPoint(otherPoint, movingPoint);
lineGenerator.processDrawing(temporaryLineElement, lineShapeG);
PlaitBoard.getElementTopHost(board).append(lineShapeG);
return temporaryLineElement;
Expand Down
Loading