fix: Linear element is not normalized (#9347)

* Fix #9292
This commit is contained in:
Márk Tolmács 2025-04-06 13:41:11 +02:00 committed by GitHub
parent c79e892e55
commit b3d5ba0567
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 73 additions and 44 deletions

View File

@ -133,6 +133,7 @@ export class LinearElementEditor {
}; };
if (!pointsEqual(element.points[0], pointFrom(0, 0))) { if (!pointsEqual(element.points[0], pointFrom(0, 0))) {
console.error("Linear element is not normalized", Error().stack); console.error("Linear element is not normalized", Error().stack);
LinearElementEditor.normalizePoints(element);
} }
this.selectedPointsIndices = null; this.selectedPointsIndices = null;

View File

@ -104,12 +104,12 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0.5, 0,
], ],
[ [
394.5, 394,
34.5, 34,
], ],
], ],
"roughness": 1, "roughness": 1,
@ -129,8 +129,8 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
"version": 4, "version": 4,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 395, "width": 395,
"x": 247, "x": 247.5,
"y": 420, "y": 420.5,
} }
`; `;
@ -160,11 +160,11 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
399.5, 399,
0, 0,
], ],
], ],
@ -185,7 +185,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s
"version": 4, "version": 4,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 400, "width": 400,
"x": 227, "x": 227.5,
"y": 450, "y": 450,
} }
`; `;
@ -350,11 +350,11 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -375,7 +375,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
"version": 4, "version": 4,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 255, "x": 255.5,
"y": 239, "y": 239,
} }
`; `;
@ -452,11 +452,11 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to shapes whe
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -477,7 +477,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to shapes whe
"version": 4, "version": 4,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 255, "x": 255.5,
"y": 239, "y": 239,
} }
`; `;
@ -628,11 +628,11 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -653,7 +653,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when
"version": 4, "version": 4,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 255, "x": 255.5,
"y": 239, "y": 239,
} }
`; `;
@ -845,11 +845,11 @@ exports[`Test Transform > should transform linear elements 1`] = `
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -866,7 +866,7 @@ exports[`Test Transform > should transform linear elements 1`] = `
"version": 2, "version": 2,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 100, "x": 100.5,
"y": 20, "y": 20,
} }
`; `;
@ -893,11 +893,11 @@ exports[`Test Transform > should transform linear elements 2`] = `
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -914,7 +914,7 @@ exports[`Test Transform > should transform linear elements 2`] = `
"version": 2, "version": 2,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 450, "x": 450.5,
"y": 20, "y": 20,
} }
`; `;
@ -1490,11 +1490,11 @@ exports[`Test Transform > should transform the elements correctly when linear el
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
272.485, 271.985,
0, 0,
], ],
], ],
@ -1517,7 +1517,7 @@ exports[`Test Transform > should transform the elements correctly when linear el
"version": 4, "version": 4,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 272.985, "width": 272.985,
"x": 111.262, "x": 111.762,
"y": 57, "y": 57,
} }
`; `;
@ -1862,11 +1862,11 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -1883,7 +1883,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"version": 2, "version": 2,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 100, "x": 100.5,
"y": 100, "y": 100,
} }
`; `;
@ -1915,11 +1915,11 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -1936,7 +1936,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"version": 2, "version": 2,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 100, "x": 100.5,
"y": 200, "y": 200,
} }
`; `;
@ -1968,11 +1968,11 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -1989,7 +1989,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"version": 2, "version": 2,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 100, "x": 100.5,
"y": 300, "y": 300,
} }
`; `;
@ -2021,11 +2021,11 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"opacity": 100, "opacity": 100,
"points": [ "points": [
[ [
0.5, 0,
0, 0,
], ],
[ [
99.5, 99,
0, 0,
], ],
], ],
@ -2042,7 +2042,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
"version": 2, "version": 2,
"versionNonce": Any<Number>, "versionNonce": Any<Number>,
"width": 100, "width": 100,
"x": 100, "x": 100.5,
"y": 400, "y": 400,
} }
`; `;

View File

@ -427,7 +427,7 @@ describe("Test Transform", () => {
const [arrow, text, rectangle, ellipse] = excalidrawElements; const [arrow, text, rectangle, ellipse] = excalidrawElements;
expect(arrow).toMatchObject({ expect(arrow).toMatchObject({
type: "arrow", type: "arrow",
x: 255, x: 255.5,
y: 239, y: 239,
boundElements: [{ id: text.id, type: "text" }], boundElements: [{ id: text.id, type: "text" }],
startBinding: { startBinding: {
@ -512,7 +512,7 @@ describe("Test Transform", () => {
expect(arrow).toMatchObject({ expect(arrow).toMatchObject({
type: "arrow", type: "arrow",
x: 255, x: 255.5,
y: 239, y: 239,
boundElements: [{ id: text1.id, type: "text" }], boundElements: [{ id: text1.id, type: "text" }],
startBinding: { startBinding: {
@ -730,7 +730,7 @@ describe("Test Transform", () => {
const [, , arrow, text] = excalidrawElements; const [, , arrow, text] = excalidrawElements;
expect(arrow).toMatchObject({ expect(arrow).toMatchObject({
type: "arrow", type: "arrow",
x: 255, x: 255.5,
y: 239, y: 239,
boundElements: [ boundElements: [
{ {

View File

@ -36,6 +36,8 @@ import { syncInvalidIndices } from "@excalidraw/element/fractionalIndex";
import { redrawTextBoundingBox } from "@excalidraw/element/textElement"; import { redrawTextBoundingBox } from "@excalidraw/element/textElement";
import { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
import type { ElementConstructorOpts } from "@excalidraw/element/newElement"; import type { ElementConstructorOpts } from "@excalidraw/element/newElement";
import type { import type {
@ -463,7 +465,13 @@ const bindLinearElementToElement = (
newPoints[endPointIndex][1] += delta; newPoints[endPointIndex][1] += delta;
} }
Object.assign(linearElement, { points: newPoints }); Object.assign(
linearElement,
LinearElementEditor.getNormalizedPoints({
...linearElement,
points: newPoints,
}),
);
return { return {
linearElement, linearElement,

View File

@ -1,3 +1,5 @@
import { newArrowElement } from "@excalidraw/element/newElement";
import { pointCenter, pointFrom } from "@excalidraw/math"; import { pointCenter, pointFrom } from "@excalidraw/math";
import { act, queryByTestId, queryByText } from "@testing-library/react"; import { act, queryByTestId, queryByText } from "@testing-library/react";
import React from "react"; import React from "react";
@ -19,7 +21,7 @@ import {
import * as textElementUtils from "@excalidraw/element/textElement"; import * as textElementUtils from "@excalidraw/element/textElement";
import { wrapText } from "@excalidraw/element/textWrapping"; import { wrapText } from "@excalidraw/element/textWrapping";
import type { GlobalPoint } from "@excalidraw/math"; import type { GlobalPoint, LocalPoint } from "@excalidraw/math";
import type { import type {
ExcalidrawElement, ExcalidrawElement,
@ -164,6 +166,24 @@ describe("Test Linear Elements", () => {
Keyboard.keyPress(KEYS.DELETE); Keyboard.keyPress(KEYS.DELETE);
}; };
it("should normalize the element points at creation", () => {
const element = newArrowElement({
type: "arrow",
points: [pointFrom<LocalPoint>(0.5, 0), pointFrom<LocalPoint>(100, 100)],
x: 0,
y: 0,
});
expect(element.points).toEqual([
pointFrom<LocalPoint>(0.5, 0),
pointFrom<LocalPoint>(100, 100),
]);
new LinearElementEditor(element);
expect(element.points).toEqual([
pointFrom<LocalPoint>(0, 0),
pointFrom<LocalPoint>(99.5, 100),
]);
});
it("should not drag line and add midpoint until dragged beyond a threshold", () => { it("should not drag line and add midpoint until dragged beyond a threshold", () => {
createTwoPointerLinearElement("line"); createTwoPointerLinearElement("line");
const line = h.elements[0] as ExcalidrawLinearElement; const line = h.elements[0] as ExcalidrawLinearElement;