update baseline when resizing text element

This commit is contained in:
Aakansha Doshi 2023-04-01 13:08:02 +05:30
parent 99500fc255
commit c0e88fbc54

View file

@ -46,6 +46,8 @@ import {
handleBindTextResize, handleBindTextResize,
getMaxContainerWidth, getMaxContainerWidth,
getApproxMinLineHeight, getApproxMinLineHeight,
measureText,
getMaxContainerHeight,
} from "./textElement"; } from "./textElement";
export const normalizeAngle = (angle: number): number => { export const normalizeAngle = (angle: number): number => {
@ -193,7 +195,8 @@ const MIN_FONT_SIZE = 1;
const measureFontSizeFromWidth = ( const measureFontSizeFromWidth = (
element: NonDeleted<ExcalidrawTextElement>, element: NonDeleted<ExcalidrawTextElement>,
nextWidth: number, nextWidth: number,
): number | null => { nextHeight: number,
): { size: number; baseline: number } | null => {
// We only use width to scale font on resize // We only use width to scale font on resize
let width = element.width; let width = element.width;
@ -208,8 +211,15 @@ const measureFontSizeFromWidth = (
if (nextFontSize < MIN_FONT_SIZE) { if (nextFontSize < MIN_FONT_SIZE) {
return null; return null;
} }
const metrics = measureText(
return nextFontSize; element.text,
getFontString({ fontSize: nextFontSize, fontFamily: element.fontFamily }),
element.lineHeight,
);
return {
size: nextFontSize,
baseline: metrics.baseline + (nextHeight - metrics.height),
};
}; };
const getSidesForTransformHandle = ( const getSidesForTransformHandle = (
@ -280,8 +290,8 @@ const resizeSingleTextElement = (
if (scale > 0) { if (scale > 0) {
const nextWidth = element.width * scale; const nextWidth = element.width * scale;
const nextHeight = element.height * scale; const nextHeight = element.height * scale;
const nextFontSize = measureFontSizeFromWidth(element, nextWidth); const metrics = measureFontSizeFromWidth(element, nextWidth, nextHeight);
if (nextFontSize === null) { if (metrics === null) {
return; return;
} }
const [nextX1, nextY1, nextX2, nextY2] = getResizedElementAbsoluteCoords( const [nextX1, nextY1, nextX2, nextY2] = getResizedElementAbsoluteCoords(
@ -305,9 +315,10 @@ const resizeSingleTextElement = (
deltaY2, deltaY2,
); );
mutateElement(element, { mutateElement(element, {
fontSize: nextFontSize, fontSize: metrics.size,
width: nextWidth, width: nextWidth,
height: nextHeight, height: nextHeight,
baseline: metrics.baseline,
x: nextElementX, x: nextElementX,
y: nextElementY, y: nextElementY,
}); });
@ -360,7 +371,7 @@ export const resizeSingleElement = (
let scaleX = atStartBoundsWidth / boundsCurrentWidth; let scaleX = atStartBoundsWidth / boundsCurrentWidth;
let scaleY = atStartBoundsHeight / boundsCurrentHeight; let scaleY = atStartBoundsHeight / boundsCurrentHeight;
let boundTextFontSize: number | null = null; let boundTextFont: { fontSize?: number; baseline?: number } = {};
const boundTextElement = getBoundTextElement(element); const boundTextElement = getBoundTextElement(element);
if (transformHandleDirection.includes("e")) { if (transformHandleDirection.includes("e")) {
@ -410,7 +421,10 @@ export const resizeSingleElement = (
boundTextElement.id, boundTextElement.id,
) as typeof boundTextElement | undefined; ) as typeof boundTextElement | undefined;
if (stateOfBoundTextElementAtResize) { if (stateOfBoundTextElementAtResize) {
boundTextFontSize = stateOfBoundTextElementAtResize.fontSize; boundTextFont = {
fontSize: stateOfBoundTextElementAtResize.fontSize,
baseline: stateOfBoundTextElementAtResize.baseline,
};
} }
if (shouldMaintainAspectRatio) { if (shouldMaintainAspectRatio) {
const updatedElement = { const updatedElement = {
@ -419,14 +433,18 @@ export const resizeSingleElement = (
height: eleNewHeight, height: eleNewHeight,
}; };
const nextFontSize = measureFontSizeFromWidth( const nextFont = measureFontSizeFromWidth(
boundTextElement, boundTextElement,
getMaxContainerWidth(updatedElement), getMaxContainerWidth(updatedElement),
getMaxContainerHeight(updatedElement),
); );
if (nextFontSize === null) { if (nextFont === null) {
return; return;
} }
boundTextFontSize = nextFontSize; boundTextFont = {
fontSize: nextFont.size,
baseline: nextFont.baseline,
};
} else { } else {
const minWidth = getApproxMinLineWidth( const minWidth = getApproxMinLineWidth(
getFontString(boundTextElement), getFontString(boundTextElement),
@ -568,9 +586,10 @@ export const resizeSingleElement = (
}); });
mutateElement(element, resizedElement); mutateElement(element, resizedElement);
if (boundTextElement && boundTextFontSize != null) { if (boundTextElement && boundTextFont != null) {
mutateElement(boundTextElement, { mutateElement(boundTextElement, {
fontSize: boundTextFontSize, fontSize: boundTextFont.fontSize,
baseline: boundTextFont.baseline,
}); });
} }
handleBindTextResize(element, transformHandleDirection); handleBindTextResize(element, transformHandleDirection);
@ -677,6 +696,7 @@ const resizeMultipleElements = (
y: number; y: number;
points?: Point[]; points?: Point[];
fontSize?: number; fontSize?: number;
baseline?: number;
} = { } = {
width, width,
height, height,
@ -685,7 +705,7 @@ const resizeMultipleElements = (
...rescaledPoints, ...rescaledPoints,
}; };
let boundTextUpdates: { fontSize: number } | null = null; let boundTextUpdates: { fontSize: number; baseline: number } | null = null;
const boundTextElement = getBoundTextElement(element.latest); const boundTextElement = getBoundTextElement(element.latest);
@ -695,24 +715,29 @@ const resizeMultipleElements = (
width, width,
height, height,
}; };
const fontSize = measureFontSizeFromWidth( const metrics = measureFontSizeFromWidth(
boundTextElement ?? (element.orig as ExcalidrawTextElement), boundTextElement ?? (element.orig as ExcalidrawTextElement),
boundTextElement boundTextElement
? getMaxContainerWidth(updatedElement) ? getMaxContainerWidth(updatedElement)
: updatedElement.width, : updatedElement.width,
boundTextElement
? getMaxContainerHeight(updatedElement)
: updatedElement.height,
); );
if (!fontSize) { if (!metrics) {
return; return;
} }
if (isTextElement(element.orig)) { if (isTextElement(element.orig)) {
update.fontSize = fontSize; update.fontSize = metrics.size;
update.baseline = metrics.baseline;
} }
if (boundTextElement) { if (boundTextElement) {
boundTextUpdates = { boundTextUpdates = {
fontSize, fontSize: metrics.size,
baseline: metrics.baseline,
}; };
} }
} }