mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
fix: make arrow binding area adapt to zoom levels (#8927)
* make binding area adapt to zoom * revert stroke color * normalize binding gap * reduce normalized gap
This commit is contained in:
parent
873698a1a2
commit
1e3399eac8
14 changed files with 247 additions and 119 deletions
|
@ -161,6 +161,7 @@ export const actionDeleteSelected = register({
|
|||
element,
|
||||
selectedPointsIndices,
|
||||
elementsMap,
|
||||
appState.zoom,
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -153,6 +153,7 @@ const flipElements = (
|
|||
app.scene,
|
||||
isBindingEnabled(appState),
|
||||
[],
|
||||
appState.zoom,
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -1591,6 +1591,7 @@ export const actionChangeArrowType = register({
|
|||
tupleToCoors(startGlobalPoint),
|
||||
elements,
|
||||
elementsMap,
|
||||
appState.zoom,
|
||||
true,
|
||||
);
|
||||
const endHoveredElement =
|
||||
|
@ -1599,6 +1600,7 @@ export const actionChangeArrowType = register({
|
|||
tupleToCoors(endGlobalPoint),
|
||||
elements,
|
||||
elementsMap,
|
||||
appState.zoom,
|
||||
true,
|
||||
);
|
||||
const startElement = startHoveredElement
|
||||
|
|
|
@ -3215,6 +3215,10 @@ class App extends React.Component<AppProps, AppState> {
|
|||
),
|
||||
),
|
||||
[el.points[0], el.points[el.points.length - 1]],
|
||||
undefined,
|
||||
{
|
||||
zoom: this.state.zoom,
|
||||
},
|
||||
),
|
||||
};
|
||||
}
|
||||
|
@ -4372,6 +4376,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
|
||||
updateBoundElements(element, this.scene.getNonDeletedElementsMap(), {
|
||||
simultaneouslyUpdated: selectedElements,
|
||||
zoom: this.state.zoom,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -4381,6 +4386,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
(element) => element.id !== elbowArrow?.id || step !== 0,
|
||||
),
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
),
|
||||
});
|
||||
|
||||
|
@ -4596,6 +4602,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
this.scene,
|
||||
isBindingEnabled(this.state),
|
||||
this.state.selectedLinearElement?.selectedPointsIndices ?? [],
|
||||
this.state.zoom,
|
||||
);
|
||||
this.setState({ suggestedBindings: [] });
|
||||
}
|
||||
|
@ -5854,6 +5861,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
{
|
||||
isDragging: true,
|
||||
informMutation: false,
|
||||
zoom: this.state.zoom,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
@ -7401,6 +7409,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
pointerDownState.origin,
|
||||
this.scene.getNonDeletedElements(),
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
);
|
||||
|
||||
this.setState({
|
||||
|
@ -7698,6 +7707,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
pointerDownState.origin,
|
||||
this.scene.getNonDeletedElements(),
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
isElbowArrow(element),
|
||||
);
|
||||
|
||||
|
@ -8276,6 +8286,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
suggestedBindings: getSuggestedBindingsForArrows(
|
||||
selectedElements,
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
@ -8444,6 +8455,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
{
|
||||
isDragging: true,
|
||||
informMutation: false,
|
||||
zoom: this.state.zoom,
|
||||
},
|
||||
);
|
||||
} else if (points.length === 2) {
|
||||
|
@ -9408,6 +9420,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
this.scene,
|
||||
isBindingEnabled(this.state),
|
||||
this.state.selectedLinearElement?.selectedPointsIndices ?? [],
|
||||
this.state.zoom,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -9900,6 +9913,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
pointerCoords,
|
||||
this.scene.getNonDeletedElements(),
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
);
|
||||
this.setState({
|
||||
suggestedBindings:
|
||||
|
@ -9928,6 +9942,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
coords,
|
||||
this.scene.getNonDeletedElements(),
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
isArrowElement(linearElement) && isElbowArrow(linearElement),
|
||||
);
|
||||
if (
|
||||
|
@ -10569,6 +10584,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
const suggestedBindings = getSuggestedBindingsForArrows(
|
||||
selectedElements,
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
);
|
||||
|
||||
const elementsToHighlight = new Set<ExcalidrawElement>();
|
||||
|
|
|
@ -300,6 +300,7 @@ export const updateBindings = (
|
|||
options?: {
|
||||
simultaneouslyUpdated?: readonly ExcalidrawElement[];
|
||||
newSize?: { width: number; height: number };
|
||||
zoom?: AppState["zoom"];
|
||||
},
|
||||
) => {
|
||||
if (isLinearElement(latestElement)) {
|
||||
|
@ -310,6 +311,7 @@ export const updateBindings = (
|
|||
scene,
|
||||
true,
|
||||
[],
|
||||
options?.zoom,
|
||||
);
|
||||
} else {
|
||||
updateBoundElements(latestElement, elementsMap, options);
|
||||
|
|
|
@ -95,7 +95,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
|
|||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
"groupIds": [],
|
||||
"height": 35,
|
||||
"height": 33.519031369643244,
|
||||
"id": Any<String>,
|
||||
"index": "a2",
|
||||
"isDeleted": false,
|
||||
|
@ -109,8 +109,8 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
|
|||
0.5,
|
||||
],
|
||||
[
|
||||
394.5,
|
||||
34.5,
|
||||
382.47606040672997,
|
||||
34.019031369643244,
|
||||
],
|
||||
],
|
||||
"roughness": 1,
|
||||
|
@ -128,9 +128,9 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 4,
|
||||
"version": 7,
|
||||
"versionNonce": Any<Number>,
|
||||
"width": 395,
|
||||
"width": 381.97606040672997,
|
||||
"x": 247,
|
||||
"y": 420,
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
|
|||
0,
|
||||
],
|
||||
[
|
||||
399.5,
|
||||
389.5,
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -186,10 +186,10 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 4,
|
||||
"version": 6,
|
||||
"versionNonce": Any<Number>,
|
||||
"width": 400,
|
||||
"x": 227,
|
||||
"width": 390,
|
||||
"x": 237,
|
||||
"y": 450,
|
||||
}
|
||||
`;
|
||||
|
@ -319,7 +319,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
|
|||
"verticalAlign": "top",
|
||||
"width": 100,
|
||||
"x": 560,
|
||||
"y": 226.5,
|
||||
"y": 236.95454545454544,
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -339,13 +339,13 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
|
|||
"endBinding": {
|
||||
"elementId": "text-2",
|
||||
"fixedPoint": null,
|
||||
"focus": 0,
|
||||
"gap": 205,
|
||||
"focus": 1.625925925925924,
|
||||
"gap": 14,
|
||||
},
|
||||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
"groupIds": [],
|
||||
"height": 0,
|
||||
"height": 18.278619528619487,
|
||||
"id": Any<String>,
|
||||
"index": "a2",
|
||||
"isDeleted": false,
|
||||
|
@ -356,11 +356,11 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
|
|||
"points": [
|
||||
[
|
||||
0.5,
|
||||
0,
|
||||
-0.5,
|
||||
],
|
||||
[
|
||||
99.5,
|
||||
0,
|
||||
357.2037037037038,
|
||||
-17.778619528619487,
|
||||
],
|
||||
],
|
||||
"roughness": 1,
|
||||
|
@ -378,11 +378,11 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 4,
|
||||
"version": 6,
|
||||
"versionNonce": Any<Number>,
|
||||
"width": 100,
|
||||
"x": 255,
|
||||
"y": 239,
|
||||
"width": 357.7037037037038,
|
||||
"x": 171,
|
||||
"y": 249.45454545454544,
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -482,7 +482,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to shapes whe
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 4,
|
||||
"version": 6,
|
||||
"versionNonce": Any<Number>,
|
||||
"width": 100,
|
||||
"x": 255,
|
||||
|
@ -660,7 +660,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 4,
|
||||
"version": 6,
|
||||
"versionNonce": Any<Number>,
|
||||
"width": 100,
|
||||
"x": 255,
|
||||
|
@ -1505,7 +1505,7 @@ exports[`Test Transform > should transform the elements correctly when linear el
|
|||
0,
|
||||
],
|
||||
[
|
||||
272.485,
|
||||
270.98528125,
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -1526,10 +1526,10 @@ exports[`Test Transform > should transform the elements correctly when linear el
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 4,
|
||||
"version": 7,
|
||||
"versionNonce": Any<Number>,
|
||||
"width": 272.985,
|
||||
"x": 111.262,
|
||||
"width": 270.48528125,
|
||||
"x": 112.76171875,
|
||||
"y": 57,
|
||||
}
|
||||
`;
|
||||
|
@ -1587,11 +1587,11 @@ exports[`Test Transform > should transform the elements correctly when linear el
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 4,
|
||||
"version": 6,
|
||||
"versionNonce": Any<Number>,
|
||||
"width": 0,
|
||||
"x": 77.017,
|
||||
"y": 79,
|
||||
"x": 83.015625,
|
||||
"y": 81.5,
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
@ -779,7 +779,7 @@ describe("Test Transform", () => {
|
|||
elementId: "rect-1",
|
||||
fixedPoint: null,
|
||||
focus: 0,
|
||||
gap: 205,
|
||||
gap: 14,
|
||||
});
|
||||
expect(rect.boundElements).toStrictEqual([
|
||||
{
|
||||
|
|
|
@ -40,7 +40,6 @@ import {
|
|||
isBoundToContainer,
|
||||
isElbowArrow,
|
||||
isFixedPointBinding,
|
||||
isFrameLikeElement,
|
||||
isLinearElement,
|
||||
isRectangularElement,
|
||||
isTextElement,
|
||||
|
@ -97,6 +96,8 @@ export const isBindingEnabled = (appState: AppState): boolean => {
|
|||
};
|
||||
|
||||
export const FIXED_BINDING_DISTANCE = 5;
|
||||
export const BINDING_HIGHLIGHT_THICKNESS = 10;
|
||||
export const BINDING_HIGHLIGHT_OFFSET = 4;
|
||||
|
||||
const getNonDeletedElements = (
|
||||
scene: Scene,
|
||||
|
@ -213,6 +214,7 @@ const getOriginalBindingIfStillCloseOfLinearElementEdge = (
|
|||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||
edge: "start" | "end",
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
): NonDeleted<ExcalidrawElement> | null => {
|
||||
const coors = getLinearElementEdgeCoors(linearElement, edge, elementsMap);
|
||||
const elementId =
|
||||
|
@ -223,7 +225,7 @@ const getOriginalBindingIfStillCloseOfLinearElementEdge = (
|
|||
const element = elementsMap.get(elementId);
|
||||
if (
|
||||
isBindableElement(element) &&
|
||||
bindingBorderTest(element, coors, elementsMap)
|
||||
bindingBorderTest(element, coors, elementsMap, zoom)
|
||||
) {
|
||||
return element;
|
||||
}
|
||||
|
@ -235,12 +237,14 @@ const getOriginalBindingIfStillCloseOfLinearElementEdge = (
|
|||
const getOriginalBindingsIfStillCloseToArrowEnds = (
|
||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
): (NonDeleted<ExcalidrawElement> | null)[] =>
|
||||
["start", "end"].map((edge) =>
|
||||
getOriginalBindingIfStillCloseOfLinearElementEdge(
|
||||
linearElement,
|
||||
edge as "start" | "end",
|
||||
elementsMap,
|
||||
zoom,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -250,6 +254,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
|
|||
draggingPoints: readonly number[],
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
zoom?: AppState["zoom"],
|
||||
): (NonDeleted<ExcalidrawBindableElement> | null | "keep")[] => {
|
||||
const startIdx = 0;
|
||||
const endIdx = selectedElement.points.length - 1;
|
||||
|
@ -262,6 +267,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
|
|||
"start",
|
||||
elementsMap,
|
||||
elements,
|
||||
zoom,
|
||||
)
|
||||
: null // If binding is disabled and start is dragged, break all binds
|
||||
: // We have to update the focus and gap of the binding, so let's rebind
|
||||
|
@ -270,6 +276,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
|
|||
"start",
|
||||
elementsMap,
|
||||
elements,
|
||||
zoom,
|
||||
);
|
||||
const end = endDragged
|
||||
? isBindingEnabled
|
||||
|
@ -278,6 +285,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
|
|||
"end",
|
||||
elementsMap,
|
||||
elements,
|
||||
zoom,
|
||||
)
|
||||
: null // If binding is disabled and end is dragged, break all binds
|
||||
: // We have to update the focus and gap of the binding, so let's rebind
|
||||
|
@ -286,6 +294,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
|
|||
"end",
|
||||
elementsMap,
|
||||
elements,
|
||||
zoom,
|
||||
);
|
||||
|
||||
return [start, end];
|
||||
|
@ -296,10 +305,12 @@ const getBindingStrategyForDraggingArrowOrJoints = (
|
|||
elementsMap: NonDeletedSceneElementsMap,
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
isBindingEnabled: boolean,
|
||||
zoom?: AppState["zoom"],
|
||||
): (NonDeleted<ExcalidrawBindableElement> | null | "keep")[] => {
|
||||
const [startIsClose, endIsClose] = getOriginalBindingsIfStillCloseToArrowEnds(
|
||||
selectedElement,
|
||||
elementsMap,
|
||||
zoom,
|
||||
);
|
||||
const start = startIsClose
|
||||
? isBindingEnabled
|
||||
|
@ -308,6 +319,7 @@ const getBindingStrategyForDraggingArrowOrJoints = (
|
|||
"start",
|
||||
elementsMap,
|
||||
elements,
|
||||
zoom,
|
||||
)
|
||||
: null
|
||||
: null;
|
||||
|
@ -318,6 +330,7 @@ const getBindingStrategyForDraggingArrowOrJoints = (
|
|||
"end",
|
||||
elementsMap,
|
||||
elements,
|
||||
zoom,
|
||||
)
|
||||
: null
|
||||
: null;
|
||||
|
@ -332,6 +345,7 @@ export const bindOrUnbindLinearElements = (
|
|||
scene: Scene,
|
||||
isBindingEnabled: boolean,
|
||||
draggingPoints: readonly number[] | null,
|
||||
zoom?: AppState["zoom"],
|
||||
): void => {
|
||||
selectedElements.forEach((selectedElement) => {
|
||||
const [start, end] = draggingPoints?.length
|
||||
|
@ -342,6 +356,7 @@ export const bindOrUnbindLinearElements = (
|
|||
draggingPoints ?? [],
|
||||
elementsMap,
|
||||
elements,
|
||||
zoom,
|
||||
)
|
||||
: // The arrow itself (the shaft) or the inner joins are dragged
|
||||
getBindingStrategyForDraggingArrowOrJoints(
|
||||
|
@ -349,6 +364,7 @@ export const bindOrUnbindLinearElements = (
|
|||
elementsMap,
|
||||
elements,
|
||||
isBindingEnabled,
|
||||
zoom,
|
||||
);
|
||||
|
||||
bindOrUnbindLinearElement(selectedElement, start, end, elementsMap, scene);
|
||||
|
@ -358,6 +374,7 @@ export const bindOrUnbindLinearElements = (
|
|||
export const getSuggestedBindingsForArrows = (
|
||||
selectedElements: NonDeleted<ExcalidrawElement>[],
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom: AppState["zoom"],
|
||||
): SuggestedBinding[] => {
|
||||
// HOT PATH: Bail out if selected elements list is too large
|
||||
if (selectedElements.length > 50) {
|
||||
|
@ -368,7 +385,7 @@ export const getSuggestedBindingsForArrows = (
|
|||
selectedElements
|
||||
.filter(isLinearElement)
|
||||
.flatMap((element) =>
|
||||
getOriginalBindingsIfStillCloseToArrowEnds(element, elementsMap),
|
||||
getOriginalBindingsIfStillCloseToArrowEnds(element, elementsMap, zoom),
|
||||
)
|
||||
.filter(
|
||||
(element): element is NonDeleted<ExcalidrawBindableElement> =>
|
||||
|
@ -406,6 +423,7 @@ export const maybeBindLinearElement = (
|
|||
pointerCoords,
|
||||
elements,
|
||||
elementsMap,
|
||||
appState.zoom,
|
||||
isElbowArrow(linearElement) && isElbowArrow(linearElement),
|
||||
);
|
||||
|
||||
|
@ -422,6 +440,26 @@ export const maybeBindLinearElement = (
|
|||
}
|
||||
};
|
||||
|
||||
const normalizePointBinding = (
|
||||
binding: { focus: number; gap: number },
|
||||
hoveredElement: ExcalidrawBindableElement,
|
||||
) => {
|
||||
let gap = binding.gap;
|
||||
const maxGap = maxBindingGap(
|
||||
hoveredElement,
|
||||
hoveredElement.width,
|
||||
hoveredElement.height,
|
||||
);
|
||||
|
||||
if (gap > maxGap) {
|
||||
gap = BINDING_HIGHLIGHT_THICKNESS + BINDING_HIGHLIGHT_OFFSET;
|
||||
}
|
||||
return {
|
||||
...binding,
|
||||
gap,
|
||||
};
|
||||
};
|
||||
|
||||
export const bindLinearElement = (
|
||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||
hoveredElement: ExcalidrawBindableElement,
|
||||
|
@ -433,12 +471,15 @@ export const bindLinearElement = (
|
|||
}
|
||||
const binding: PointBinding = {
|
||||
elementId: hoveredElement.id,
|
||||
...calculateFocusAndGap(
|
||||
...normalizePointBinding(
|
||||
calculateFocusAndGap(
|
||||
linearElement,
|
||||
hoveredElement,
|
||||
startOrEnd,
|
||||
elementsMap,
|
||||
),
|
||||
hoveredElement,
|
||||
),
|
||||
...(isElbowArrow(linearElement)
|
||||
? calculateFixedPointForElbowArrowBinding(
|
||||
linearElement,
|
||||
|
@ -462,6 +503,12 @@ export const bindLinearElement = (
|
|||
}),
|
||||
});
|
||||
}
|
||||
|
||||
// update bound elements to make sure the binding tips are in sync with
|
||||
// the normalized gap from above
|
||||
if (!isElbowArrow(linearElement)) {
|
||||
updateBoundElements(hoveredElement, elementsMap);
|
||||
}
|
||||
};
|
||||
|
||||
// Don't bind both ends of a simple segment
|
||||
|
@ -514,6 +561,7 @@ export const getHoveredElementForBinding = (
|
|||
},
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
fullShape?: boolean,
|
||||
): NonDeleted<ExcalidrawBindableElement> | null => {
|
||||
const hoveredElement = getElementAtPosition(
|
||||
|
@ -524,11 +572,13 @@ export const getHoveredElementForBinding = (
|
|||
element,
|
||||
pointerCoords,
|
||||
elementsMap,
|
||||
zoom,
|
||||
// disable fullshape snapping for frame elements so we
|
||||
// can bind to frame children
|
||||
fullShape && !isFrameLikeElement(element),
|
||||
fullShape,
|
||||
),
|
||||
);
|
||||
|
||||
return hoveredElement as NonDeleted<ExcalidrawBindableElement> | null;
|
||||
};
|
||||
|
||||
|
@ -578,9 +628,11 @@ export const updateBoundElements = (
|
|||
simultaneouslyUpdated?: readonly ExcalidrawElement[];
|
||||
newSize?: { width: number; height: number };
|
||||
changedElements?: Map<string, OrderedExcalidrawElement>;
|
||||
zoom?: AppState["zoom"];
|
||||
},
|
||||
) => {
|
||||
const { newSize, simultaneouslyUpdated, changedElements } = options ?? {};
|
||||
const { newSize, simultaneouslyUpdated, changedElements, zoom } =
|
||||
options ?? {};
|
||||
const simultaneouslyUpdatedElementIds = getSimultaneouslyUpdatedElementIds(
|
||||
simultaneouslyUpdated,
|
||||
);
|
||||
|
@ -670,6 +722,7 @@ export const updateBoundElements = (
|
|||
},
|
||||
{
|
||||
changedElements,
|
||||
zoom,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -703,6 +756,7 @@ export const getHeadingForElbowArrowSnap = (
|
|||
aabb: Bounds | undefined | null,
|
||||
elementsMap: ElementsMap,
|
||||
origPoint: GlobalPoint,
|
||||
zoom?: AppState["zoom"],
|
||||
): Heading => {
|
||||
const otherPointHeading = vectorToHeading(vectorFromPoint(otherPoint, p));
|
||||
|
||||
|
@ -714,6 +768,7 @@ export const getHeadingForElbowArrowSnap = (
|
|||
origPoint,
|
||||
bindableElement,
|
||||
elementsMap,
|
||||
zoom,
|
||||
);
|
||||
|
||||
if (!distance) {
|
||||
|
@ -737,6 +792,7 @@ const getDistanceForBinding = (
|
|||
point: Readonly<GlobalPoint>,
|
||||
bindableElement: ExcalidrawBindableElement,
|
||||
elementsMap: ElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
) => {
|
||||
const distance = distanceToBindableElement(
|
||||
bindableElement,
|
||||
|
@ -747,6 +803,7 @@ const getDistanceForBinding = (
|
|||
bindableElement,
|
||||
bindableElement.width,
|
||||
bindableElement.height,
|
||||
zoom,
|
||||
);
|
||||
|
||||
return distance > bindDistance ? null : distance;
|
||||
|
@ -1174,11 +1231,13 @@ const getElligibleElementForBindingElement = (
|
|||
startOrEnd: "start" | "end",
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
zoom?: AppState["zoom"],
|
||||
): NonDeleted<ExcalidrawBindableElement> | null => {
|
||||
return getHoveredElementForBinding(
|
||||
getLinearElementEdgeCoors(linearElement, startOrEnd, elementsMap),
|
||||
elements,
|
||||
elementsMap,
|
||||
zoom,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1341,9 +1400,11 @@ export const bindingBorderTest = (
|
|||
element: NonDeleted<ExcalidrawBindableElement>,
|
||||
{ x, y }: { x: number; y: number },
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
fullShape?: boolean,
|
||||
): boolean => {
|
||||
const threshold = maxBindingGap(element, element.width, element.height);
|
||||
const threshold = maxBindingGap(element, element.width, element.height, zoom);
|
||||
|
||||
const shape = getElementShape(element, elementsMap);
|
||||
return (
|
||||
isPointOnShape(pointFrom(x, y), shape, threshold) ||
|
||||
|
@ -1356,12 +1417,21 @@ export const maxBindingGap = (
|
|||
element: ExcalidrawElement,
|
||||
elementWidth: number,
|
||||
elementHeight: number,
|
||||
zoom?: AppState["zoom"],
|
||||
): number => {
|
||||
const zoomValue = zoom?.value && zoom.value < 1 ? zoom.value : 1;
|
||||
|
||||
// Aligns diamonds with rectangles
|
||||
const shapeRatio = element.type === "diamond" ? 1 / Math.sqrt(2) : 1;
|
||||
const smallerDimension = shapeRatio * Math.min(elementWidth, elementHeight);
|
||||
// We make the bindable boundary bigger for bigger elements
|
||||
return Math.max(16, Math.min(0.25 * smallerDimension, 32));
|
||||
|
||||
return Math.max(
|
||||
16,
|
||||
// bigger bindable boundary for bigger elements
|
||||
Math.min(0.25 * smallerDimension, 32),
|
||||
// keep in sync with the zoomed highlight
|
||||
BINDING_HIGHLIGHT_THICKNESS / zoomValue + BINDING_HIGHLIGHT_OFFSET,
|
||||
);
|
||||
};
|
||||
|
||||
export const distanceToBindableElement = (
|
||||
|
|
|
@ -448,6 +448,7 @@ export class LinearElementEditor {
|
|||
),
|
||||
elements,
|
||||
elementsMap,
|
||||
appState.zoom,
|
||||
)
|
||||
: null;
|
||||
|
||||
|
@ -787,6 +788,7 @@ export class LinearElementEditor {
|
|||
scenePointer,
|
||||
elements,
|
||||
elementsMap,
|
||||
app.state.zoom,
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -911,6 +913,7 @@ export class LinearElementEditor {
|
|||
element,
|
||||
[points.length - 1],
|
||||
elementsMap,
|
||||
app.state.zoom,
|
||||
);
|
||||
}
|
||||
return {
|
||||
|
@ -964,6 +967,7 @@ export class LinearElementEditor {
|
|||
element,
|
||||
[{ point: newPoint }],
|
||||
elementsMap,
|
||||
app.state.zoom,
|
||||
);
|
||||
}
|
||||
return {
|
||||
|
@ -1218,6 +1222,7 @@ export class LinearElementEditor {
|
|||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
pointIndices: readonly number[],
|
||||
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||
zoom: AppState["zoom"],
|
||||
) {
|
||||
let offsetX = 0;
|
||||
let offsetY = 0;
|
||||
|
@ -1260,6 +1265,7 @@ export class LinearElementEditor {
|
|||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
targetPoints: { point: LocalPoint }[],
|
||||
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||
zoom: AppState["zoom"],
|
||||
) {
|
||||
const offsetX = 0;
|
||||
const offsetY = 0;
|
||||
|
@ -1285,6 +1291,7 @@ export class LinearElementEditor {
|
|||
options?: {
|
||||
changedElements?: Map<string, OrderedExcalidrawElement>;
|
||||
isDragging?: boolean;
|
||||
zoom?: AppState["zoom"];
|
||||
},
|
||||
) {
|
||||
const { points } = element;
|
||||
|
@ -1337,6 +1344,7 @@ export class LinearElementEditor {
|
|||
false,
|
||||
),
|
||||
changedElements: options?.changedElements,
|
||||
zoom: options?.zoom,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -1451,6 +1459,7 @@ export class LinearElementEditor {
|
|||
options?: {
|
||||
changedElements?: Map<string, OrderedExcalidrawElement>;
|
||||
isDragging?: boolean;
|
||||
zoom?: AppState["zoom"];
|
||||
},
|
||||
) {
|
||||
if (isElbowArrow(element)) {
|
||||
|
@ -1487,6 +1496,7 @@ export class LinearElementEditor {
|
|||
bindings,
|
||||
{
|
||||
isDragging: options?.isDragging,
|
||||
zoom: options?.zoom,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
import BinaryHeap from "../binaryheap";
|
||||
import { getSizeFromPoints } from "../points";
|
||||
import { aabbForElement, pointInsideBounds } from "../shapes";
|
||||
import type { AppState } from "../types";
|
||||
import { isAnyTrue, toBrandedType, tupleToCoors } from "../utils";
|
||||
import {
|
||||
bindPointToSnapToElementOutline,
|
||||
|
@ -79,6 +80,7 @@ export const mutateElbowArrow = (
|
|||
options?: {
|
||||
isDragging?: boolean;
|
||||
informMutation?: boolean;
|
||||
zoom?: AppState["zoom"];
|
||||
},
|
||||
) => {
|
||||
const update = updateElbowArrow(
|
||||
|
@ -112,6 +114,7 @@ export const updateElbowArrow = (
|
|||
isDragging?: boolean;
|
||||
disableBinding?: boolean;
|
||||
informMutation?: boolean;
|
||||
zoom?: AppState["zoom"];
|
||||
},
|
||||
): ElementUpdate<ExcalidrawElbowArrowElement> | null => {
|
||||
const origStartGlobalPoint: GlobalPoint = pointTranslate(
|
||||
|
@ -136,7 +139,12 @@ export const updateElbowArrow = (
|
|||
arrow.endBinding &&
|
||||
getBindableElementForId(arrow.endBinding.elementId, elementsMap);
|
||||
const [hoveredStartElement, hoveredEndElement] = options?.isDragging
|
||||
? getHoveredElements(origStartGlobalPoint, origEndGlobalPoint, elementsMap)
|
||||
? getHoveredElements(
|
||||
origStartGlobalPoint,
|
||||
origEndGlobalPoint,
|
||||
elementsMap,
|
||||
options?.zoom,
|
||||
)
|
||||
: [startElement, endElement];
|
||||
const startGlobalPoint = getGlobalPoint(
|
||||
arrow.startBinding?.fixedPoint,
|
||||
|
@ -1072,6 +1080,7 @@ const getHoveredElements = (
|
|||
origStartGlobalPoint: GlobalPoint,
|
||||
origEndGlobalPoint: GlobalPoint,
|
||||
elementsMap: NonDeletedSceneElementsMap | SceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
) => {
|
||||
// TODO: Might be a performance bottleneck and the Map type
|
||||
// remembers the insertion order anyway...
|
||||
|
@ -1084,12 +1093,14 @@ const getHoveredElements = (
|
|||
tupleToCoors(origStartGlobalPoint),
|
||||
elements,
|
||||
nonDeletedSceneElementsMap,
|
||||
zoom,
|
||||
true,
|
||||
),
|
||||
getHoveredElementForBinding(
|
||||
tupleToCoors(origEndGlobalPoint),
|
||||
elements,
|
||||
nonDeletedSceneElementsMap,
|
||||
zoom,
|
||||
true,
|
||||
),
|
||||
];
|
||||
|
|
|
@ -43,7 +43,11 @@ import type {
|
|||
SuggestedBinding,
|
||||
SuggestedPointBinding,
|
||||
} from "../element/binding";
|
||||
import { maxBindingGap } from "../element/binding";
|
||||
import {
|
||||
BINDING_HIGHLIGHT_OFFSET,
|
||||
BINDING_HIGHLIGHT_THICKNESS,
|
||||
maxBindingGap,
|
||||
} from "../element/binding";
|
||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||
import {
|
||||
bootstrapCanvas,
|
||||
|
@ -217,17 +221,18 @@ const renderBindingHighlightForBindableElement = (
|
|||
context: CanvasRenderingContext2D,
|
||||
element: ExcalidrawBindableElement,
|
||||
elementsMap: ElementsMap,
|
||||
zoom: InteractiveCanvasAppState["zoom"],
|
||||
) => {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
||||
const width = x2 - x1;
|
||||
const height = y2 - y1;
|
||||
const thickness = 10;
|
||||
|
||||
// So that we don't overlap the element itself
|
||||
const strokeOffset = 4;
|
||||
context.strokeStyle = "rgba(0,0,0,.05)";
|
||||
context.lineWidth = thickness - strokeOffset;
|
||||
const padding = strokeOffset / 2 + thickness / 2;
|
||||
// When zooming out, make line width greater for visibility
|
||||
const zoomValue = zoom.value < 1 ? zoom.value : 1;
|
||||
context.lineWidth = BINDING_HIGHLIGHT_THICKNESS / zoomValue;
|
||||
// To ensure the binding highlight doesn't overlap the element itself
|
||||
const padding = context.lineWidth / 2 + BINDING_HIGHLIGHT_OFFSET;
|
||||
|
||||
const radius = getCornerRadius(
|
||||
Math.min(element.width, element.height),
|
||||
|
@ -285,6 +290,7 @@ const renderBindingHighlightForSuggestedPointBinding = (
|
|||
context: CanvasRenderingContext2D,
|
||||
suggestedBinding: SuggestedPointBinding,
|
||||
elementsMap: ElementsMap,
|
||||
zoom: InteractiveCanvasAppState["zoom"],
|
||||
) => {
|
||||
const [element, startOrEnd, bindableElement] = suggestedBinding;
|
||||
|
||||
|
@ -292,6 +298,7 @@ const renderBindingHighlightForSuggestedPointBinding = (
|
|||
bindableElement,
|
||||
bindableElement.width,
|
||||
bindableElement.height,
|
||||
zoom,
|
||||
);
|
||||
|
||||
context.strokeStyle = "rgba(0,0,0,0)";
|
||||
|
@ -390,7 +397,7 @@ const renderBindingHighlight = (
|
|||
|
||||
context.save();
|
||||
context.translate(appState.scrollX, appState.scrollY);
|
||||
renderHighlight(context, suggestedBinding as any, elementsMap);
|
||||
renderHighlight(context, suggestedBinding as any, elementsMap, appState.zoom);
|
||||
|
||||
context.restore();
|
||||
};
|
||||
|
|
|
@ -197,7 +197,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||
"fillStyle": "solid",
|
||||
"frameId": null,
|
||||
"groupIds": [],
|
||||
"height": 99,
|
||||
"height": 125,
|
||||
"id": "id166",
|
||||
"index": "a2",
|
||||
"isDeleted": false,
|
||||
|
@ -211,8 +211,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||
0,
|
||||
],
|
||||
[
|
||||
"98.20800",
|
||||
99,
|
||||
125,
|
||||
125,
|
||||
],
|
||||
],
|
||||
"roughness": 1,
|
||||
|
@ -226,9 +226,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 40,
|
||||
"width": "98.20800",
|
||||
"x": 1,
|
||||
"version": 47,
|
||||
"width": 125,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -298,7 +298,7 @@ History {
|
|||
"focus": "0.00990",
|
||||
"gap": 1,
|
||||
},
|
||||
"height": "0.98017",
|
||||
"height": "0.98000",
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
|
@ -306,7 +306,7 @@ History {
|
|||
],
|
||||
[
|
||||
98,
|
||||
"-0.98017",
|
||||
"-0.98000",
|
||||
],
|
||||
],
|
||||
"startBinding": {
|
||||
|
@ -320,10 +320,10 @@ History {
|
|||
"endBinding": {
|
||||
"elementId": "id165",
|
||||
"fixedPoint": null,
|
||||
"focus": "-0.02000",
|
||||
"focus": "-0.02040",
|
||||
"gap": 1,
|
||||
},
|
||||
"height": "0.00169",
|
||||
"height": "0.02000",
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
|
@ -331,13 +331,13 @@ History {
|
|||
],
|
||||
[
|
||||
98,
|
||||
"0.00169",
|
||||
"0.02000",
|
||||
],
|
||||
],
|
||||
"startBinding": {
|
||||
"elementId": "id164",
|
||||
"fixedPoint": null,
|
||||
"focus": "0.02000",
|
||||
"focus": "0.01959",
|
||||
"gap": 1,
|
||||
},
|
||||
},
|
||||
|
@ -393,18 +393,20 @@ History {
|
|||
"focus": 0,
|
||||
"gap": 1,
|
||||
},
|
||||
"height": 99,
|
||||
"height": 125,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
"98.20800",
|
||||
99,
|
||||
125,
|
||||
125,
|
||||
],
|
||||
],
|
||||
"startBinding": null,
|
||||
"width": 125,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
|
@ -414,7 +416,7 @@ History {
|
|||
"focus": "0.00990",
|
||||
"gap": 1,
|
||||
},
|
||||
"height": "0.98161",
|
||||
"height": "0.98000",
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
|
@ -422,7 +424,7 @@ History {
|
|||
],
|
||||
[
|
||||
98,
|
||||
"-0.98161",
|
||||
"-0.98000",
|
||||
],
|
||||
],
|
||||
"startBinding": {
|
||||
|
@ -431,7 +433,9 @@ History {
|
|||
"focus": "0.02970",
|
||||
"gap": 1,
|
||||
},
|
||||
"y": "0.99245",
|
||||
"width": 98,
|
||||
"x": 1,
|
||||
"y": "0.99000",
|
||||
},
|
||||
},
|
||||
"id169" => Delta {
|
||||
|
@ -823,9 +827,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 30,
|
||||
"width": 0,
|
||||
"x": 200,
|
||||
"version": 37,
|
||||
"width": 100,
|
||||
"x": 150,
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -862,6 +866,8 @@ History {
|
|||
0,
|
||||
],
|
||||
],
|
||||
"width": 0,
|
||||
"x": 149,
|
||||
},
|
||||
"inserted": {
|
||||
"points": [
|
||||
|
@ -870,10 +876,12 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
"width": "98.00000",
|
||||
"x": "1.00000",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -930,6 +938,8 @@ History {
|
|||
],
|
||||
],
|
||||
"startBinding": null,
|
||||
"width": 100,
|
||||
"x": 150,
|
||||
},
|
||||
"inserted": {
|
||||
"endBinding": {
|
||||
|
@ -954,6 +964,8 @@ History {
|
|||
"focus": 0,
|
||||
"gap": 1,
|
||||
},
|
||||
"width": 0,
|
||||
"x": 149,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2363,9 +2375,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 10,
|
||||
"version": 12,
|
||||
"width": 498,
|
||||
"x": 1,
|
||||
"x": "1.00000",
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -2504,7 +2516,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -2523,8 +2535,8 @@ History {
|
|||
"strokeStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"width": 100,
|
||||
"x": 0,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
|
@ -15167,9 +15179,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 10,
|
||||
"version": 12,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"x": "1.00000",
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -15208,7 +15220,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -15221,7 +15233,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -15517,7 +15529,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -15536,8 +15548,8 @@ History {
|
|||
"strokeStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"width": 100,
|
||||
"x": 0,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
|
@ -15866,9 +15878,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 10,
|
||||
"version": 12,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"x": "1.00000",
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -16140,7 +16152,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -16159,8 +16171,8 @@ History {
|
|||
"strokeStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"width": 100,
|
||||
"x": 0,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
|
@ -16489,9 +16501,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 10,
|
||||
"version": 12,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"x": "1.00000",
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -16763,7 +16775,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -16782,8 +16794,8 @@ History {
|
|||
"strokeStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"width": 100,
|
||||
"x": 0,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
|
@ -17110,9 +17122,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 10,
|
||||
"version": 12,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"x": "1.00000",
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -17168,7 +17180,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -17186,7 +17198,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -17455,7 +17467,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -17474,8 +17486,8 @@ History {
|
|||
"strokeStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"width": 100,
|
||||
"x": 0,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
|
@ -17828,9 +17840,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 11,
|
||||
"version": 13,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"x": "1.00000",
|
||||
"y": 0,
|
||||
}
|
||||
`;
|
||||
|
@ -17901,7 +17913,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -17920,7 +17932,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -18189,7 +18201,7 @@ History {
|
|||
0,
|
||||
],
|
||||
[
|
||||
100,
|
||||
"98.00000",
|
||||
0,
|
||||
],
|
||||
],
|
||||
|
@ -18208,8 +18220,8 @@ History {
|
|||
"strokeStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"width": 100,
|
||||
"x": 0,
|
||||
"width": "98.00000",
|
||||
"x": 1,
|
||||
"y": 0,
|
||||
},
|
||||
"inserted": {
|
||||
|
|
|
@ -173,7 +173,7 @@ exports[`move element > rectangles with binding arrow 6`] = `
|
|||
"type": "rectangle",
|
||||
"updated": 1,
|
||||
"version": 7,
|
||||
"versionNonce": 745419401,
|
||||
"versionNonce": 2066753033,
|
||||
"width": 300,
|
||||
"x": 201,
|
||||
"y": 2,
|
||||
|
@ -232,8 +232,8 @@ exports[`move element > rectangles with binding arrow 7`] = `
|
|||
"strokeWidth": 2,
|
||||
"type": "arrow",
|
||||
"updated": 1,
|
||||
"version": 11,
|
||||
"versionNonce": 1996028265,
|
||||
"version": 15,
|
||||
"versionNonce": 271613161,
|
||||
"width": 81,
|
||||
"x": 110,
|
||||
"y": 50,
|
||||
|
|
|
@ -4785,21 +4785,17 @@ describe("history", () => {
|
|||
expect.objectContaining({ id: rect2.id, boundElements: [] }),
|
||||
expect.objectContaining({
|
||||
id: arrowId,
|
||||
points: [
|
||||
[0, 0],
|
||||
[100, 0],
|
||||
],
|
||||
startBinding: expect.objectContaining({
|
||||
elementId: rect1.id,
|
||||
fixedPoint: null,
|
||||
focus: expect.toBeNonNaNNumber(),
|
||||
gap: expect.toBeNonNaNNumber(),
|
||||
focus: 0,
|
||||
gap: 1,
|
||||
}),
|
||||
endBinding: expect.objectContaining({
|
||||
elementId: rect2.id,
|
||||
fixedPoint: null,
|
||||
focus: expect.toBeNonNaNNumber(),
|
||||
gap: expect.toBeNonNaNNumber(),
|
||||
focus: 0,
|
||||
gap: 1,
|
||||
}),
|
||||
isDeleted: true,
|
||||
}),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue