feat: Support updating text properties by clicking on container (#4499)

This commit is contained in:
Aakansha Doshi 2021-12-29 16:49:52 +05:30 committed by GitHub
parent 11396a21de
commit dd8e465304
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 99 additions and 55 deletions

View File

@ -57,21 +57,27 @@ import {
canChangeSharpness,
canHaveArrowheads,
getCommonAttributeOfSelectedElements,
getSelectedElements,
getTargetElements,
isSomeElementSelected,
} from "../scene";
import { hasStrokeColor } from "../scene/comparisons";
import Scene from "../scene/Scene";
import { arrayToMap } from "../utils";
import { register } from "./register";
const changeProperty = (
elements: readonly ExcalidrawElement[],
appState: AppState,
callback: (element: ExcalidrawElement) => ExcalidrawElement,
includeBoundText = false,
) => {
const selectedElementIds = arrayToMap(
getSelectedElements(elements, appState, includeBoundText),
);
return elements.map((element) => {
if (
appState.selectedElementIds[element.id] ||
selectedElementIds.get(element.id) ||
element.id === appState.editingElement?.id
) {
return callback(element);
@ -427,7 +433,10 @@ export const actionChangeFontSize = register({
name: "changeFontSize",
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) => {
elements: changeProperty(
elements,
appState,
(el) => {
if (isTextElement(el)) {
const element: ExcalidrawTextElement = newElementWith(el, {
fontSize: value,
@ -436,12 +445,14 @@ export const actionChangeFontSize = register({
if (el.containerId) {
container = Scene.getScene(el)!.getElement(el.containerId);
}
redrawTextBoundingBox(element, container);
redrawTextBoundingBox(element, container, appState);
return element;
}
return el;
}),
},
true,
),
appState: {
...appState,
currentItemFontSize: value,
@ -492,7 +503,10 @@ export const actionChangeFontFamily = register({
name: "changeFontFamily",
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) => {
elements: changeProperty(
elements,
appState,
(el) => {
if (isTextElement(el)) {
const element: ExcalidrawTextElement = newElementWith(el, {
fontFamily: value,
@ -501,12 +515,14 @@ export const actionChangeFontFamily = register({
if (el.containerId) {
container = Scene.getScene(el)!.getElement(el.containerId);
}
redrawTextBoundingBox(element, container);
redrawTextBoundingBox(element, container, appState);
return element;
}
return el;
}),
},
true,
),
appState: {
...appState,
currentItemFontFamily: value,
@ -560,7 +576,10 @@ export const actionChangeTextAlign = register({
name: "changeTextAlign",
perform: (elements, appState, value) => {
return {
elements: changeProperty(elements, appState, (el) => {
elements: changeProperty(
elements,
appState,
(el) => {
if (isTextElement(el)) {
const element: ExcalidrawTextElement = newElementWith(el, {
textAlign: value,
@ -569,12 +588,14 @@ export const actionChangeTextAlign = register({
if (el.containerId) {
container = Scene.getScene(el)!.getElement(el.containerId);
}
redrawTextBoundingBox(element, container);
redrawTextBoundingBox(element, container, appState);
return element;
}
return el;
}),
},
true,
),
appState: {
...appState,
currentItemTextAlign: value,

View File

@ -71,7 +71,11 @@ export const actionPasteStyles = register({
element.containerId,
);
}
redrawTextBoundingBox(element as ExcalidrawTextElement, container);
redrawTextBoundingBox(
element as ExcalidrawTextElement,
container,
appState,
);
}
return newElement;
}

View File

@ -10,24 +10,52 @@ import { mutateElement } from "./mutateElement";
import { BOUND_TEXT_PADDING } from "../constants";
import { MaybeTransformHandleType } from "./transformHandles";
import Scene from "../scene/Scene";
import { AppState } from "../types";
import { isTextElement } from ".";
export const redrawTextBoundingBox = (
element: ExcalidrawTextElement,
container: ExcalidrawElement | null,
appState: AppState,
) => {
const maxWidth = container
? container.width - BOUND_TEXT_PADDING * 2
: undefined;
let text = element.originalText;
// Call wrapText only when updating text properties
// By clicking on the container
if (container && !isTextElement(appState.editingElement)) {
text = wrapText(
element.originalText,
getFontString(element),
container.width,
);
}
const metrics = measureText(
element.originalText,
getFontString(element),
maxWidth,
);
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;
}
mutateElement(container, { height: nextHeight });
}
mutateElement(element, {
width: metrics.width,
height: metrics.height,
baseline: metrics.baseline,
y: coordY,
text,
});
};

View File

@ -102,7 +102,7 @@ export const textWysiwyg = ({
if (updatedElement && isTextElement(updatedElement)) {
let coordX = updatedElement.x;
let coordY = updatedElement.y;
let container = updatedElement?.containerId
const container = updatedElement?.containerId
? Scene.getScene(updatedElement)!.getElement(updatedElement.containerId)
: null;
let maxWidth = updatedElement.width;
@ -123,21 +123,12 @@ export const textWysiwyg = ({
height = editorHeight;
}
if (propertiesUpdated) {
const currentContainer = Scene.getScene(updatedElement)?.getElement(
updatedElement.containerId,
) as ExcalidrawBindableElement;
approxLineHeight = isTextElement(updatedElement)
? getApproxLineHeight(getFontString(updatedElement))
: 0;
if (
updatedElement.height >
currentContainer.height - BOUND_TEXT_PADDING * 2
) {
const nextHeight = updatedElement.height + BOUND_TEXT_PADDING * 2;
originalContainerHeight = nextHeight;
mutateElement(container, { height: nextHeight });
container = { ...container, height: nextHeight };
}
originalContainerHeight = container.height;
// update height of the editor after properties updated
height = updatedElement.height;
}

View File

@ -77,4 +77,4 @@ export const getTargetElements = (
) =>
appState.editingElement
? [appState.editingElement]
: getSelectedElements(elements, appState);
: getSelectedElements(elements, appState, true);