From 4604c8d8230760c7e725eac9923887bfddb4f53e Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Fri, 18 Feb 2022 18:20:55 +0530 Subject: [PATCH] fix: stuck resizing when resizing bound text container very fast beyond threshold (#4804) * fix: stuck resizing when resizing bound text container very fast beyond threshold * fix * fix --- src/element/resizeElements.ts | 26 +++++++++++++------------- src/element/textElement.ts | 17 ++++++++++++++--- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/element/resizeElements.ts b/src/element/resizeElements.ts index e925b0e2..9b825a11 100644 --- a/src/element/resizeElements.ts +++ b/src/element/resizeElements.ts @@ -35,6 +35,7 @@ import { import { Point, PointerDownState } from "../types"; import Scene from "../scene/Scene"; import { + getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getBoundTextElementId, @@ -429,8 +430,6 @@ export const resizeSingleElement = ( element.height, ); - const boundTextElementId = getBoundTextElementId(element); - const boundsCurrentWidth = esx2 - esx1; const boundsCurrentHeight = esy2 - esy1; @@ -453,6 +452,9 @@ export const resizeSingleElement = ( if (transformHandleDirection.includes("n")) { scaleY = (startBottomRight[1] - rotatedPointer[1]) / boundsCurrentHeight; } + + const boundTextElement = getBoundTextElement(element); + // Linear elements dimensions differ from bounds dimensions const eleInitialWidth = stateAtResizeStart.width; const eleInitialHeight = stateAtResizeStart.height; @@ -482,6 +484,13 @@ export const resizeSingleElement = ( } } + if (boundTextElement) { + const minWidth = getApproxMinLineWidth(getFontString(boundTextElement)); + const minHeight = getApproxMinLineHeight(getFontString(boundTextElement)); + eleNewWidth = Math.ceil(Math.max(eleNewWidth, minWidth)); + eleNewHeight = Math.ceil(Math.max(eleNewHeight, minHeight)); + } + const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] = getResizedElementAbsoluteCoords( stateAtResizeStart, @@ -491,11 +500,6 @@ export const resizeSingleElement = ( const newBoundsWidth = newBoundsX2 - newBoundsX1; const newBoundsHeight = newBoundsY2 - newBoundsY1; - // don't allow resize to negative dimensions when text is bounded to container - if ((newBoundsWidth < 0 || newBoundsHeight < 0) && boundTextElementId) { - return; - } - // Calculate new topLeft based on fixed corner during resize let newTopLeft = [...startTopLeft] as [number, number]; if (["n", "w", "nw"].includes(transformHandleDirection)) { @@ -588,13 +592,9 @@ export const resizeSingleElement = ( ], }); } - let minWidth = 0; - const boundTextElement = getBoundTextElement(element); - if (boundTextElement) { - minWidth = getApproxMinLineWidth(getFontString(boundTextElement)); - } + if ( - resizedElement.width >= minWidth && + resizedElement.width !== 0 && resizedElement.height !== 0 && Number.isFinite(resizedElement.x) && Number.isFinite(resizedElement.y) diff --git a/src/element/textElement.ts b/src/element/textElement.ts index 1c0c2b8b..e2d294e3 100644 --- a/src/element/textElement.ts +++ b/src/element/textElement.ts @@ -144,6 +144,7 @@ export const handleBindTextResize = ( } const updatedY = element.y + containerHeight / 2 - nextHeight / 2; + mutateElement(textElement, { text, // preserve padding and set width correctly @@ -355,6 +356,7 @@ export const charWidth = (() => { const width = getTextWidth(char, font); cachedCharWidth[font][ascii] = width; } + return cachedCharWidth[font][ascii]; }; @@ -367,14 +369,14 @@ export const charWidth = (() => { }; })(); export const getApproxMinLineWidth = (font: FontString) => { - const minCharWidth = getMinCharWidth(font); - if (minCharWidth === 0) { + const maxCharWidth = getMaxCharWidth(font); + if (maxCharWidth === 0) { return ( measureText(DUMMY_TEXT.split("").join("\n"), font).width + BOUND_TEXT_PADDING * 2 ); } - return minCharWidth + BOUND_TEXT_PADDING * 2; + return maxCharWidth + BOUND_TEXT_PADDING * 2; }; export const getApproxMinLineHeight = (font: FontString) => { @@ -391,6 +393,15 @@ export const getMinCharWidth = (font: FontString) => { return Math.min(...cacheWithOutEmpty); }; +export const getMaxCharWidth = (font: FontString) => { + const cache = charWidth.getCache(font); + if (!cache) { + return 0; + } + const cacheWithOutEmpty = cache.filter((val) => val !== undefined); + return Math.max(...cacheWithOutEmpty); +}; + export const getApproxCharsToFitInWidth = (font: FontString, width: number) => { // Generally lower case is used so converting to lower case const dummyText = DUMMY_TEXT.toLocaleLowerCase();