mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-04-14 16:40:58 -04:00
update baseline when resizing text element
This commit is contained in:
parent
99500fc255
commit
c0e88fbc54
1 changed files with 43 additions and 18 deletions
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue