mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-19 23:40:45 +02:00
fix: introduce baseline to fix the layout shift when switching to text editor
This commit is contained in:
@@ -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.
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user