Fixed creating text with shape tool

This commit is contained in:
hazam 2020-01-09 01:04:20 +05:00
parent 2a00d82acc
commit 0b2000d3e2
3 changed files with 82 additions and 38 deletions

View file

@ -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,

View file

@ -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;
}

View file

@ -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";