Parcourir la source

update baseline when resizing text element

Aakansha Doshi il y a 2 ans
Parent
commit
c0e88fbc54
1 fichiers modifiés avec 43 ajouts et 18 suppressions
  1. 43 18
      src/element/resizeElements.ts

+ 43 - 18
src/element/resizeElements.ts

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