From 0b2000d3e2ac5a60736b2f2611ea1257e1534130 Mon Sep 17 00:00:00 2001 From: hazam Date: Thu, 9 Jan 2020 01:04:20 +0500 Subject: [PATCH] Fixed creating text with shape tool --- src/index.tsx | 95 ++++++++++++++++++++++++---------------- src/scene/comparisons.ts | 18 ++++++++ src/scene/index.ts | 7 ++- 3 files changed, 82 insertions(+), 38 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 9a2456f6a..2648d7212 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,8 +8,7 @@ import { duplicateElement, resizeTest, isTextElement, - textWysiwyg, - getElementAbsoluteCoords + textWysiwyg } from "./element"; import { clearSelection, @@ -27,7 +26,8 @@ import { hasBackground, hasStroke, getElementAtPosition, - createScene + createScene, + getElementContainingPosition } from "./scene"; import { renderScene } from "./renderer"; @@ -704,10 +704,25 @@ class App extends React.Component<{}, AppState> { } if (isTextElement(element)) { + let textX = e.clientX; + let textY = e.clientY; + if (!e.altKey) { + const snappedToCenterPosition = this.getTextWysiwygSnappedToCenterPosition( + x, + y + ); + if (snappedToCenterPosition) { + element.x = snappedToCenterPosition.elementCenterX; + element.y = snappedToCenterPosition.elementCenterY; + textX = snappedToCenterPosition.wysiwygX; + textY = snappedToCenterPosition.wysiwygY; + } + } + textWysiwyg({ initText: "", - x: e.clientX, - y: e.clientY, + x: textX, + y: textY, strokeColor: this.state.currentItemStrokeColor, font: this.state.currentItemFont, onSubmit: text => { @@ -971,39 +986,16 @@ class App extends React.Component<{}, AppState> { CANVAS_WINDOW_OFFSET_TOP + elementAtPosition.height / 2; } else if (!e.altKey) { - // Element must be searched from the end - // to pick element with the highest z-index - const elementClickedInside = elements - .slice() - .reverse() - .find(element => { - const [x1, y1, x2, y2] = getElementAbsoluteCoords(element); - return x1 < x && x < x2 && y1 < y && y < y2; - }); + const snappedToCenterPosition = this.getTextWysiwygSnappedToCenterPosition( + x, + y + ); - if (elementClickedInside) { - const elementCenterX = - elementClickedInside.x + elementClickedInside.width / 2; - const elementCenterY = - elementClickedInside.y + elementClickedInside.height / 2; - const distanceToCenter = Math.hypot( - x - elementCenterX, - y - elementCenterY - ); - if (distanceToCenter < TEXT_TO_CENTER_SNAP_THRESHOLD) { - element.x = elementCenterX; - element.y = elementCenterY; - textX = - this.state.scrollX + - elementClickedInside.x + - CANVAS_WINDOW_OFFSET_LEFT + - elementClickedInside.width / 2; - textY = - this.state.scrollY + - elementClickedInside.y + - CANVAS_WINDOW_OFFSET_TOP + - elementClickedInside.height / 2; - } + if (snappedToCenterPosition) { + element.x = snappedToCenterPosition.elementCenterX; + element.y = snappedToCenterPosition.elementCenterY; + textX = snappedToCenterPosition.wysiwygX; + textY = snappedToCenterPosition.wysiwygY; } } @@ -1071,6 +1063,35 @@ class App extends React.Component<{}, AppState> { } }; + private getTextWysiwygSnappedToCenterPosition(x: number, y: number) { + const elementClickedInside = getElementContainingPosition(elements, x, y); + if (elementClickedInside) { + const elementCenterX = + elementClickedInside.x + elementClickedInside.width / 2; + const elementCenterY = + elementClickedInside.y + elementClickedInside.height / 2; + const distanceToCenter = Math.hypot( + x - elementCenterX, + y - elementCenterY + ); + const isSnappedToCenter = + distanceToCenter < TEXT_TO_CENTER_SNAP_THRESHOLD; + if (isSnappedToCenter) { + const wysiwygX = + this.state.scrollX + + elementClickedInside.x + + CANVAS_WINDOW_OFFSET_LEFT + + elementClickedInside.width / 2; + const wysiwygY = + this.state.scrollY + + elementClickedInside.y + + CANVAS_WINDOW_OFFSET_TOP + + elementClickedInside.height / 2; + return { wysiwygX, wysiwygY, elementCenterX, elementCenterY }; + } + } + } + componentDidUpdate() { renderScene(elements, rc, canvas, { scrollX: this.state.scrollX, diff --git a/src/scene/comparisons.ts b/src/scene/comparisons.ts index 0acc4a332..a1a3d41d6 100644 --- a/src/scene/comparisons.ts +++ b/src/scene/comparisons.ts @@ -1,5 +1,6 @@ import { ExcalidrawElement } from "../element/types"; import { hitTest } from "../element/collision"; +import { getElementAbsoluteCoords } from "../element"; export const hasBackground = (elements: ExcalidrawElement[]) => elements.some( @@ -36,3 +37,20 @@ export function getElementAtPosition( return hitElement; } + +export function getElementContainingPosition( + elements: ExcalidrawElement[], + x: number, + y: number +) { + let hitElement = null; + // We need to to hit testing from front (end of the array) to back (beginning of the array) + for (let i = elements.length - 1; i >= 0; --i) { + const [x1, y1, x2, y2] = getElementAbsoluteCoords(elements[i]); + if (x1 < x && x < x2 && y1 < y && y < y2) { + hitElement = elements[i]; + break; + } + } + return hitElement; +} diff --git a/src/scene/index.ts b/src/scene/index.ts index 71e78d69b..479c60efa 100644 --- a/src/scene/index.ts +++ b/src/scene/index.ts @@ -14,5 +14,10 @@ export { restoreFromLocalStorage, saveToLocalStorage } from "./data"; -export { hasBackground, hasStroke, getElementAtPosition } from "./comparisons"; +export { + hasBackground, + hasStroke, + getElementAtPosition, + getElementContainingPosition +} from "./comparisons"; export { createScene } from "./createScene";