From abff7809832f43984746ddcd77016c9730f70e68 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Tue, 25 Jan 2022 17:01:12 +0530 Subject: [PATCH] perf: cache approx line height in textwysiwg (#4651) --- src/element/textElement.ts | 8 +++++++- src/element/textWysiwyg.tsx | 16 ++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/element/textElement.ts b/src/element/textElement.ts index efe799a9..1de918ce 100644 --- a/src/element/textElement.ts +++ b/src/element/textElement.ts @@ -205,8 +205,14 @@ export const measureText = ( }; const DUMMY_TEXT = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toLocaleUpperCase(); +const cacheApproxLineHeight: { [key: FontString]: number } = {}; + export const getApproxLineHeight = (font: FontString) => { - return measureText(DUMMY_TEXT, font, null).height; + if (cacheApproxLineHeight[font]) { + return cacheApproxLineHeight[font]; + } + cacheApproxLineHeight[font] = measureText(DUMMY_TEXT, font, null).height; + return cacheApproxLineHeight[font]; }; let canvas: HTMLCanvasElement | undefined; diff --git a/src/element/textWysiwyg.tsx b/src/element/textWysiwyg.tsx index 7b862874..b82513f6 100644 --- a/src/element/textWysiwyg.tsx +++ b/src/element/textWysiwyg.tsx @@ -102,10 +102,12 @@ export const textWysiwyg = ({ return false; }; let originalContainerHeight: number; - let approxLineHeight = getApproxLineHeight(getFontString(element)); const updateWysiwygStyle = () => { - const updatedElement = Scene.getScene(element)?.getElement(id); + const updatedElement = Scene.getScene(element)?.getElement( + id, + ) as ExcalidrawTextElement; + const approxLineHeight = getApproxLineHeight(getFontString(updatedElement)); if (updatedElement && isTextElement(updatedElement)) { let coordX = updatedElement.x; let coordY = updatedElement.y; @@ -128,8 +130,6 @@ export const textWysiwyg = ({ height = editorHeight; } if (propertiesUpdated) { - approxLineHeight = getApproxLineHeight(getFontString(updatedElement)); - originalContainerHeight = container.height; // update height of the editor after properties updated @@ -268,10 +268,14 @@ export const textWysiwyg = ({ if (onChange) { editable.oninput = () => { + const updatedElement = Scene.getScene(element)?.getElement( + id, + ) as ExcalidrawTextElement; + const font = getFontString(updatedElement); // using scrollHeight here since we need to calculate // number of lines so cannot use editable.style.height // as that gets updated below - const lines = editable.scrollHeight / approxLineHeight; + const lines = editable.scrollHeight / getApproxLineHeight(font); // auto increase height only when lines > 1 so its // measured correctly and vertically alignes for // first line as well as setting height to "auto" @@ -283,7 +287,7 @@ export const textWysiwyg = ({ const container = getContainerElement(element); const actualLineCount = wrapText( editable.value, - getFontString(element), + font, container!.width, ).split("\n").length;