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],
|
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 {
|
return {
|
||||||
|
@ -8,11 +8,14 @@ export const fillCircle = (
|
|||||||
cx: number,
|
cx: number,
|
||||||
cy: number,
|
cy: number,
|
||||||
radius: number,
|
radius: number,
|
||||||
stroke = true,
|
stroke: boolean,
|
||||||
|
fill = true,
|
||||||
) => {
|
) => {
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
context.arc(cx, cy, radius, 0, Math.PI * 2);
|
context.arc(cx, cy, radius, 0, Math.PI * 2);
|
||||||
|
if (fill) {
|
||||||
context.fill();
|
context.fill();
|
||||||
|
}
|
||||||
if (stroke) {
|
if (stroke) {
|
||||||
context.stroke();
|
context.stroke();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import oc from "open-color";
|
import oc from "open-color";
|
||||||
import {
|
import {
|
||||||
pointFrom,
|
pointFrom,
|
||||||
|
pointsEqual,
|
||||||
type GlobalPoint,
|
type GlobalPoint,
|
||||||
type LocalPoint,
|
type LocalPoint,
|
||||||
type Radians,
|
type Radians,
|
||||||
@ -32,6 +33,7 @@ import {
|
|||||||
isFrameLikeElement,
|
isFrameLikeElement,
|
||||||
isImageElement,
|
isImageElement,
|
||||||
isLinearElement,
|
isLinearElement,
|
||||||
|
isLineElement,
|
||||||
isTextElement,
|
isTextElement,
|
||||||
} from "@excalidraw/element/typeChecks";
|
} from "@excalidraw/element/typeChecks";
|
||||||
|
|
||||||
@ -217,7 +219,8 @@ const renderSingleLinearPoint = <Point extends GlobalPoint | LocalPoint>(
|
|||||||
point: Point,
|
point: Point,
|
||||||
radius: number,
|
radius: number,
|
||||||
isSelected: boolean,
|
isSelected: boolean,
|
||||||
isPhantomPoint = false,
|
isPhantomPoint: boolean,
|
||||||
|
isOverlappingPoint: boolean,
|
||||||
) => {
|
) => {
|
||||||
context.strokeStyle = "#5e5ad8";
|
context.strokeStyle = "#5e5ad8";
|
||||||
context.setLineDash([]);
|
context.setLineDash([]);
|
||||||
@ -232,8 +235,9 @@ const renderSingleLinearPoint = <Point extends GlobalPoint | LocalPoint>(
|
|||||||
context,
|
context,
|
||||||
point[0],
|
point[0],
|
||||||
point[1],
|
point[1],
|
||||||
radius / appState.zoom.value,
|
(isOverlappingPoint ? radius * 2 : radius) / appState.zoom.value,
|
||||||
!isPhantomPoint,
|
!isPhantomPoint,
|
||||||
|
!isOverlappingPoint,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -345,7 +349,7 @@ const renderBindingHighlightForSuggestedPointBinding = (
|
|||||||
index,
|
index,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
);
|
);
|
||||||
fillCircle(context, x, y, threshold);
|
fillCircle(context, x, y, threshold, true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -532,15 +536,36 @@ const renderLinearPointHandles = (
|
|||||||
const radius = appState.editingLinearElement
|
const radius = appState.editingLinearElement
|
||||||
? POINT_HANDLE_SIZE
|
? POINT_HANDLE_SIZE
|
||||||
: POINT_HANDLE_SIZE / 2;
|
: POINT_HANDLE_SIZE / 2;
|
||||||
|
|
||||||
|
const _isElbowArrow = isElbowArrow(element);
|
||||||
|
const _isLineElement = isLineElement(element);
|
||||||
|
|
||||||
points.forEach((point, idx) => {
|
points.forEach((point, idx) => {
|
||||||
if (isElbowArrow(element) && idx !== 0 && idx !== points.length - 1) {
|
if (_isElbowArrow && idx !== 0 && idx !== points.length - 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSelected =
|
const isSelected =
|
||||||
!!appState.editingLinearElement?.selectedPointsIndices?.includes(idx);
|
!!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
|
// Rendering segment mid points
|
||||||
@ -567,6 +592,7 @@ const renderLinearPointHandles = (
|
|||||||
POINT_HANDLE_SIZE / 2,
|
POINT_HANDLE_SIZE / 2,
|
||||||
false,
|
false,
|
||||||
!fixedSegments.includes(idx + 1),
|
!fixedSegments.includes(idx + 1),
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -590,6 +616,7 @@ const renderLinearPointHandles = (
|
|||||||
POINT_HANDLE_SIZE / 2,
|
POINT_HANDLE_SIZE / 2,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -616,7 +643,7 @@ const renderTransformHandles = (
|
|||||||
context.strokeStyle = renderConfig.selectionColor;
|
context.strokeStyle = renderConfig.selectionColor;
|
||||||
}
|
}
|
||||||
if (key === "rotation") {
|
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
|
// prefer round corners if roundRect API is available
|
||||||
} else if (context.roundRect) {
|
} else if (context.roundRect) {
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
|
@ -91,9 +91,10 @@ export function isPoint(p: unknown): p is LocalPoint | GlobalPoint {
|
|||||||
export function pointsEqual<Point extends GlobalPoint | LocalPoint>(
|
export function pointsEqual<Point extends GlobalPoint | LocalPoint>(
|
||||||
a: Point,
|
a: Point,
|
||||||
b: Point,
|
b: Point,
|
||||||
|
tolerance: number = PRECISION,
|
||||||
): boolean {
|
): boolean {
|
||||||
const abs = Math.abs;
|
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