do not split points on de-polygonizing & highlight overlapping points
This commit is contained in:
parent
eb619f8fde
commit
a7b4b08e86
@ -422,53 +422,6 @@ export const toggleLinePolygonState = (
|
||||
firstPoint[1],
|
||||
);
|
||||
}
|
||||
} else if (element.loopLock) {
|
||||
// When toggling from loopLock=true to loopLock=false
|
||||
// We need to dislocate the end point by 15 points
|
||||
|
||||
// When loopLock is true, the last point is the same as the first point
|
||||
// We'll use the direction from second-to-last point to first point
|
||||
const firstPoint = updatedPoints[0];
|
||||
|
||||
if (updatedPoints.length >= 3) {
|
||||
const secondLastPoint = updatedPoints[updatedPoints.length - 2];
|
||||
|
||||
// Get direction from second-last to first
|
||||
const dx = firstPoint[0] - secondLastPoint[0];
|
||||
const dy = firstPoint[1] - secondLastPoint[1];
|
||||
|
||||
// Calculate perpendicular direction (rotate 90 degrees)
|
||||
// This creates a visible gap perpendicular to the line direction
|
||||
const perpDx = dy;
|
||||
const perpDy = -dx;
|
||||
|
||||
// Normalize the perpendicular direction vector
|
||||
const perpLength = Math.sqrt(perpDx * perpDx + perpDy * perpDy);
|
||||
let normalizedPerpDx = 0;
|
||||
let normalizedPerpDy = 0;
|
||||
|
||||
if (perpLength > 0) {
|
||||
normalizedPerpDx = perpDx / perpLength;
|
||||
normalizedPerpDy = perpDy / perpLength;
|
||||
} else {
|
||||
// Default perpendicular if points are the same
|
||||
normalizedPerpDx = -0.7071;
|
||||
normalizedPerpDy = 0.7071;
|
||||
}
|
||||
|
||||
// Move the end point perpendicular to the line direction
|
||||
updatedPoints[updatedPoints.length - 1] = pointFrom(
|
||||
firstPoint[0] + normalizedPerpDx * 15,
|
||||
firstPoint[1] + normalizedPerpDy * 15,
|
||||
);
|
||||
} else {
|
||||
// For simple lines with fewer than 3 points
|
||||
// Just move away from the first point at a 45-degree angle
|
||||
updatedPoints[updatedPoints.length - 1] = pointFrom(
|
||||
firstPoint[0] + 10.6,
|
||||
firstPoint[1] - 10.6, // Different direction to avoid crossing
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -8,11 +8,14 @@ export const fillCircle = (
|
||||
cx: number,
|
||||
cy: number,
|
||||
radius: number,
|
||||
stroke = true,
|
||||
stroke: boolean,
|
||||
fill = true,
|
||||
) => {
|
||||
context.beginPath();
|
||||
context.arc(cx, cy, radius, 0, Math.PI * 2);
|
||||
context.fill();
|
||||
if (fill) {
|
||||
context.fill();
|
||||
}
|
||||
if (stroke) {
|
||||
context.stroke();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import oc from "open-color";
|
||||
import {
|
||||
pointFrom,
|
||||
pointsEqual,
|
||||
type GlobalPoint,
|
||||
type LocalPoint,
|
||||
type Radians,
|
||||
@ -32,6 +33,7 @@ import {
|
||||
isFrameLikeElement,
|
||||
isImageElement,
|
||||
isLinearElement,
|
||||
isLineElement,
|
||||
isTextElement,
|
||||
} from "@excalidraw/element/typeChecks";
|
||||
|
||||
@ -217,7 +219,8 @@ const renderSingleLinearPoint = <Point extends GlobalPoint | LocalPoint>(
|
||||
point: Point,
|
||||
radius: number,
|
||||
isSelected: boolean,
|
||||
isPhantomPoint = false,
|
||||
isPhantomPoint: boolean,
|
||||
isOverlappingPoint: boolean,
|
||||
) => {
|
||||
context.strokeStyle = "#5e5ad8";
|
||||
context.setLineDash([]);
|
||||
@ -232,8 +235,9 @@ const renderSingleLinearPoint = <Point extends GlobalPoint | LocalPoint>(
|
||||
context,
|
||||
point[0],
|
||||
point[1],
|
||||
radius / appState.zoom.value,
|
||||
(isOverlappingPoint ? radius * 2 : radius) / appState.zoom.value,
|
||||
!isPhantomPoint,
|
||||
!isOverlappingPoint,
|
||||
);
|
||||
};
|
||||
|
||||
@ -345,7 +349,7 @@ const renderBindingHighlightForSuggestedPointBinding = (
|
||||
index,
|
||||
elementsMap,
|
||||
);
|
||||
fillCircle(context, x, y, threshold);
|
||||
fillCircle(context, x, y, threshold, true);
|
||||
});
|
||||
};
|
||||
|
||||
@ -532,15 +536,36 @@ const renderLinearPointHandles = (
|
||||
const radius = appState.editingLinearElement
|
||||
? POINT_HANDLE_SIZE
|
||||
: POINT_HANDLE_SIZE / 2;
|
||||
|
||||
const _isElbowArrow = isElbowArrow(element);
|
||||
const _isLineElement = isLineElement(element);
|
||||
|
||||
points.forEach((point, idx) => {
|
||||
if (isElbowArrow(element) && idx !== 0 && idx !== points.length - 1) {
|
||||
if (_isElbowArrow && idx !== 0 && idx !== points.length - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isSelected =
|
||||
!!appState.editingLinearElement?.selectedPointsIndices?.includes(idx);
|
||||
|
||||
renderSingleLinearPoint(context, appState, point, radius, isSelected);
|
||||
const isOverlappingPoint =
|
||||
idx > 0 &&
|
||||
(idx !== points.length - 1 || !_isLineElement || !element.loopLock) &&
|
||||
pointsEqual(
|
||||
point,
|
||||
idx === points.length - 1 ? points[0] : points[idx - 1],
|
||||
2 / appState.zoom.value,
|
||||
);
|
||||
|
||||
renderSingleLinearPoint(
|
||||
context,
|
||||
appState,
|
||||
point,
|
||||
radius,
|
||||
isSelected,
|
||||
false,
|
||||
isOverlappingPoint,
|
||||
);
|
||||
});
|
||||
|
||||
// Rendering segment mid points
|
||||
@ -567,6 +592,7 @@ const renderLinearPointHandles = (
|
||||
POINT_HANDLE_SIZE / 2,
|
||||
false,
|
||||
!fixedSegments.includes(idx + 1),
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -590,6 +616,7 @@ const renderLinearPointHandles = (
|
||||
POINT_HANDLE_SIZE / 2,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -616,7 +643,7 @@ const renderTransformHandles = (
|
||||
context.strokeStyle = renderConfig.selectionColor;
|
||||
}
|
||||
if (key === "rotation") {
|
||||
fillCircle(context, x + width / 2, y + height / 2, width / 2);
|
||||
fillCircle(context, x + width / 2, y + height / 2, width / 2, true);
|
||||
// prefer round corners if roundRect API is available
|
||||
} else if (context.roundRect) {
|
||||
context.beginPath();
|
||||
|
@ -91,9 +91,10 @@ export function isPoint(p: unknown): p is LocalPoint | GlobalPoint {
|
||||
export function pointsEqual<Point extends GlobalPoint | LocalPoint>(
|
||||
a: Point,
|
||||
b: Point,
|
||||
tolerance: number = PRECISION,
|
||||
): boolean {
|
||||
const abs = Math.abs;
|
||||
return abs(a[0] - b[0]) < PRECISION && abs(a[1] - b[1]) < PRECISION;
|
||||
return abs(a[0] - b[0]) < tolerance && abs(a[1] - b[1]) < tolerance;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user