fix(editor): remove extremely large arrows on restore (#11235)
* fix: Temp fix for elbow arrow at restore Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Mark Tolmacs <mark@lazycat.hu> * fix: Speculative fixes to avoid Infinity Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Mark Tolmacs <mark@lazycat.hu> * validate/remove arrow size after point normalization & move binding repairs back * validate even simple arrows * remove x/y check * remove duplicate constant --------- Signed-off-by: Mark Tolmacs <mark@lazycat.hu> Co-authored-by: Copilot <copilot@github.com> Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot
dwelle
parent
b1c6bfcf40
commit
2e1a529c67
@@ -1943,9 +1943,9 @@ export const calculateFixedPointForElbowArrowBinding = (
|
|||||||
return {
|
return {
|
||||||
fixedPoint: normalizeFixedPoint([
|
fixedPoint: normalizeFixedPoint([
|
||||||
(nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) /
|
(nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) /
|
||||||
hoveredElement.width,
|
Math.max(hoveredElement.width, PRECISION),
|
||||||
(nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) /
|
(nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) /
|
||||||
hoveredElement.height,
|
Math.max(hoveredElement.height, PRECISION),
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1976,9 +1976,11 @@ export const calculateFixedPointForNonElbowArrowBinding = (
|
|||||||
|
|
||||||
// Calculate the ratio relative to the element's bounds
|
// Calculate the ratio relative to the element's bounds
|
||||||
const fixedPointX =
|
const fixedPointX =
|
||||||
(nonRotatedPoint[0] - hoveredElement.x) / hoveredElement.width;
|
(nonRotatedPoint[0] - hoveredElement.x) /
|
||||||
|
Math.max(hoveredElement.width, PRECISION);
|
||||||
const fixedPointY =
|
const fixedPointY =
|
||||||
(nonRotatedPoint[1] - hoveredElement.y) / hoveredElement.height;
|
(nonRotatedPoint[1] - hoveredElement.y) /
|
||||||
|
Math.max(hoveredElement.height, PRECISION);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fixedPoint: normalizeFixedPoint([fixedPointX, fixedPointY]),
|
fixedPoint: normalizeFixedPoint([fixedPointX, fixedPointY]),
|
||||||
|
|||||||
@@ -2124,8 +2124,8 @@ const normalizeArrowElementUpdate = (
|
|||||||
offsetY < -MAX_POS ||
|
offsetY < -MAX_POS ||
|
||||||
offsetY > MAX_POS ||
|
offsetY > MAX_POS ||
|
||||||
offsetX + points[points.length - 1][0] < -MAX_POS ||
|
offsetX + points[points.length - 1][0] < -MAX_POS ||
|
||||||
offsetY + points[points.length - 1][0] > MAX_POS ||
|
offsetX + points[points.length - 1][0] > MAX_POS ||
|
||||||
offsetX + points[points.length - 1][1] < -MAX_POS ||
|
offsetY + points[points.length - 1][1] < -MAX_POS ||
|
||||||
offsetY + points[points.length - 1][1] > MAX_POS
|
offsetY + points[points.length - 1][1] > MAX_POS
|
||||||
) {
|
) {
|
||||||
console.error(
|
console.error(
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ type RestoredAppState = Omit<
|
|||||||
"offsetTop" | "offsetLeft" | "width" | "height"
|
"offsetTop" | "offsetLeft" | "width" | "height"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
const MAX_ARROW_PX = 75_000;
|
||||||
|
|
||||||
export const AllowedExcalidrawActiveTools: Record<
|
export const AllowedExcalidrawActiveTools: Record<
|
||||||
AppState["activeTool"]["type"],
|
AppState["activeTool"]["type"],
|
||||||
boolean
|
boolean
|
||||||
@@ -467,8 +469,8 @@ export const restoreElement = (
|
|||||||
element.endArrowhead === undefined
|
element.endArrowhead === undefined
|
||||||
? "arrow"
|
? "arrow"
|
||||||
: normalizeArrowhead(element.endArrowhead);
|
: normalizeArrowhead(element.endArrowhead);
|
||||||
const x: number | undefined = element.x;
|
const x = element.x as number | undefined;
|
||||||
const y: number | undefined = element.y;
|
const y = element.y as number | undefined;
|
||||||
const points: readonly LocalPoint[] | undefined = // migrate old arrow model to new one
|
const points: readonly LocalPoint[] | undefined = // migrate old arrow model to new one
|
||||||
!Array.isArray(element.points) || element.points.length < 2
|
!Array.isArray(element.points) || element.points.length < 2
|
||||||
? [pointFrom(0, 0), pointFrom(element.width, element.height)]
|
? [pointFrom(0, 0), pointFrom(element.width, element.height)]
|
||||||
@@ -493,8 +495,8 @@ export const restoreElement = (
|
|||||||
startArrowhead,
|
startArrowhead,
|
||||||
endArrowhead,
|
endArrowhead,
|
||||||
points,
|
points,
|
||||||
x,
|
x: x ?? 0,
|
||||||
y,
|
y: y ?? 0,
|
||||||
elbowed: (element as ExcalidrawArrowElement).elbowed,
|
elbowed: (element as ExcalidrawArrowElement).elbowed,
|
||||||
...getSizeFromPoints(points),
|
...getSizeFromPoints(points),
|
||||||
};
|
};
|
||||||
@@ -513,12 +515,44 @@ export const restoreElement = (
|
|||||||
})
|
})
|
||||||
: restoreElementWithProperties(element as ExcalidrawArrowElement, base);
|
: restoreElementWithProperties(element as ExcalidrawArrowElement, base);
|
||||||
|
|
||||||
return {
|
const normalizedRestoredElement = {
|
||||||
...restoredElement,
|
...restoredElement,
|
||||||
...LinearElementEditor.getNormalizeElementPointsAndCoords(
|
...LinearElementEditor.getNormalizeElementPointsAndCoords(
|
||||||
restoredElement,
|
restoredElement,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Last resort fix for extremely large arrows
|
||||||
|
if (
|
||||||
|
normalizedRestoredElement.width > MAX_ARROW_PX ||
|
||||||
|
normalizedRestoredElement.height > MAX_ARROW_PX
|
||||||
|
) {
|
||||||
|
console.error(
|
||||||
|
`Removing extremely large arrow ${
|
||||||
|
normalizedRestoredElement.id
|
||||||
|
} (type: ${
|
||||||
|
isElbowArrow(normalizedRestoredElement) ? "elbow" : "simple"
|
||||||
|
}, width: ${normalizedRestoredElement.width}, height: ${
|
||||||
|
normalizedRestoredElement.height
|
||||||
|
}, x: ${normalizedRestoredElement.x}, y: ${
|
||||||
|
normalizedRestoredElement.y
|
||||||
|
})`,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...normalizedRestoredElement,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
points: [
|
||||||
|
pointFrom<LocalPoint>(0, 0),
|
||||||
|
pointFrom<LocalPoint>(100, 100),
|
||||||
|
],
|
||||||
|
isDeleted: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizedRestoredElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic elements
|
// generic elements
|
||||||
@@ -666,6 +700,7 @@ export const restoreElements = <T extends ExcalidrawElement>(
|
|||||||
const existingElementsMap = existingElements
|
const existingElementsMap = existingElements
|
||||||
? arrayToMap(existingElements)
|
? arrayToMap(existingElements)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const restoredElements = syncInvalidIndices(
|
const restoredElements = syncInvalidIndices(
|
||||||
(targetElements || []).reduce((elements, element) => {
|
(targetElements || []).reduce((elements, element) => {
|
||||||
// filtering out selection, which is legacy, no longer kept in elements,
|
// filtering out selection, which is legacy, no longer kept in elements,
|
||||||
@@ -762,7 +797,7 @@ export const restoreElements = <T extends ExcalidrawElement>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE (mtolmacs): Temporary fix for extremely large arrows
|
// NOTE (mtolmacs): Temporary fix for invalid/self-bound elbow arrows
|
||||||
// Need to iterate again so we have attached text nodes in elementsMap
|
// Need to iterate again so we have attached text nodes in elementsMap
|
||||||
return restoredElements.map((element) => {
|
return restoredElements.map((element) => {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
export const PRECISION = 10e-5;
|
|
||||||
|
|
||||||
// Legendre-Gauss abscissae (x values) and weights for n=24
|
// Legendre-Gauss abscissae (x values) and weights for n=24
|
||||||
// Refeerence: https://pomax.github.io/bezierinfo/legendre-gauss.html
|
// Refeerence: https://pomax.github.io/bezierinfo/legendre-gauss.html
|
||||||
export const LegendreGaussN24TValues = [
|
export const LegendreGaussN24TValues = [
|
||||||
|
|||||||
Reference in New Issue
Block a user