mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: support vertical text align for bound containers (#4852)
* feat: support vertical text align for bound containers * update icons * use const * fix lint * rename to and show when text editor active * don't update vertical align if not center * fix svgs * fix y coords when vertical align bottm Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
c5a7723185
commit
8e26d5b500
13 changed files with 222 additions and 66 deletions
|
@ -23,7 +23,7 @@ import { adjustXYWithRotation } from "../math";
|
|||
import { getResizedElementAbsoluteCoords } from "./bounds";
|
||||
import { getContainerElement, measureText, wrapText } from "./textElement";
|
||||
import { isBoundToContainer } from "./typeChecks";
|
||||
import { BOUND_TEXT_PADDING } from "../constants";
|
||||
import { BOUND_TEXT_PADDING, VERTICAL_ALIGN } from "../constants";
|
||||
|
||||
type ElementConstructorOpts = MarkOptional<
|
||||
Omit<ExcalidrawGenericElement, "id" | "type" | "isDeleted" | "updated">,
|
||||
|
@ -175,7 +175,7 @@ const getAdjustedDimensions = (
|
|||
let y: number;
|
||||
if (
|
||||
textAlign === "center" &&
|
||||
verticalAlign === "middle" &&
|
||||
verticalAlign === VERTICAL_ALIGN.MIDDLE &&
|
||||
!element.containerId
|
||||
) {
|
||||
const prevMetrics = measureText(
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
NonDeletedExcalidrawElement,
|
||||
} from "./types";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
import { BOUND_TEXT_PADDING } from "../constants";
|
||||
import { BOUND_TEXT_PADDING, VERTICAL_ALIGN } from "../constants";
|
||||
import { MaybeTransformHandleType } from "./transformHandles";
|
||||
import Scene from "../scene/Scene";
|
||||
import { AppState } from "../types";
|
||||
|
@ -39,11 +39,19 @@ export const redrawTextBoundingBox = (
|
|||
let coordY = element.y;
|
||||
// Resize container and vertically center align the text
|
||||
if (container) {
|
||||
coordY = container.y + container.height / 2 - metrics.height / 2;
|
||||
let nextHeight = container.height;
|
||||
if (metrics.height > container.height - BOUND_TEXT_PADDING * 2) {
|
||||
nextHeight = metrics.height + BOUND_TEXT_PADDING * 2;
|
||||
coordY = container.y + nextHeight / 2 - metrics.height / 2;
|
||||
|
||||
if (element.verticalAlign === VERTICAL_ALIGN.TOP) {
|
||||
coordY = container.y + BOUND_TEXT_PADDING;
|
||||
} else if (element.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
||||
coordY =
|
||||
container.y + container.height - metrics.height - BOUND_TEXT_PADDING;
|
||||
} else {
|
||||
coordY = container.y + container.height / 2 - metrics.height / 2;
|
||||
if (metrics.height > container.height - BOUND_TEXT_PADDING * 2) {
|
||||
nextHeight = metrics.height + BOUND_TEXT_PADDING * 2;
|
||||
coordY = container.y + nextHeight / 2 - metrics.height / 2;
|
||||
}
|
||||
}
|
||||
mutateElement(container, { height: nextHeight });
|
||||
}
|
||||
|
@ -142,7 +150,14 @@ export const handleBindTextResize = (
|
|||
});
|
||||
}
|
||||
|
||||
const updatedY = element.y + containerHeight / 2 - nextHeight / 2;
|
||||
let updatedY;
|
||||
if (textElement.verticalAlign === VERTICAL_ALIGN.TOP) {
|
||||
updatedY = element.y + BOUND_TEXT_PADDING;
|
||||
} else if (textElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
||||
updatedY = element.y + element.height - nextHeight - BOUND_TEXT_PADDING;
|
||||
} else {
|
||||
updatedY = element.y + element.height / 2 - nextHeight / 2;
|
||||
}
|
||||
|
||||
mutateElement(textElement, {
|
||||
text,
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
} from "../utils";
|
||||
import Scene from "../scene/Scene";
|
||||
import { isBoundToContainer, isTextElement } from "./typeChecks";
|
||||
import { CLASSES, BOUND_TEXT_PADDING } from "../constants";
|
||||
import { CLASSES, BOUND_TEXT_PADDING, VERTICAL_ALIGN } from "../constants";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
ExcalidrawTextElement,
|
||||
|
@ -105,6 +105,8 @@ export const textWysiwyg = ({
|
|||
const updatedElement = Scene.getScene(element)?.getElement(
|
||||
id,
|
||||
) as ExcalidrawTextElement;
|
||||
const { textAlign, verticalAlign } = updatedElement;
|
||||
|
||||
const approxLineHeight = getApproxLineHeight(getFontString(updatedElement));
|
||||
if (updatedElement && isTextElement(updatedElement)) {
|
||||
let coordX = updatedElement.x;
|
||||
|
@ -140,7 +142,7 @@ export const textWysiwyg = ({
|
|||
maxHeight = container.height - BOUND_TEXT_PADDING * 2;
|
||||
width = maxWidth;
|
||||
// The coordinates of text box set a distance of
|
||||
// 30px to preserve padding
|
||||
// 5px to preserve padding
|
||||
coordX = container.x + BOUND_TEXT_PADDING;
|
||||
// autogrow container height if text exceeds
|
||||
if (height > maxHeight) {
|
||||
|
@ -160,11 +162,16 @@ export const textWysiwyg = ({
|
|||
// is reached
|
||||
else {
|
||||
// vertically center align the text
|
||||
coordY = container.y + container.height / 2 - height / 2;
|
||||
if (verticalAlign === VERTICAL_ALIGN.MIDDLE) {
|
||||
coordY = container.y + container.height / 2 - height / 2;
|
||||
}
|
||||
if (verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
||||
coordY =
|
||||
container.y + container.height - height - BOUND_TEXT_PADDING;
|
||||
}
|
||||
}
|
||||
}
|
||||
const [viewportX, viewportY] = getViewportCoords(coordX, coordY);
|
||||
const { textAlign } = updatedElement;
|
||||
const initialSelectionStart = editable.selectionStart;
|
||||
const initialSelectionEnd = editable.selectionEnd;
|
||||
const initialLength = editable.value.length;
|
||||
|
@ -212,6 +219,7 @@ export const textWysiwyg = ({
|
|||
editorMaxHeight,
|
||||
),
|
||||
textAlign,
|
||||
verticalAlign,
|
||||
color: updatedElement.strokeColor,
|
||||
opacity: updatedElement.opacity / 100,
|
||||
filter: "var(--theme-filter)",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Point } from "../types";
|
||||
import { FONT_FAMILY, THEME } from "../constants";
|
||||
import { FONT_FAMILY, THEME, VERTICAL_ALIGN } from "../constants";
|
||||
|
||||
export type ChartType = "bar" | "line";
|
||||
export type FillStyle = "hachure" | "cross-hatch" | "solid";
|
||||
|
@ -12,7 +12,9 @@ export type PointerType = "mouse" | "pen" | "touch";
|
|||
export type StrokeSharpness = "round" | "sharp";
|
||||
export type StrokeStyle = "solid" | "dashed" | "dotted";
|
||||
export type TextAlign = "left" | "center" | "right";
|
||||
export type VerticalAlign = "top" | "middle";
|
||||
|
||||
type VerticalAlignKeys = keyof typeof VERTICAL_ALIGN;
|
||||
export type VerticalAlign = typeof VERTICAL_ALIGN[VerticalAlignKeys];
|
||||
|
||||
type _ExcalidrawElementBase = Readonly<{
|
||||
id: string;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue