fix: improve text wrapping inside rhombus and more fixes (#6265)
* fix: improve text wrapping inside rhombus * Add comments * specs * fix: shift resize and multiple element regression for ellipse and rhombus * use container width for scaling font size * fix * fix multiple resize * lint * redraw on submit * redraw only newly pasted elements * no padding when center * fix tests * fix * dont add padding in rhombus when aligning * refactor * fix * move getMaxContainerHeight and getMaxContainerWidth to textElement.ts * Add specs
This commit is contained in:
parent
88ff32e9b3
commit
5368ddef74
@ -1627,6 +1627,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
oldIdToDuplicatedId.set(element.id, newElement.id);
|
oldIdToDuplicatedId.set(element.id, newElement.id);
|
||||||
return newElement;
|
return newElement;
|
||||||
});
|
});
|
||||||
|
|
||||||
bindTextToShapeAfterDuplication(newElements, elements, oldIdToDuplicatedId);
|
bindTextToShapeAfterDuplication(newElements, elements, oldIdToDuplicatedId);
|
||||||
const nextElements = [
|
const nextElements = [
|
||||||
...this.scene.getElementsIncludingDeleted(),
|
...this.scene.getElementsIncludingDeleted(),
|
||||||
@ -1640,10 +1641,10 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
this.scene.replaceAllElements(nextElements);
|
this.scene.replaceAllElements(nextElements);
|
||||||
|
|
||||||
nextElements.forEach((nextElement) => {
|
newElements.forEach((newElement) => {
|
||||||
if (isTextElement(nextElement) && isBoundToContainer(nextElement)) {
|
if (isTextElement(newElement) && isBoundToContainer(newElement)) {
|
||||||
const container = getContainerElement(nextElement);
|
const container = getContainerElement(newElement);
|
||||||
redrawTextBoundingBox(nextElement, container);
|
redrawTextBoundingBox(newElement, container);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,15 +22,15 @@ import { getElementAbsoluteCoords } from ".";
|
|||||||
import { adjustXYWithRotation } from "../math";
|
import { adjustXYWithRotation } from "../math";
|
||||||
import { getResizedElementAbsoluteCoords } from "./bounds";
|
import { getResizedElementAbsoluteCoords } from "./bounds";
|
||||||
import {
|
import {
|
||||||
getBoundTextElement,
|
|
||||||
getBoundTextElementOffset,
|
getBoundTextElementOffset,
|
||||||
getContainerDims,
|
getContainerDims,
|
||||||
getContainerElement,
|
getContainerElement,
|
||||||
measureText,
|
measureText,
|
||||||
normalizeText,
|
normalizeText,
|
||||||
wrapText,
|
wrapText,
|
||||||
|
getMaxContainerWidth,
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
import { BOUND_TEXT_PADDING, VERTICAL_ALIGN } from "../constants";
|
import { VERTICAL_ALIGN } from "../constants";
|
||||||
import { isArrowElement } from "./typeChecks";
|
import { isArrowElement } from "./typeChecks";
|
||||||
|
|
||||||
type ElementConstructorOpts = MarkOptional<
|
type ElementConstructorOpts = MarkOptional<
|
||||||
@ -278,48 +278,6 @@ export const refreshTextDimensions = (
|
|||||||
return { text, ...dimensions };
|
return { text, ...dimensions };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMaxContainerWidth = (container: ExcalidrawElement) => {
|
|
||||||
const width = getContainerDims(container).width;
|
|
||||||
if (isArrowElement(container)) {
|
|
||||||
const containerWidth = width - BOUND_TEXT_PADDING * 8 * 2;
|
|
||||||
if (containerWidth <= 0) {
|
|
||||||
const boundText = getBoundTextElement(container);
|
|
||||||
if (boundText) {
|
|
||||||
return boundText.width;
|
|
||||||
}
|
|
||||||
return BOUND_TEXT_PADDING * 8 * 2;
|
|
||||||
}
|
|
||||||
return containerWidth;
|
|
||||||
} else if (container.type === "ellipse") {
|
|
||||||
// The width of the largest rectangle inscribed inside an ellipse is
|
|
||||||
// Math.round((ellipse.width / 2) * Math.sqrt(2)) which is derived from
|
|
||||||
// equation of an ellipse -https://github.com/excalidraw/excalidraw/pull/6172
|
|
||||||
return Math.round((width / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;
|
|
||||||
}
|
|
||||||
return width - BOUND_TEXT_PADDING * 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getMaxContainerHeight = (container: ExcalidrawElement) => {
|
|
||||||
const height = getContainerDims(container).height;
|
|
||||||
if (isArrowElement(container)) {
|
|
||||||
const containerHeight = height - BOUND_TEXT_PADDING * 8 * 2;
|
|
||||||
if (containerHeight <= 0) {
|
|
||||||
const boundText = getBoundTextElement(container);
|
|
||||||
if (boundText) {
|
|
||||||
return boundText.height;
|
|
||||||
}
|
|
||||||
return BOUND_TEXT_PADDING * 8 * 2;
|
|
||||||
}
|
|
||||||
return height;
|
|
||||||
} else if (container.type === "ellipse") {
|
|
||||||
// The height of the largest rectangle inscribed inside an ellipse is
|
|
||||||
// Math.round((ellipse.height / 2) * Math.sqrt(2)) which is derived from
|
|
||||||
// equation of an ellipse - https://github.com/excalidraw/excalidraw/pull/6172
|
|
||||||
return Math.round((height / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;
|
|
||||||
}
|
|
||||||
return height - BOUND_TEXT_PADDING * 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateTextElement = (
|
export const updateTextElement = (
|
||||||
textElement: ExcalidrawTextElement,
|
textElement: ExcalidrawTextElement,
|
||||||
{
|
{
|
||||||
|
@ -43,12 +43,12 @@ import {
|
|||||||
getApproxMinLineWidth,
|
getApproxMinLineWidth,
|
||||||
getBoundTextElement,
|
getBoundTextElement,
|
||||||
getBoundTextElementId,
|
getBoundTextElementId,
|
||||||
getBoundTextElementOffset,
|
|
||||||
getContainerElement,
|
getContainerElement,
|
||||||
handleBindTextResize,
|
handleBindTextResize,
|
||||||
measureText,
|
measureText,
|
||||||
|
getMaxContainerHeight,
|
||||||
|
getMaxContainerWidth,
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
import { getMaxContainerWidth } from "./newElement";
|
|
||||||
|
|
||||||
export const normalizeAngle = (angle: number): number => {
|
export const normalizeAngle = (angle: number): number => {
|
||||||
if (angle >= 2 * Math.PI) {
|
if (angle >= 2 * Math.PI) {
|
||||||
@ -427,12 +427,16 @@ export const resizeSingleElement = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (shouldMaintainAspectRatio) {
|
if (shouldMaintainAspectRatio) {
|
||||||
const boundTextElementPadding =
|
const updatedElement = {
|
||||||
getBoundTextElementOffset(boundTextElement);
|
...element,
|
||||||
|
width: eleNewWidth,
|
||||||
|
height: eleNewHeight,
|
||||||
|
};
|
||||||
|
|
||||||
const nextFont = measureFontSizeFromWH(
|
const nextFont = measureFontSizeFromWH(
|
||||||
boundTextElement,
|
boundTextElement,
|
||||||
eleNewWidth - boundTextElementPadding * 2,
|
getMaxContainerWidth(updatedElement),
|
||||||
eleNewHeight - boundTextElementPadding * 2,
|
getMaxContainerHeight(updatedElement),
|
||||||
);
|
);
|
||||||
if (nextFont === null) {
|
if (nextFont === null) {
|
||||||
return;
|
return;
|
||||||
@ -697,11 +701,15 @@ const resizeMultipleElements = (
|
|||||||
const boundTextElement = getBoundTextElement(element.latest);
|
const boundTextElement = getBoundTextElement(element.latest);
|
||||||
|
|
||||||
if (boundTextElement || isTextElement(element.orig)) {
|
if (boundTextElement || isTextElement(element.orig)) {
|
||||||
const optionalPadding = getBoundTextElementOffset(boundTextElement) * 2;
|
const updatedElement = {
|
||||||
|
...element.latest,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
};
|
||||||
const textMeasurements = measureFontSizeFromWH(
|
const textMeasurements = measureFontSizeFromWH(
|
||||||
boundTextElement ?? (element.orig as ExcalidrawTextElement),
|
boundTextElement ?? (element.orig as ExcalidrawTextElement),
|
||||||
width - optionalPadding,
|
getMaxContainerWidth(updatedElement),
|
||||||
height - optionalPadding,
|
getMaxContainerHeight(updatedElement),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!textMeasurements) {
|
if (!textMeasurements) {
|
||||||
|
@ -3,6 +3,8 @@ import { API } from "../tests/helpers/api";
|
|||||||
import {
|
import {
|
||||||
computeContainerHeightForBoundText,
|
computeContainerHeightForBoundText,
|
||||||
getContainerCoords,
|
getContainerCoords,
|
||||||
|
getMaxContainerWidth,
|
||||||
|
getMaxContainerHeight,
|
||||||
measureText,
|
measureText,
|
||||||
wrapText,
|
wrapText,
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
@ -202,24 +204,37 @@ describe("Test measureText", () => {
|
|||||||
|
|
||||||
describe("Test getContainerCoords", () => {
|
describe("Test getContainerCoords", () => {
|
||||||
const params = { width: 200, height: 100, x: 10, y: 20 };
|
const params = { width: 200, height: 100, x: 10, y: 20 };
|
||||||
|
|
||||||
it("should compute coords correctly when ellipse", () => {
|
it("should compute coords correctly when ellipse", () => {
|
||||||
const ellipse = API.createElement({
|
const element = API.createElement({
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
...params,
|
...params,
|
||||||
});
|
});
|
||||||
expect(getContainerCoords(ellipse)).toEqual({
|
expect(getContainerCoords(element)).toEqual({
|
||||||
x: 44.2893218813452455,
|
x: 44.2893218813452455,
|
||||||
y: 39.64466094067262,
|
y: 39.64466094067262,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should compute coords correctly when rectangle", () => {
|
it("should compute coords correctly when rectangle", () => {
|
||||||
const rectangle = API.createElement({
|
const element = API.createElement({
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
...params,
|
...params,
|
||||||
});
|
});
|
||||||
expect(getContainerCoords(rectangle)).toEqual({
|
expect(getContainerCoords(element)).toEqual({
|
||||||
x: 10,
|
x: 15,
|
||||||
y: 20,
|
y: 25,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should compute coords correctly when diamond", () => {
|
||||||
|
const element = API.createElement({
|
||||||
|
type: "diamond",
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
expect(getContainerCoords(element)).toEqual({
|
||||||
|
x: 65,
|
||||||
|
y: 50,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -229,6 +244,7 @@ describe("Test measureText", () => {
|
|||||||
width: 178,
|
width: 178,
|
||||||
height: 194,
|
height: 194,
|
||||||
};
|
};
|
||||||
|
|
||||||
it("should compute container height correctly for rectangle", () => {
|
it("should compute container height correctly for rectangle", () => {
|
||||||
const element = API.createElement({
|
const element = API.createElement({
|
||||||
type: "rectangle",
|
type: "rectangle",
|
||||||
@ -236,6 +252,7 @@ describe("Test measureText", () => {
|
|||||||
});
|
});
|
||||||
expect(computeContainerHeightForBoundText(element, 150)).toEqual(160);
|
expect(computeContainerHeightForBoundText(element, 150)).toEqual(160);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should compute container height correctly for ellipse", () => {
|
it("should compute container height correctly for ellipse", () => {
|
||||||
const element = API.createElement({
|
const element = API.createElement({
|
||||||
type: "ellipse",
|
type: "ellipse",
|
||||||
@ -243,5 +260,57 @@ describe("Test measureText", () => {
|
|||||||
});
|
});
|
||||||
expect(computeContainerHeightForBoundText(element, 150)).toEqual(212);
|
expect(computeContainerHeightForBoundText(element, 150)).toEqual(212);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should compute container height correctly for diamond", () => {
|
||||||
|
const element = API.createElement({
|
||||||
|
type: "diamond",
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
expect(computeContainerHeightForBoundText(element, 150)).toEqual(300);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Test getMaxContainerWidth", () => {
|
||||||
|
const params = {
|
||||||
|
width: 178,
|
||||||
|
height: 194,
|
||||||
|
};
|
||||||
|
|
||||||
|
it("should return max width when container is rectangle", () => {
|
||||||
|
const container = API.createElement({ type: "rectangle", ...params });
|
||||||
|
expect(getMaxContainerWidth(container)).toBe(168);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return max width when container is ellipse", () => {
|
||||||
|
const container = API.createElement({ type: "ellipse", ...params });
|
||||||
|
expect(getMaxContainerWidth(container)).toBe(116);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return max width when container is diamond", () => {
|
||||||
|
const container = API.createElement({ type: "diamond", ...params });
|
||||||
|
expect(getMaxContainerWidth(container)).toBe(79);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Test getMaxContainerHeight", () => {
|
||||||
|
const params = {
|
||||||
|
width: 178,
|
||||||
|
height: 194,
|
||||||
|
};
|
||||||
|
|
||||||
|
it("should return max height when container is rectangle", () => {
|
||||||
|
const container = API.createElement({ type: "rectangle", ...params });
|
||||||
|
expect(getMaxContainerHeight(container)).toBe(184);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return max height when container is ellipse", () => {
|
||||||
|
const container = API.createElement({ type: "ellipse", ...params });
|
||||||
|
expect(getMaxContainerHeight(container)).toBe(127);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return max height when container is diamond", () => {
|
||||||
|
const container = API.createElement({ type: "diamond", ...params });
|
||||||
|
expect(getMaxContainerHeight(container)).toBe(87);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,6 @@ import { BOUND_TEXT_PADDING, TEXT_ALIGN, VERTICAL_ALIGN } from "../constants";
|
|||||||
import { MaybeTransformHandleType } from "./transformHandles";
|
import { MaybeTransformHandleType } from "./transformHandles";
|
||||||
import Scene from "../scene/Scene";
|
import Scene from "../scene/Scene";
|
||||||
import { isTextElement } from ".";
|
import { isTextElement } from ".";
|
||||||
import { getMaxContainerHeight, getMaxContainerWidth } from "./newElement";
|
|
||||||
import {
|
import {
|
||||||
isBoundToContainer,
|
isBoundToContainer,
|
||||||
isImageElement,
|
isImageElement,
|
||||||
@ -244,31 +243,25 @@ const computeBoundTextPosition = (
|
|||||||
const containerCoords = getContainerCoords(container);
|
const containerCoords = getContainerCoords(container);
|
||||||
const maxContainerHeight = getMaxContainerHeight(container);
|
const maxContainerHeight = getMaxContainerHeight(container);
|
||||||
const maxContainerWidth = getMaxContainerWidth(container);
|
const maxContainerWidth = getMaxContainerWidth(container);
|
||||||
const padding = container.type === "ellipse" ? 0 : BOUND_TEXT_PADDING;
|
|
||||||
|
|
||||||
let x;
|
let x;
|
||||||
let y;
|
let y;
|
||||||
if (boundTextElement.verticalAlign === VERTICAL_ALIGN.TOP) {
|
if (boundTextElement.verticalAlign === VERTICAL_ALIGN.TOP) {
|
||||||
y = containerCoords.y + padding;
|
y = containerCoords.y;
|
||||||
} else if (boundTextElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
} else if (boundTextElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
||||||
y =
|
y = containerCoords.y + (maxContainerHeight - boundTextElement.height);
|
||||||
containerCoords.y +
|
|
||||||
(maxContainerHeight - boundTextElement.height + padding);
|
|
||||||
} else {
|
} else {
|
||||||
y =
|
y =
|
||||||
containerCoords.y +
|
containerCoords.y +
|
||||||
(maxContainerHeight / 2 - boundTextElement.height / 2 + padding);
|
(maxContainerHeight / 2 - boundTextElement.height / 2);
|
||||||
}
|
}
|
||||||
if (boundTextElement.textAlign === TEXT_ALIGN.LEFT) {
|
if (boundTextElement.textAlign === TEXT_ALIGN.LEFT) {
|
||||||
x = containerCoords.x + padding;
|
x = containerCoords.x;
|
||||||
} else if (boundTextElement.textAlign === TEXT_ALIGN.RIGHT) {
|
} else if (boundTextElement.textAlign === TEXT_ALIGN.RIGHT) {
|
||||||
x =
|
x = containerCoords.x + (maxContainerWidth - boundTextElement.width);
|
||||||
containerCoords.x +
|
|
||||||
(maxContainerWidth - boundTextElement.width + padding);
|
|
||||||
} else {
|
} else {
|
||||||
x =
|
x =
|
||||||
containerCoords.x +
|
containerCoords.x + (maxContainerWidth / 2 - boundTextElement.width / 2);
|
||||||
(maxContainerWidth / 2 - boundTextElement.width / 2 + padding);
|
|
||||||
}
|
}
|
||||||
return { x, y };
|
return { x, y };
|
||||||
};
|
};
|
||||||
@ -636,20 +629,22 @@ export const getContainerCenter = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getContainerCoords = (container: NonDeletedExcalidrawElement) => {
|
export const getContainerCoords = (container: NonDeletedExcalidrawElement) => {
|
||||||
|
let offsetX = BOUND_TEXT_PADDING;
|
||||||
|
let offsetY = BOUND_TEXT_PADDING;
|
||||||
|
|
||||||
if (container.type === "ellipse") {
|
if (container.type === "ellipse") {
|
||||||
// The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6172
|
// The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6172
|
||||||
const offsetX =
|
offsetX += (container.width / 2) * (1 - Math.sqrt(2) / 2);
|
||||||
(container.width / 2) * (1 - Math.sqrt(2) / 2) + BOUND_TEXT_PADDING;
|
offsetY += (container.height / 2) * (1 - Math.sqrt(2) / 2);
|
||||||
const offsetY =
|
}
|
||||||
(container.height / 2) * (1 - Math.sqrt(2) / 2) + BOUND_TEXT_PADDING;
|
// The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6265
|
||||||
return {
|
if (container.type === "diamond") {
|
||||||
x: container.x + offsetX,
|
offsetX += container.width / 4;
|
||||||
y: container.y + offsetY,
|
offsetY += container.height / 4;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
x: container.x,
|
x: container.x + offsetX,
|
||||||
y: container.y,
|
y: container.y + offsetY,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -767,5 +762,63 @@ export const computeContainerHeightForBoundText = (
|
|||||||
if (isArrowElement(container)) {
|
if (isArrowElement(container)) {
|
||||||
return boundTextElementHeight + BOUND_TEXT_PADDING * 8 * 2;
|
return boundTextElementHeight + BOUND_TEXT_PADDING * 8 * 2;
|
||||||
}
|
}
|
||||||
|
if (container.type === "diamond") {
|
||||||
|
return 2 * boundTextElementHeight;
|
||||||
|
}
|
||||||
return boundTextElementHeight + BOUND_TEXT_PADDING * 2;
|
return boundTextElementHeight + BOUND_TEXT_PADDING * 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getMaxContainerWidth = (container: ExcalidrawElement) => {
|
||||||
|
const width = getContainerDims(container).width;
|
||||||
|
if (isArrowElement(container)) {
|
||||||
|
const containerWidth = width - BOUND_TEXT_PADDING * 8 * 2;
|
||||||
|
if (containerWidth <= 0) {
|
||||||
|
const boundText = getBoundTextElement(container);
|
||||||
|
if (boundText) {
|
||||||
|
return boundText.width;
|
||||||
|
}
|
||||||
|
return BOUND_TEXT_PADDING * 8 * 2;
|
||||||
|
}
|
||||||
|
return containerWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container.type === "ellipse") {
|
||||||
|
// The width of the largest rectangle inscribed inside an ellipse is
|
||||||
|
// Math.round((ellipse.width / 2) * Math.sqrt(2)) which is derived from
|
||||||
|
// equation of an ellipse -https://github.com/excalidraw/excalidraw/pull/6172
|
||||||
|
return Math.round((width / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;
|
||||||
|
}
|
||||||
|
if (container.type === "diamond") {
|
||||||
|
// The width of the largest rectangle inscribed inside a rhombus is
|
||||||
|
// Math.round(width / 2) - https://github.com/excalidraw/excalidraw/pull/6265
|
||||||
|
return Math.round(width / 2) - BOUND_TEXT_PADDING * 2;
|
||||||
|
}
|
||||||
|
return width - BOUND_TEXT_PADDING * 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMaxContainerHeight = (container: ExcalidrawElement) => {
|
||||||
|
const height = getContainerDims(container).height;
|
||||||
|
if (isArrowElement(container)) {
|
||||||
|
const containerHeight = height - BOUND_TEXT_PADDING * 8 * 2;
|
||||||
|
if (containerHeight <= 0) {
|
||||||
|
const boundText = getBoundTextElement(container);
|
||||||
|
if (boundText) {
|
||||||
|
return boundText.height;
|
||||||
|
}
|
||||||
|
return BOUND_TEXT_PADDING * 8 * 2;
|
||||||
|
}
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
if (container.type === "ellipse") {
|
||||||
|
// The height of the largest rectangle inscribed inside an ellipse is
|
||||||
|
// Math.round((ellipse.height / 2) * Math.sqrt(2)) which is derived from
|
||||||
|
// equation of an ellipse - https://github.com/excalidraw/excalidraw/pull/6172
|
||||||
|
return Math.round((height / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;
|
||||||
|
}
|
||||||
|
if (container.type === "diamond") {
|
||||||
|
// The height of the largest rectangle inscribed inside a rhombus is
|
||||||
|
// Math.round(height / 2) - https://github.com/excalidraw/excalidraw/pull/6265
|
||||||
|
return Math.round(height / 2) - BOUND_TEXT_PADDING * 2;
|
||||||
|
}
|
||||||
|
return height - BOUND_TEXT_PADDING * 2;
|
||||||
|
};
|
||||||
|
@ -791,7 +791,7 @@ describe("textWysiwyg", () => {
|
|||||||
text = h.elements[1] as ExcalidrawTextElementWithContainer;
|
text = h.elements[1] as ExcalidrawTextElementWithContainer;
|
||||||
expect(text.text).toBe("Hello \nWorld!");
|
expect(text.text).toBe("Hello \nWorld!");
|
||||||
expect(text.originalText).toBe("Hello World!");
|
expect(text.originalText).toBe("Hello World!");
|
||||||
expect(text.y).toBe(27.5);
|
expect(text.y).toBe(57.5);
|
||||||
expect(text.x).toBe(rectangle.x + BOUND_TEXT_PADDING);
|
expect(text.x).toBe(rectangle.x + BOUND_TEXT_PADDING);
|
||||||
expect(text.height).toBe(APPROX_LINE_HEIGHT * 2);
|
expect(text.height).toBe(APPROX_LINE_HEIGHT * 2);
|
||||||
expect(text.width).toBe(rectangle.width - BOUND_TEXT_PADDING * 2);
|
expect(text.width).toBe(rectangle.width - BOUND_TEXT_PADDING * 2);
|
||||||
@ -825,7 +825,7 @@ describe("textWysiwyg", () => {
|
|||||||
|
|
||||||
expect(text.text).toBe("Hello");
|
expect(text.text).toBe("Hello");
|
||||||
expect(text.originalText).toBe("Hello");
|
expect(text.originalText).toBe("Hello");
|
||||||
expect(text.y).toBe(40);
|
expect(text.y).toBe(57.5);
|
||||||
expect(text.x).toBe(rectangle.x + BOUND_TEXT_PADDING);
|
expect(text.x).toBe(rectangle.x + BOUND_TEXT_PADDING);
|
||||||
expect(text.height).toBe(APPROX_LINE_HEIGHT);
|
expect(text.height).toBe(APPROX_LINE_HEIGHT);
|
||||||
expect(text.width).toBe(rectangle.width - BOUND_TEXT_PADDING * 2);
|
expect(text.width).toBe(rectangle.width - BOUND_TEXT_PADDING * 2);
|
||||||
@ -930,6 +930,8 @@ describe("textWysiwyg", () => {
|
|||||||
editor.select();
|
editor.select();
|
||||||
|
|
||||||
fireEvent.click(screen.getByTitle("Left"));
|
fireEvent.click(screen.getByTitle("Left"));
|
||||||
|
await new Promise((r) => setTimeout(r, 0));
|
||||||
|
|
||||||
fireEvent.click(screen.getByTitle("Align bottom"));
|
fireEvent.click(screen.getByTitle("Align bottom"));
|
||||||
await new Promise((r) => setTimeout(r, 0));
|
await new Promise((r) => setTimeout(r, 0));
|
||||||
|
|
||||||
@ -1278,7 +1280,7 @@ describe("textWysiwyg", () => {
|
|||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
15,
|
15,
|
||||||
20,
|
25,
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
@ -1290,7 +1292,7 @@ describe("textWysiwyg", () => {
|
|||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
-25,
|
-25,
|
||||||
20,
|
25,
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
@ -1302,7 +1304,7 @@ describe("textWysiwyg", () => {
|
|||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
174,
|
174,
|
||||||
20,
|
25,
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
@ -24,14 +24,16 @@ import { mutateElement } from "./mutateElement";
|
|||||||
import {
|
import {
|
||||||
getApproxLineHeight,
|
getApproxLineHeight,
|
||||||
getBoundTextElementId,
|
getBoundTextElementId,
|
||||||
getBoundTextElementOffset,
|
|
||||||
getContainerCoords,
|
getContainerCoords,
|
||||||
getContainerDims,
|
getContainerDims,
|
||||||
getContainerElement,
|
getContainerElement,
|
||||||
getTextElementAngle,
|
getTextElementAngle,
|
||||||
getTextWidth,
|
getTextWidth,
|
||||||
normalizeText,
|
normalizeText,
|
||||||
|
redrawTextBoundingBox,
|
||||||
wrapText,
|
wrapText,
|
||||||
|
getMaxContainerHeight,
|
||||||
|
getMaxContainerWidth,
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
import {
|
import {
|
||||||
actionDecreaseFontSize,
|
actionDecreaseFontSize,
|
||||||
@ -39,7 +41,6 @@ import {
|
|||||||
} from "../actions/actionProperties";
|
} from "../actions/actionProperties";
|
||||||
import { actionZoomIn, actionZoomOut } from "../actions/actionCanvas";
|
import { actionZoomIn, actionZoomOut } from "../actions/actionCanvas";
|
||||||
import App from "../components/App";
|
import App from "../components/App";
|
||||||
import { getMaxContainerHeight, getMaxContainerWidth } from "./newElement";
|
|
||||||
import { LinearElementEditor } from "./linearElementEditor";
|
import { LinearElementEditor } from "./linearElementEditor";
|
||||||
import { parseClipboard } from "../clipboard";
|
import { parseClipboard } from "../clipboard";
|
||||||
|
|
||||||
@ -231,10 +232,6 @@ export const textWysiwyg = ({
|
|||||||
// Start pushing text upward until a diff of 30px (padding)
|
// Start pushing text upward until a diff of 30px (padding)
|
||||||
// is reached
|
// is reached
|
||||||
else {
|
else {
|
||||||
const padding =
|
|
||||||
container.type === "ellipse"
|
|
||||||
? 0
|
|
||||||
: getBoundTextElementOffset(updatedTextElement);
|
|
||||||
const containerCoords = getContainerCoords(container);
|
const containerCoords = getContainerCoords(container);
|
||||||
|
|
||||||
// vertically center align the text
|
// vertically center align the text
|
||||||
@ -245,8 +242,7 @@ export const textWysiwyg = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
if (verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
||||||
coordY =
|
coordY = containerCoords.y + (maxHeight - textElementHeight);
|
||||||
containerCoords.y + (maxHeight - textElementHeight + padding);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -616,6 +612,7 @@ export const textWysiwyg = ({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
redrawTextBoundingBox(updateElement, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit({
|
onSubmit({
|
||||||
|
@ -17,8 +17,11 @@ import { KEYS } from "../keys";
|
|||||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||||
import { queryByTestId, queryByText } from "@testing-library/react";
|
import { queryByTestId, queryByText } from "@testing-library/react";
|
||||||
import { resize, rotate } from "./utils";
|
import { resize, rotate } from "./utils";
|
||||||
import { getBoundTextElementPosition, wrapText } from "../element/textElement";
|
import {
|
||||||
import { getMaxContainerWidth } from "../element/newElement";
|
getBoundTextElementPosition,
|
||||||
|
wrapText,
|
||||||
|
getMaxContainerWidth,
|
||||||
|
} from "../element/textElement";
|
||||||
import * as textElementUtils from "../element/textElement";
|
import * as textElementUtils from "../element/textElement";
|
||||||
import { ROUNDNESS } from "../constants";
|
import { ROUNDNESS } from "../constants";
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user