diff --git a/app/components/elements/editable-text.jsx b/app/components/elements/editable-text.jsx index bb98088e..1221ca2b 100644 --- a/app/components/elements/editable-text.jsx +++ b/app/components/elements/editable-text.jsx @@ -13,15 +13,16 @@ export const EditableText = props => { const previewStyles = { width: props.width + "px", height: props.height + "px", - whiteSpace: "pre-wrap", // "pre-wrap", + whiteSpace: "pre-wrap", color: props.textColor, fontFamily: props.textFont, fontSize: props.textSize + "px", lineHeight: "normal", textAlign: props.textAlign, userSelect: "none", - wordBreak: "break-all", + // wordBreak: "break-all", overflow: "hidden", + overflowWrap: "break-word", }; // Enable autofocus when element changes to editable @@ -65,7 +66,8 @@ export const EditableText = props => { textAlign: props.textAlign, // transform: "translateX(-50%) translateY(-50%)", whiteSpace: "pre-wrap", - wordBreak: "break-all", + // wordBreak: "break-all", + overflowWrap: "break-word", }} onPointerDown={stopEventPropagation} onMouseDown={stopEventPropagation} diff --git a/app/constants.js b/app/constants.js index b371d235..7b66b1a0 100644 --- a/app/constants.js +++ b/app/constants.js @@ -237,7 +237,7 @@ export const TEXT_SIZES = { XLARGE: 64, }; -export const TEXT_SIZE_STEP = 8; +export const TEXT_SIZE_STEP = 2; export const TEXT_SIZE_MIN = 8; export const TEXT_SIZE_MAX = 256; diff --git a/app/elements.js b/app/elements.js index ee297ad3..cf2810d0 100644 --- a/app/elements.js +++ b/app/elements.js @@ -91,57 +91,55 @@ const checkStrokeStyleValue = initialValue => { // allow to perserve the aspect ratio of the element const preserveAspectRatio = (element, snapshot, event) => { - if (event.shiftKey) { - const ratio = (snapshot.y2 - snapshot.y1) / Math.max(1, snapshot.x2 - snapshot.x1); - if (event.handler === HANDLERS.CORNER_TOP_LEFT) { - if (event.dx * ratio < event.dy) { - element.y1 = snapshot.y1 + ((element.x1 - snapshot.x1) * ratio); - } - else { - element.x1 = snapshot.x1 + ((element.y1 - snapshot.y1) / ratio); - } + const ratio = (snapshot.y2 - snapshot.y1) / Math.max(1, snapshot.x2 - snapshot.x1); + if (event.handler === HANDLERS.CORNER_TOP_LEFT) { + if (event.dx * ratio < event.dy) { + element.y1 = snapshot.y1 + ((element.x1 - snapshot.x1) * ratio); } - else if (event.handler === HANDLERS.CORNER_TOP_RIGHT) { - if ((-1) * event.dx * ratio < event.dy) { - element.y1 = snapshot.y1 - ((element.x2 - snapshot.x2) * ratio); - } - else { - element.x2 = snapshot.x2 - ((element.y1 - snapshot.y1) / ratio); - } + else { + element.x1 = snapshot.x1 + ((element.y1 - snapshot.y1) / ratio); } - else if (event.handler === HANDLERS.CORNER_BOTTOM_LEFT) { - if ((-1) * event.dx * ratio > event.dy) { - element.y2 = snapshot.y2 - ((element.x1 - snapshot.x1) * ratio); - } - else { - element.x1 = snapshot.x1 - ((element.y2 - snapshot.y2) / ratio); - } + } + else if (event.handler === HANDLERS.CORNER_TOP_RIGHT) { + if ((-1) * event.dx * ratio < event.dy) { + element.y1 = snapshot.y1 - ((element.x2 - snapshot.x2) * ratio); } - else if (event.handler === HANDLERS.CORNER_BOTTOM_RIGHT) { - if (event.dx * ratio > event.dy) { - element.y2 = snapshot.y2 + ((element.x2 - snapshot.x2) * ratio); - } - else { - element.x2 = snapshot.x2 + ((element.y2 - snapshot.y2) / ratio); - } + else { + element.x2 = snapshot.x2 - ((element.y1 - snapshot.y1) / ratio); } - else if (event.handler === HANDLERS.EDGE_TOP) { - element.x1 = snapshot.x1 + ((snapshot.x2 - snapshot.x1) / 2) - ((element.y2 - element.y1) / (2 * ratio)); - element.x2 = snapshot.x2 - ((snapshot.x2 - snapshot.x1) / 2) + ((element.y2 - element.y1) / (2 * ratio)); + } + else if (event.handler === HANDLERS.CORNER_BOTTOM_LEFT) { + if ((-1) * event.dx * ratio > event.dy) { + element.y2 = snapshot.y2 - ((element.x1 - snapshot.x1) * ratio); } - else if (event.handler === HANDLERS.EDGE_BOTTOM) { - element.x1 = snapshot.x1 + ((snapshot.x2 - snapshot.x1) / 2) - ((element.y2 - element.y1) / (2 * ratio)); - element.x2 = snapshot.x2 - ((snapshot.x2 - snapshot.x1) / 2) + ((element.y2 - element.y1) / (2 * ratio)); + else { + element.x1 = snapshot.x1 - ((element.y2 - snapshot.y2) / ratio); } - else if (event.handler === HANDLERS.EDGE_LEFT) { - element.y1 = snapshot.y1 + ((snapshot.y2 - snapshot.y1) / 2) - ((element.x2 - element.x1) * ratio) / 2; - element.y2 = snapshot.y2 - ((snapshot.y2 - snapshot.y1) / 2) + ((element.x2 - element.x1) * ratio) / 2; + } + else if (event.handler === HANDLERS.CORNER_BOTTOM_RIGHT) { + if (event.dx * ratio > event.dy) { + element.y2 = snapshot.y2 + ((element.x2 - snapshot.x2) * ratio); } - else if (event.handler === HANDLERS.EDGE_RIGHT) { - element.y1 = snapshot.y1 + ((snapshot.y2 - snapshot.y1) / 2) - ((element.x2 - element.x1) * ratio) / 2; - element.y2 = snapshot.y2 - ((snapshot.y2 - snapshot.y1) / 2) + ((element.x2 - element.x1) * ratio) / 2; + else { + element.x2 = snapshot.x2 + ((element.y2 - snapshot.y2) / ratio); } } + else if (event.handler === HANDLERS.EDGE_TOP) { + element.x1 = snapshot.x1 + ((snapshot.x2 - snapshot.x1) / 2) - ((element.y2 - element.y1) / (2 * ratio)); + element.x2 = snapshot.x2 - ((snapshot.x2 - snapshot.x1) / 2) + ((element.y2 - element.y1) / (2 * ratio)); + } + else if (event.handler === HANDLERS.EDGE_BOTTOM) { + element.x1 = snapshot.x1 + ((snapshot.x2 - snapshot.x1) / 2) - ((element.y2 - element.y1) / (2 * ratio)); + element.x2 = snapshot.x2 - ((snapshot.x2 - snapshot.x1) / 2) + ((element.y2 - element.y1) / (2 * ratio)); + } + else if (event.handler === HANDLERS.EDGE_LEFT) { + element.y1 = snapshot.y1 + ((snapshot.y2 - snapshot.y1) / 2) - ((element.x2 - element.x1) * ratio) / 2; + element.y2 = snapshot.y2 - ((snapshot.y2 - snapshot.y1) / 2) + ((element.x2 - element.x1) * ratio) / 2; + } + else if (event.handler === HANDLERS.EDGE_RIGHT) { + element.y1 = snapshot.y1 + ((snapshot.y2 - snapshot.y1) / 2) - ((element.x2 - element.x1) * ratio) / 2; + element.y2 = snapshot.y2 - ((snapshot.y2 - snapshot.y1) / 2) + ((element.x2 - element.x1) * ratio) / 2; + } }; export const elementsConfig = { @@ -193,14 +191,29 @@ export const elementsConfig = { y2: Math.max(element.y1, element.y2), }); }, - onResize: preserveAspectRatio, + onResize: (element, snapshot, event) => { + if (event.shiftKey) { + preserveAspectRatio(element, snapshot, event); + } + // Check if we have a text inside the shape + if (element.text) { + const width = Math.abs(element.x2 - element.x1); + const [textWidth, textHeight] = measureText(element.text || " ", element.textSize, element.textFont, width + "px"); + element.textWidth = textWidth; + element.textHeight = textHeight; + } + }, onUpdate: (element, changedKeys) => { if (element.text && (changedKeys.has("textFont") || changedKeys.has("textSize"))) { - const [textWidth, textHeight] = measureText(element.text || " ", element.textSize, element.textFont); + const width = Math.abs(element.x2 - element.x1); + const [textWidth, textHeight] = measureText(element.text || " ", element.textSize, element.textFont, width + "px"); element.textWidth = textWidth; element.textHeight = textHeight; } }, + getUpdatedFields: element => { + return element.text ? ["textWidth", "textHeight"] : []; + }, }, [ELEMENTS.ARROW]: { displayName: "Arrow", @@ -433,9 +446,10 @@ export const elementsConfig = { }, onResize: (element, snapshot, event) => { const handler = event.handler || ""; - const width = Math.abs(element.x2 - element.x1); - const height = Math.abs(element.y2 - element.y1); if (isCornerHandler(handler) || handler === HANDLERS.EDGE_BOTTOM || handler === HANDLERS.EDGE_TOP) { + preserveAspectRatio(element, snapshot, event); + const width = Math.abs(element.x2 - element.x1); + const height = Math.abs(element.y2 - element.y1); let textSize = TEXT_SIZE_MIN; while (textSize <= TEXT_SIZE_MAX) { const size = measureText(element.text || " ", textSize, element.textFont, width + "px"); @@ -447,20 +461,13 @@ export const elementsConfig = { element.textHeight = size[1]; textSize = textSize + TEXT_SIZE_STEP; } - // Terrible hack to prevent having 0px text elements - if (handler === HANDLERS.EDGE_BOTTOM || handler === HANDLERS.CORNER_BOTTOM_LEFT || handler === HANDLERS.CORNER_BOTTOM_RIGHT) { - element.y2 = element.y1 + Math.max(height, element.textHeight, GRID_SIZE); - } - else { - element.y1 = element.y2 - Math.max(height, element.textHeight, GRID_SIZE); - } } else if (handler === HANDLERS.EDGE_LEFT || handler === HANDLERS.EDGE_RIGHT) { + const width = Math.abs(element.x2 - element.x1); const sizes = measureText(element.text || " ", element.textSize, element.textFont, width + "px"); element.textWidth = sizes[0]; element.textHeight = sizes[1]; - element.y1 = snapshot.y1; - element.y2 = element.y1 + Math.ceil(sizes[1] / GRID_SIZE) * GRID_SIZE; + element.y2 = element.y1 + element.textHeight; // fix height } // Terrible hack to prevent having 0px text elements if (handler === HANDLERS.EDGE_LEFT || handler === HANDLERS.CORNER_TOP_LEFT || handler === HANDLERS.CORNER_BOTTOM_LEFT) { @@ -524,7 +531,11 @@ export const elementsConfig = { element.drawWidth = Math.abs(element.x2 - element.x1); element.drawHeight = Math.abs(element.y2 - element.y1); }, - onResize: preserveAspectRatio, + onResize: (element, snapshot, event) => { + if (event.shiftKey) { + return preserveAspectRatio(element, snapshot, event); + } + }, }, [ELEMENTS.IMAGE]: { displayName: "Image", @@ -533,7 +544,11 @@ export const elementsConfig = { [FIELDS.ASSET_ID]: "", [FIELDS.OPACITY]: DEFAULTS.OPACITY, }), - onResize: preserveAspectRatio, + onResize: (element, snapshot, event) => { + if (event.shiftKey) { + return preserveAspectRatio(element, snapshot, event); + } + }, }, [ELEMENTS.NOTE]: { displayName: "Note", diff --git a/app/utils/math.js b/app/utils/math.js index 6df476ad..a3a42ec0 100644 --- a/app/utils/math.js +++ b/app/utils/math.js @@ -123,7 +123,8 @@ export const measureText = (text, textSize, textFont, maxWidth) => { measureText.container.style.left = "-9999px"; measureText.container.style.lineHeight = "normal"; // Set line-height as normal measureText.container.style.whiteSpace = "pre-wrap"; - measureText.container.style.wordBreak = "break-all"; + // measureText.container.style.wordBreak = "keep-all"; + measureText.container.style.overflowWrap = "break-word"; measureText.container.style.minHeight = "1em"; measureText.container.style.minWidth = "1em"; measureText.container.style.margin = "0";