fix: introduce baseline to fix the layout shift when switching to text editor

This commit is contained in:
Aakansha Doshi
2023-03-28 13:48:34 +05:30
parent 83383977f5
commit fc80fd15dc
3 changed files with 85 additions and 4 deletions

View File

@@ -289,6 +289,43 @@ export const measureText = (
return { width, height };
};
export const measureBaseline = (
text: string,
font: FontString,
lineHeight: ExcalidrawTextElement["lineHeight"],
wrapInContainer?: boolean,
) => {
const container = document.createElement("div");
container.style.position = "absolute";
container.style.whiteSpace = "pre";
container.style.font = font;
container.style.minHeight = "1em";
if (wrapInContainer) {
container.style.overflow = "hidden";
container.style.wordBreak = "break-word";
container.style.whiteSpace = "pre-wrap";
}
//@ts-ignore
container.style.lineHeight = lineHeight;
container.innerText = text;
// Baseline is important for positioning text on canvas
document.body.appendChild(container);
const span = document.createElement("span");
span.style.display = "inline-block";
span.style.overflow = "hidden";
span.style.width = "1px";
span.style.height = "1px";
container.appendChild(span);
const baseline = span.offsetTop + span.offsetHeight;
//document.body.removeChild(container);
return baseline;
};
/**
* To get unitless line-height (if unknown) we can calculate it by dividing
* height-per-line by fontSize.

View File

@@ -34,6 +34,7 @@ import {
wrapText,
getMaxContainerHeight,
getMaxContainerWidth,
measureBaseline,
} from "./textElement";
import {
actionDecreaseFontSize,
@@ -269,6 +270,17 @@ export const textWysiwyg = ({
} else {
textElementWidth += 0.5;
}
const baseline = measureBaseline(
updatedTextElement.text,
getFontString(updatedTextElement),
updatedTextElement.lineHeight,
!!container,
);
const offset =
(updatedTextElement.height - baseline - 10) * appState.zoom.value;
const top = viewportY + offset;
// Make sure text editor height doesn't go beyond viewport
const editorMaxHeight =
(appState.height - viewportY) / appState.zoom.value;
@@ -279,7 +291,7 @@ export const textWysiwyg = ({
width: `${textElementWidth}px`,
height: `${textElementHeight}px`,
left: `${viewportX}px`,
top: `${viewportY}px`,
top: `${top}px`,
transform: getTransform(
textElementWidth,
textElementHeight,