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:
Aakansha Doshi 2021-12-21 17:13:11 +05:30 committed by GitHub
parent 8b5657e1ce
commit 081e097cef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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) {