Browse Source

Inside detection for outline binding

Signed-off-by: Mark Tolmacs <[email protected]>
Mark Tolmacs 5 months ago
parent
commit
d6d4d00f60
2 changed files with 32 additions and 30 deletions
  1. 22 7
      packages/element/src/binding.ts
  2. 10 23
      packages/element/src/elbowArrow.ts

+ 22 - 7
packages/element/src/binding.ts

@@ -275,7 +275,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
   const endDragged = draggingPoints.findIndex((i) => i === endIdx) > -1;
   const start = startDragged
     ? isBindingEnabled
-      ? getElligibleElementForBindingElement(
+      ? getEligibleElementForBindingElement(
           selectedElement,
           "start",
           elementsMap,
@@ -285,7 +285,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
       : null // If binding is disabled and start is dragged, break all binds
     : !isElbowArrow(selectedElement)
     ? // We have to update the focus and gap of the binding, so let's rebind
-      getElligibleElementForBindingElement(
+      getEligibleElementForBindingElement(
         selectedElement,
         "start",
         elementsMap,
@@ -295,7 +295,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
     : "keep";
   const end = endDragged
     ? isBindingEnabled
-      ? getElligibleElementForBindingElement(
+      ? getEligibleElementForBindingElement(
           selectedElement,
           "end",
           elementsMap,
@@ -305,7 +305,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
       : null // If binding is disabled and end is dragged, break all binds
     : !isElbowArrow(selectedElement)
     ? // We have to update the focus and gap of the binding, so let's rebind
-      getElligibleElementForBindingElement(
+      getEligibleElementForBindingElement(
         selectedElement,
         "end",
         elementsMap,
@@ -336,7 +336,7 @@ const getBindingStrategyForDraggingArrowOrJoints = (
   );
   const start = startIsClose
     ? isBindingEnabled
-      ? getElligibleElementForBindingElement(
+      ? getEligibleElementForBindingElement(
           selectedElement,
           "start",
           elementsMap,
@@ -347,7 +347,7 @@ const getBindingStrategyForDraggingArrowOrJoints = (
     : null;
   const end = endIsClose
     ? isBindingEnabled
-      ? getElligibleElementForBindingElement(
+      ? getEligibleElementForBindingElement(
           selectedElement,
           "end",
           elementsMap,
@@ -903,6 +903,13 @@ export const bindPointToSnapToElementOutline = (
   );
   const edgePoint = avoidRectangularCorner(bindableElement, p);
 
+  const otherPointIdx =
+    startOrEnd === "start" ? linearElement.points.length - 1 : 0;
+  const otherPoint = pointFrom<GlobalPoint>(
+    linearElement.x + linearElement.points[otherPointIdx][0],
+    linearElement.y + linearElement.points[otherPointIdx][1],
+  );
+
   const adjacentPointIdx =
     startOrEnd === "start" ? 1 : linearElement.points.length - 2;
   const adjacentPoint =
@@ -968,6 +975,14 @@ export const bindPointToSnapToElementOutline = (
     return edgePoint;
   }
 
+  const shape = getElementShape(bindableElement, elementsMap);
+  const pointInShape = isPointInShape(edgePoint, shape);
+  const otherPointInShape = isPointInShape(otherPoint, shape);
+
+  if (pointInShape && otherPointInShape) {
+    return edgePoint;
+  }
+
   if (elbowed) {
     const scalar =
       pointDistanceSq(edgePoint, center) -
@@ -1379,7 +1394,7 @@ export const calculateFixedPointForElbowArrowBinding = (
   };
 };
 
-const getElligibleElementForBindingElement = (
+const getEligibleElementForBindingElement = (
   linearElement: NonDeleted<ExcalidrawLinearElement>,
   startOrEnd: "start" | "end",
   elementsMap: NonDeletedSceneElementsMap,

+ 10 - 23
packages/element/src/elbowArrow.ts

@@ -63,7 +63,6 @@ import type {
   ExcalidrawBindableElement,
   FixedPointBinding,
   FixedSegment,
-  NonDeletedExcalidrawElement,
 } from "./types";
 
 type GridAddress = [number, number] & { _brand: "gridaddress" };
@@ -1221,18 +1220,22 @@ const getElbowArrowData = (
   if (options?.isDragging) {
     const elements = Array.from(elementsMap.values());
     hoveredStartElement =
-      getHoveredElement(
-        origStartGlobalPoint,
-        elementsMap,
+      getHoveredElementForBinding(
+        tupleToCoors(origStartGlobalPoint),
         elements,
+        elementsMap,
         options?.zoom,
+        true,
+        true,
       ) || null;
     hoveredEndElement =
-      getHoveredElement(
-        origEndGlobalPoint,
-        elementsMap,
+      getHoveredElementForBinding(
+        tupleToCoors(origEndGlobalPoint),
         elements,
+        elementsMap,
         options?.zoom,
+        true,
+        true,
       ) || null;
   } else {
     hoveredStartElement = arrow.startBinding
@@ -2275,22 +2278,6 @@ const getBindPointHeading = (
     origPoint,
   );
 
-const getHoveredElement = (
-  origPoint: GlobalPoint,
-  elementsMap: NonDeletedSceneElementsMap,
-  elements: readonly NonDeletedExcalidrawElement[],
-  zoom?: AppState["zoom"],
-) => {
-  return getHoveredElementForBinding(
-    tupleToCoors(origPoint),
-    elements,
-    elementsMap,
-    zoom,
-    true,
-    true,
-  );
-};
-
 const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean =>
   a[0] === b[0] && a[1] === b[1];