90% inside center binding

This commit is contained in:
Mark Tolmacs
2025-08-11 17:12:51 +02:00
parent e183c29178
commit 98702ace88

View File

@@ -399,7 +399,9 @@ const bindingStrategyForNewSimpleArrowEndpointDragging = (
// Inside -> outside binding // Inside -> outside binding
if (arrow.startBinding && arrow.startBinding.elementId !== hovered?.id) { if (arrow.startBinding && arrow.startBinding.elementId !== hovered?.id) {
const otherElement = elementsMap.get(arrow.startBinding.elementId); const otherElement = elementsMap.get(
arrow.startBinding.elementId,
) as ExcalidrawBindableElement;
invariant(otherElement, "Other element must be in the elements map"); invariant(otherElement, "Other element must be in the elements map");
const otherIsInsideBinding = const otherIsInsideBinding =
@@ -413,18 +415,22 @@ const bindingStrategyForNewSimpleArrowEndpointDragging = (
); );
const other: BindingStrategy = { const other: BindingStrategy = {
mode: otherIsInsideBinding ? "inside" : "orbit", mode: otherIsInsideBinding ? "inside" : "orbit",
element: otherElement as ExcalidrawBindableElement, element: otherElement,
focusPoint: arrowOriginalStartPoint, focusPoint: snapToCenter(
otherElement,
elementsMap,
arrowOriginalStartPoint,
),
}; };
let current: BindingStrategy;
// We are hovering another element with the end point // We are hovering another element with the end point
let current: BindingStrategy;
if (hovered) { if (hovered) {
const isInsideBinding = globalBindMode === "inside"; const isInsideBinding = globalBindMode === "inside";
current = { current = {
mode: isInsideBinding ? "inside" : "orbit", mode: isInsideBinding ? "inside" : "orbit",
element: hovered, element: hovered,
focusPoint: point, focusPoint: snapToCenter(hovered, elementsMap, point),
}; };
} else { } else {
current = { mode: null }; current = { mode: null };
@@ -1354,7 +1360,37 @@ export const snapToCenter = (
) => { ) => {
const extent = Math.min(element.width, element.height); const extent = Math.min(element.width, element.height);
const center = elementCenterPoint(element, elementsMap); const center = elementCenterPoint(element, elementsMap);
if (pointDistance(p, center) < extent * 0.05) { const nonRotated = pointRotateRads(p, center, -element.angle as Radians);
if (isRectanguloidElement(element)) {
if (
Math.abs(nonRotated[0] - (element.x + element.width / 2)) >
element.width * 0.9 ||
Math.abs(nonRotated[1] - (element.y + element.height / 2)) >
element.height * 0.9
) {
return pointFrom<GlobalPoint>(center[0], center[1]);
}
}
if (element.type === "diamond") {
const center = elementCenterPoint(element, elementsMap);
const nonRotated = pointRotateRads(p, center, -element.angle as Radians);
const cx = element.x + element.width / 2;
const cy = element.y + element.height / 2;
const scale = 0.9; // 90% sized inner diamond
const halfW = (element.width / 2) * scale;
const halfH = (element.height / 2) * scale;
if (halfW > 0 && halfH > 0) {
const dx = Math.abs(nonRotated[0] - cx);
const dy = Math.abs(nonRotated[1] - cy);
if (dx / halfW + dy / halfH <= 1) {
return pointFrom<GlobalPoint>(center[0], center[1]);
}
}
}
if (pointDistance(nonRotated, center) < extent * 0.5) {
return pointFrom<GlobalPoint>(center[0], center[1]); return pointFrom<GlobalPoint>(center[0], center[1]);
} }
return p; return p;