mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Fixed creating text with shape tool
This commit is contained in:
parent
2a00d82acc
commit
0b2000d3e2
3 changed files with 82 additions and 38 deletions
|
@ -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;
|
||||
});
|
||||
|
||||
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 snappedToCenterPosition = this.getTextWysiwygSnappedToCenterPosition(
|
||||
x,
|
||||
y
|
||||
);
|
||||
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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue