mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-23 17:30:44 +02:00
Fixed point binding for simple arrows
This commit is contained in:
@@ -88,8 +88,12 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
|
||||
"endArrowhead": "arrow",
|
||||
"endBinding": {
|
||||
"elementId": "ellipse-1",
|
||||
"focus": -0.007519379844961235,
|
||||
"gap": 11.562288374879595,
|
||||
"fixedPoint": [
|
||||
0.04,
|
||||
0.4633333333333333,
|
||||
],
|
||||
"focus": 0,
|
||||
"gap": 0,
|
||||
},
|
||||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
@@ -174,8 +178,12 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
|
||||
"startArrowhead": null,
|
||||
"startBinding": {
|
||||
"elementId": "diamond-1",
|
||||
"fixedPoint": [
|
||||
0.9357142857142857,
|
||||
0.5001,
|
||||
],
|
||||
"focus": 0,
|
||||
"gap": 4.535423522449215,
|
||||
"gap": 0,
|
||||
},
|
||||
"strokeColor": "#e67700",
|
||||
"strokeStyle": "solid",
|
||||
@@ -1539,8 +1547,12 @@ exports[`Test Transform > should transform the elements correctly when linear el
|
||||
"endArrowhead": "arrow",
|
||||
"endBinding": {
|
||||
"elementId": "B",
|
||||
"fixedPoint": [
|
||||
0.46387050630528887,
|
||||
0.48466257668711654,
|
||||
],
|
||||
"focus": 0,
|
||||
"gap": 32,
|
||||
"gap": 0,
|
||||
},
|
||||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
|
@@ -28,9 +28,14 @@ import { LinearElementEditor } from "@excalidraw/element";
|
||||
import { bumpVersion } from "@excalidraw/element";
|
||||
import { getContainerElement } from "@excalidraw/element";
|
||||
import { detectLineHeight } from "@excalidraw/element";
|
||||
import {
|
||||
isPointInElement,
|
||||
calculateFixedPointForNonElbowArrowBinding,
|
||||
} from "@excalidraw/element";
|
||||
import {
|
||||
isArrowBoundToElement,
|
||||
isArrowElement,
|
||||
isBindableElement,
|
||||
isElbowArrow,
|
||||
isFixedPointBinding,
|
||||
isLinearElement,
|
||||
@@ -521,6 +526,87 @@ const repairFrameMembership = (
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Migrates old PointBinding to FixedPointBinding for non-elbow arrows
|
||||
* when arrow endpoints are inside bindable shapes.
|
||||
*
|
||||
* NOTE mutates element.
|
||||
*/
|
||||
const migratePointBindingToFixedPoint = (
|
||||
element: Mutable<ExcalidrawElement>,
|
||||
elementsMap: Map<string, Mutable<ExcalidrawElement>>,
|
||||
) => {
|
||||
if (!isArrowElement(element) || isElbowArrow(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let shouldUpdateElement = false;
|
||||
let newStartBinding: FixedPointBinding | PointBinding | null =
|
||||
element.startBinding;
|
||||
let newEndBinding: FixedPointBinding | PointBinding | null =
|
||||
element.endBinding;
|
||||
|
||||
// Check start binding
|
||||
if (element.startBinding && !isFixedPointBinding(element.startBinding)) {
|
||||
const boundElement = elementsMap.get(element.startBinding.elementId);
|
||||
if (boundElement && isBindableElement(boundElement)) {
|
||||
const edgePoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||
element,
|
||||
0,
|
||||
elementsMap,
|
||||
);
|
||||
if (isPointInElement(edgePoint, boundElement, elementsMap)) {
|
||||
const { fixedPoint } = calculateFixedPointForNonElbowArrowBinding(
|
||||
element,
|
||||
boundElement,
|
||||
"start",
|
||||
elementsMap,
|
||||
);
|
||||
newStartBinding = {
|
||||
elementId: element.startBinding.elementId,
|
||||
focus: 0,
|
||||
gap: 0,
|
||||
fixedPoint,
|
||||
};
|
||||
shouldUpdateElement = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check end binding
|
||||
if (element.endBinding && !isFixedPointBinding(element.endBinding)) {
|
||||
const boundElement = elementsMap.get(element.endBinding.elementId);
|
||||
if (boundElement && isBindableElement(boundElement)) {
|
||||
const edgePoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||
element,
|
||||
-1,
|
||||
elementsMap,
|
||||
);
|
||||
if (isPointInElement(edgePoint, boundElement, elementsMap)) {
|
||||
const { fixedPoint } = calculateFixedPointForNonElbowArrowBinding(
|
||||
element,
|
||||
boundElement,
|
||||
"end",
|
||||
elementsMap,
|
||||
);
|
||||
newEndBinding = {
|
||||
elementId: element.endBinding.elementId,
|
||||
focus: 0,
|
||||
gap: 0,
|
||||
fixedPoint,
|
||||
};
|
||||
shouldUpdateElement = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldUpdateElement) {
|
||||
(element as Mutable<ExcalidrawLinearElement>).startBinding =
|
||||
newStartBinding;
|
||||
(element as Mutable<ExcalidrawLinearElement>).endBinding = newEndBinding;
|
||||
}
|
||||
};
|
||||
|
||||
export const restoreElements = (
|
||||
elements: ImportedDataState["elements"],
|
||||
/** NOTE doesn't serve for reconciliation */
|
||||
@@ -620,6 +706,9 @@ export const restoreElements = (
|
||||
(element as Mutable<ExcalidrawLinearElement>).endBinding = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate old PointBinding to FixedPointBinding for non-elbow arrows
|
||||
migratePointBindingToFixedPoint(element, restoredElementsMap);
|
||||
}
|
||||
|
||||
// NOTE (mtolmacs): Temporary fix for extremely large arrows
|
||||
|
@@ -194,7 +194,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
"groupIds": [],
|
||||
"height": "99.19972",
|
||||
"height": 150,
|
||||
"id": "id4",
|
||||
"index": "a2",
|
||||
"isDeleted": false,
|
||||
@@ -208,8 +208,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
0,
|
||||
],
|
||||
[
|
||||
"98.40611",
|
||||
"99.19972",
|
||||
"124.00500",
|
||||
150,
|
||||
],
|
||||
],
|
||||
"roughness": 1,
|
||||
@@ -224,7 +224,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 35,
|
||||
"width": "98.40611",
|
||||
"width": "124.00500",
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
}
|
||||
@@ -323,15 +323,15 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"focus": 0,
|
||||
"gap": 1,
|
||||
},
|
||||
"height": "68.58402",
|
||||
"height": "104.34908",
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
98,
|
||||
"68.58402",
|
||||
"124.00500",
|
||||
"104.34908",
|
||||
],
|
||||
],
|
||||
"startBinding": {
|
||||
@@ -347,7 +347,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"focus": "-0.02000",
|
||||
"gap": 1,
|
||||
},
|
||||
"height": "0.00656",
|
||||
"height": "0.00849",
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
@@ -355,7 +355,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
],
|
||||
[
|
||||
"98.00000",
|
||||
"-0.00656",
|
||||
"-0.00849",
|
||||
],
|
||||
],
|
||||
"startBinding": {
|
||||
@@ -398,15 +398,15 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
},
|
||||
"id4": {
|
||||
"deleted": {
|
||||
"height": "99.19972",
|
||||
"height": 150,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
"98.40611",
|
||||
"99.19972",
|
||||
"124.00500",
|
||||
150,
|
||||
],
|
||||
],
|
||||
"startBinding": null,
|
||||
@@ -414,15 +414,15 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
"height": "68.58402",
|
||||
"height": "104.34908",
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
98,
|
||||
"68.58402",
|
||||
"124.00500",
|
||||
"104.34908",
|
||||
],
|
||||
],
|
||||
"startBinding": {
|
||||
@@ -431,7 +431,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"gap": 1,
|
||||
},
|
||||
"version": 33,
|
||||
"y": "35.82151",
|
||||
"y": "45.65092",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1207,7 +1207,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
"groupIds": [],
|
||||
"height": "1.36342",
|
||||
"height": "49.99000",
|
||||
"id": "id4",
|
||||
"index": "Zz",
|
||||
"isDeleted": false,
|
||||
@@ -1221,8 +1221,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
0,
|
||||
],
|
||||
[
|
||||
98,
|
||||
"1.36342",
|
||||
"150.01000",
|
||||
"49.99000",
|
||||
],
|
||||
],
|
||||
"roughness": 1,
|
||||
@@ -1242,10 +1242,10 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 10,
|
||||
"width": 98,
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"version": 11,
|
||||
"width": "150.01000",
|
||||
"x": 0,
|
||||
"y": "0.01000",
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1569,7 +1569,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
"groupIds": [],
|
||||
"height": "1.36342",
|
||||
"height": "49.99000",
|
||||
"id": "id5",
|
||||
"index": "a0",
|
||||
"isDeleted": false,
|
||||
@@ -1583,8 +1583,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
0,
|
||||
],
|
||||
[
|
||||
98,
|
||||
"1.36342",
|
||||
"249.99000",
|
||||
"-49.99000",
|
||||
],
|
||||
],
|
||||
"roughness": 1,
|
||||
@@ -1605,9 +1605,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 11,
|
||||
"width": 98,
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"width": "249.99000",
|
||||
"x": "-49.99000",
|
||||
"y": 50,
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1719,7 +1719,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
"groupIds": [],
|
||||
"height": "1.36342",
|
||||
"height": "49.99000",
|
||||
"index": "a0",
|
||||
"isDeleted": false,
|
||||
"lastCommittedPoint": null,
|
||||
@@ -1732,8 +1732,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
0,
|
||||
],
|
||||
[
|
||||
98,
|
||||
"1.36342",
|
||||
"249.99000",
|
||||
"-49.99000",
|
||||
],
|
||||
],
|
||||
"roughness": 1,
|
||||
@@ -1753,9 +1753,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"version": 11,
|
||||
"width": 98,
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
"width": "249.99000",
|
||||
"x": "-49.99000",
|
||||
"y": 50,
|
||||
},
|
||||
"inserted": {
|
||||
"isDeleted": true,
|
||||
|
Reference in New Issue
Block a user