fix: vertically center align the bounded text correctly when zoomed (#4444)
* fix: vertically center align the bounded text correctly when zoomed * dnt add offsets since its calculated correctly * set editor max width better when offsets present * Update src/element/textWysiwyg.tsx * const * revert
This commit is contained in:
parent
8b5657e1ce
commit
081e097cef
@ -2,7 +2,6 @@ import { CODES, KEYS } from "../keys";
|
|||||||
import {
|
import {
|
||||||
isWritableElement,
|
isWritableElement,
|
||||||
getFontString,
|
getFontString,
|
||||||
viewportCoordsToSceneCoords,
|
|
||||||
getFontFamilyString,
|
getFontFamilyString,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
import Scene from "../scene/Scene";
|
import Scene from "../scene/Scene";
|
||||||
@ -37,16 +36,20 @@ const getTransform = (
|
|||||||
angle: number,
|
angle: number,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
maxWidth: number,
|
maxWidth: number,
|
||||||
|
maxHeight: number,
|
||||||
) => {
|
) => {
|
||||||
const { zoom, offsetTop, offsetLeft } = appState;
|
const { zoom, offsetTop, offsetLeft } = appState;
|
||||||
const degree = (180 * angle) / Math.PI;
|
const degree = (180 * angle) / Math.PI;
|
||||||
// offsets must be multiplied by 2 to account for the division by 2 of
|
// offsets must be multiplied by 2 to account for the division by 2 of
|
||||||
// the whole expression afterwards
|
// the whole expression afterwards
|
||||||
let translateX = ((width - offsetLeft * 2) * (zoom.value - 1)) / 2;
|
let translateX = ((width - offsetLeft * 2) * (zoom.value - 1)) / 2;
|
||||||
const translateY = ((height - offsetTop * 2) * (zoom.value - 1)) / 2;
|
let translateY = ((height - offsetTop * 2) * (zoom.value - 1)) / 2;
|
||||||
if (width > maxWidth && zoom.value !== 1) {
|
if (width > maxWidth && zoom.value !== 1) {
|
||||||
translateX = (maxWidth / 2) * (zoom.value - 1);
|
translateX = (maxWidth / 2) * (zoom.value - 1);
|
||||||
}
|
}
|
||||||
|
if (height > maxHeight && zoom.value !== 1) {
|
||||||
|
translateY = ((maxHeight - offsetTop * 2) * (zoom.value - 1)) / 2;
|
||||||
|
}
|
||||||
return `translate(${translateX}px, ${translateY}px) scale(${zoom.value}) rotate(${degree}deg)`;
|
return `translate(${translateX}px, ${translateY}px) scale(${zoom.value}) rotate(${degree}deg)`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,12 +109,13 @@ export const textWysiwyg = ({
|
|||||||
|
|
||||||
let maxHeight = updatedElement.height;
|
let maxHeight = updatedElement.height;
|
||||||
let width = updatedElement.width;
|
let width = updatedElement.width;
|
||||||
let height = updatedElement.height;
|
const height = Math.max(editable.scrollHeight, updatedElement.height);
|
||||||
if (container && updatedElement.containerId) {
|
if (container && updatedElement.containerId) {
|
||||||
const propertiesUpdated = textPropertiesUpdated(
|
const propertiesUpdated = textPropertiesUpdated(
|
||||||
updatedElement,
|
updatedElement,
|
||||||
editable,
|
editable,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (propertiesUpdated) {
|
if (propertiesUpdated) {
|
||||||
const currentContainer = Scene.getScene(updatedElement)?.getElement(
|
const currentContainer = Scene.getScene(updatedElement)?.getElement(
|
||||||
updatedElement.containerId,
|
updatedElement.containerId,
|
||||||
@ -133,15 +137,14 @@ export const textWysiwyg = ({
|
|||||||
maxWidth = container.width - PADDING * 2;
|
maxWidth = container.width - PADDING * 2;
|
||||||
maxHeight = container.height - PADDING * 2;
|
maxHeight = container.height - PADDING * 2;
|
||||||
width = maxWidth;
|
width = maxWidth;
|
||||||
height = Math.min(height, maxHeight);
|
|
||||||
// The coordinates of text box set a distance of
|
// The coordinates of text box set a distance of
|
||||||
// 30px to preserve padding
|
// 30px to preserve padding
|
||||||
coordX = container.x + PADDING;
|
coordX = container.x + PADDING;
|
||||||
|
|
||||||
// autogrow container height if text exceeds
|
// autogrow container height if text exceeds
|
||||||
if (editable.clientHeight > maxHeight) {
|
if (editable.scrollHeight > maxHeight) {
|
||||||
const diff = Math.min(
|
const diff = Math.min(
|
||||||
editable.clientHeight - maxHeight,
|
editable.scrollHeight - maxHeight,
|
||||||
approxLineHeight,
|
approxLineHeight,
|
||||||
);
|
);
|
||||||
mutateElement(container, { height: container.height + diff });
|
mutateElement(container, { height: container.height + diff });
|
||||||
@ -150,10 +153,10 @@ export const textWysiwyg = ({
|
|||||||
// autoshrink container height until original container height
|
// autoshrink container height until original container height
|
||||||
// is reached when text is removed
|
// is reached when text is removed
|
||||||
container.height > originalContainerHeight &&
|
container.height > originalContainerHeight &&
|
||||||
editable.clientHeight < maxHeight
|
editable.scrollHeight < maxHeight
|
||||||
) {
|
) {
|
||||||
const diff = Math.min(
|
const diff = Math.min(
|
||||||
maxHeight - editable.clientHeight,
|
maxHeight - editable.scrollHeight,
|
||||||
approxLineHeight,
|
approxLineHeight,
|
||||||
);
|
);
|
||||||
mutateElement(container, { height: container.height - diff });
|
mutateElement(container, { height: container.height - diff });
|
||||||
@ -161,18 +164,17 @@ 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 lines = editable.clientHeight / approxLineHeight;
|
const lines = editable.scrollHeight / approxLineHeight;
|
||||||
// For some reason the scrollHeight gets set to twice the lineHeight
|
// For some reason the scrollHeight gets set to twice the lineHeight
|
||||||
// when you start typing for first time and thus line count is 2
|
// when you start typing for first time and thus line count is 2
|
||||||
// hence this check
|
// hence this check
|
||||||
if (lines > 2 || propertiesUpdated) {
|
if (lines > 2 || propertiesUpdated) {
|
||||||
// vertically center align the text
|
// vertically center align the text
|
||||||
coordY =
|
coordY =
|
||||||
container.y + container.height / 2 - editable.clientHeight / 2;
|
container.y + container.height / 2 - editable.scrollHeight / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [viewportX, viewportY] = getViewportCoords(coordX, coordY);
|
const [viewportX, viewportY] = getViewportCoords(coordX, coordY);
|
||||||
const { textAlign, angle } = updatedElement;
|
const { textAlign, angle } = updatedElement;
|
||||||
|
|
||||||
@ -192,19 +194,35 @@ export const textWysiwyg = ({
|
|||||||
).marginRight.slice(0, -2),
|
).marginRight.slice(0, -2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure text editor height doesn't go beyond viewport
|
// Make sure text editor height doesn't go beyond viewport
|
||||||
const editorMaxHeight =
|
const editorMaxHeight =
|
||||||
(appState.offsetTop + appState.height - viewportY) /
|
(appState.height -
|
||||||
|
viewportY -
|
||||||
|
// There is a ~14px difference which keeps on increasing
|
||||||
|
// with every zoom step when offset present hence I am subtracting it here
|
||||||
|
// However this is not the best fix and breaks in
|
||||||
|
// few scenarios
|
||||||
|
(appState.offsetTop
|
||||||
|
? ((appState.zoom.value * 100 - 100) / 10) * 14
|
||||||
|
: 0)) /
|
||||||
appState.zoom.value;
|
appState.zoom.value;
|
||||||
Object.assign(editable.style, {
|
Object.assign(editable.style, {
|
||||||
font: getFontString(updatedElement),
|
font: getFontString(updatedElement),
|
||||||
// must be defined *after* font ¯\_(ツ)_/¯
|
// must be defined *after* font ¯\_(ツ)_/¯
|
||||||
lineHeight: `${lineHeight}px`,
|
lineHeight: `${lineHeight}px`,
|
||||||
width: `${width}px`,
|
width: `${width}px`,
|
||||||
height: `${Math.max(editable.clientHeight, updatedElement.height)}px`,
|
height: `${height}px`,
|
||||||
left: `${viewportX}px`,
|
left: `${viewportX}px`,
|
||||||
top: `${viewportY}px`,
|
top: `${viewportY}px`,
|
||||||
transform: getTransform(width, height, angle, appState, maxWidth),
|
transform: getTransform(
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
angle,
|
||||||
|
appState,
|
||||||
|
maxWidth,
|
||||||
|
editorMaxHeight,
|
||||||
|
),
|
||||||
textAlign,
|
textAlign,
|
||||||
color: updatedElement.strokeColor,
|
color: updatedElement.strokeColor,
|
||||||
opacity: updatedElement.opacity / 100,
|
opacity: updatedElement.opacity / 100,
|
||||||
@ -416,20 +434,16 @@ export const textWysiwyg = ({
|
|||||||
getFontString(updateElement),
|
getFontString(updateElement),
|
||||||
container.width,
|
container.width,
|
||||||
);
|
);
|
||||||
const { x, y } = viewportCoordsToSceneCoords(
|
|
||||||
{
|
|
||||||
clientX: Number(editable.style.left.slice(0, -2)),
|
|
||||||
clientY: Number(editable.style.top.slice(0, -2)),
|
|
||||||
},
|
|
||||||
appState,
|
|
||||||
);
|
|
||||||
if (isTextElement(updateElement) && updateElement.containerId) {
|
if (isTextElement(updateElement) && updateElement.containerId) {
|
||||||
|
const editorHeight = Number(editable.style.height.slice(0, -2));
|
||||||
if (editable.value) {
|
if (editable.value) {
|
||||||
mutateElement(updateElement, {
|
mutateElement(updateElement, {
|
||||||
y: y + appState.offsetTop,
|
// vertically center align
|
||||||
height: Number(editable.style.height.slice(0, -2)),
|
y: container.y + container.height / 2 - editorHeight / 2,
|
||||||
|
height: editorHeight,
|
||||||
width: Number(editable.style.width.slice(0, -2)),
|
width: Number(editable.style.width.slice(0, -2)),
|
||||||
x: x + appState.offsetLeft,
|
// preserve padding
|
||||||
|
x: container.x + PADDING,
|
||||||
});
|
});
|
||||||
const boundTextElementId = getBoundTextElementId(container);
|
const boundTextElementId = getBoundTextElementId(container);
|
||||||
if (!boundTextElementId || boundTextElementId !== element.id) {
|
if (!boundTextElementId || boundTextElementId !== element.id) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user