mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Merge 60907a5a0e
into debf2ad608
This commit is contained in:
commit
741ddd4e16
48 changed files with 860 additions and 851 deletions
|
@ -29,7 +29,7 @@ import {
|
|||
|
||||
import { isPointOnShape } from "@excalidraw/utils/collision";
|
||||
|
||||
import type { LocalPoint, Radians } from "@excalidraw/math";
|
||||
import type { GenericPoint, LocalPoint, Radians } from "@excalidraw/math";
|
||||
|
||||
import type Scene from "@excalidraw/excalidraw/scene/Scene";
|
||||
|
||||
|
@ -425,10 +425,10 @@ export const getSuggestedBindingsForArrows = (
|
|||
);
|
||||
};
|
||||
|
||||
export const maybeBindLinearElement = (
|
||||
export const maybeBindLinearElement = <Point extends GenericPoint>(
|
||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||
appState: AppState,
|
||||
pointerCoords: { x: number; y: number },
|
||||
pointerCoords: Point,
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
): void => {
|
||||
|
@ -576,11 +576,8 @@ const unbindLinearElement = (
|
|||
return binding.elementId;
|
||||
};
|
||||
|
||||
export const getHoveredElementForBinding = (
|
||||
pointerCoords: {
|
||||
x: number;
|
||||
y: number;
|
||||
},
|
||||
export const getHoveredElementForBinding = <Point extends GenericPoint>(
|
||||
pointerCoords: Point,
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
|
@ -1392,11 +1389,11 @@ const getElligibleElementForBindingElement = (
|
|||
);
|
||||
};
|
||||
|
||||
const getLinearElementEdgeCoors = (
|
||||
const getLinearElementEdgeCoors = <Point extends GenericPoint>(
|
||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||
startOrEnd: "start" | "end",
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
): { x: number; y: number } => {
|
||||
): Point => {
|
||||
const index = startOrEnd === "start" ? 0 : -1;
|
||||
return tupleToCoors(
|
||||
LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||
|
@ -1516,9 +1513,9 @@ const newBoundElements = (
|
|||
return nextBoundElements;
|
||||
};
|
||||
|
||||
export const bindingBorderTest = (
|
||||
export const bindingBorderTest = <Point extends GenericPoint>(
|
||||
element: NonDeleted<ExcalidrawBindableElement>,
|
||||
{ x, y }: { x: number; y: number },
|
||||
[x, y]: Point,
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
fullShape?: boolean,
|
||||
|
|
|
@ -23,6 +23,7 @@ import { pointsOnBezierCurves } from "points-on-curve";
|
|||
import type {
|
||||
Curve,
|
||||
Degrees,
|
||||
GenericPoint,
|
||||
GlobalPoint,
|
||||
LineSegment,
|
||||
LocalPoint,
|
||||
|
@ -1057,7 +1058,7 @@ export const getElementPointsCoords = (
|
|||
|
||||
export const getClosestElementBounds = (
|
||||
elements: readonly ExcalidrawElement[],
|
||||
from: { x: number; y: number },
|
||||
from: GenericPoint,
|
||||
): Bounds => {
|
||||
if (!elements.length) {
|
||||
return [0, 0, 0, 0];
|
||||
|
@ -1070,7 +1071,7 @@ export const getClosestElementBounds = (
|
|||
const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);
|
||||
const distance = pointDistance(
|
||||
pointFrom((x1 + x2) / 2, (y1 + y2) / 2),
|
||||
pointFrom(from.x, from.y),
|
||||
from,
|
||||
);
|
||||
|
||||
if (distance < minDistance) {
|
||||
|
|
|
@ -19,9 +19,9 @@ import { isPointInShape, isPointOnShape } from "@excalidraw/utils/collision";
|
|||
import { type GeometricShape, getPolygonShape } from "@excalidraw/utils/shape";
|
||||
|
||||
import type {
|
||||
GenericPoint,
|
||||
GlobalPoint,
|
||||
LineSegment,
|
||||
LocalPoint,
|
||||
Polygon,
|
||||
Radians,
|
||||
} from "@excalidraw/math";
|
||||
|
@ -72,7 +72,7 @@ export const shouldTestInside = (element: ExcalidrawElement) => {
|
|||
return isDraggableFromInside || isImageElement(element);
|
||||
};
|
||||
|
||||
export type HitTestArgs<Point extends GlobalPoint | LocalPoint> = {
|
||||
export type HitTestArgs<Point extends GenericPoint> = {
|
||||
x: number;
|
||||
y: number;
|
||||
element: ExcalidrawElement;
|
||||
|
@ -81,7 +81,7 @@ export type HitTestArgs<Point extends GlobalPoint | LocalPoint> = {
|
|||
frameNameBound?: FrameNameBounds | null;
|
||||
};
|
||||
|
||||
export const hitElementItself = <Point extends GlobalPoint | LocalPoint>({
|
||||
export const hitElementItself = <Point extends GenericPoint>({
|
||||
x,
|
||||
y,
|
||||
element,
|
||||
|
@ -127,9 +127,7 @@ export const hitElementBoundingBox = (
|
|||
);
|
||||
};
|
||||
|
||||
export const hitElementBoundingBoxOnly = <
|
||||
Point extends GlobalPoint | LocalPoint,
|
||||
>(
|
||||
export const hitElementBoundingBoxOnly = <Point extends GenericPoint>(
|
||||
hitArgs: HitTestArgs<Point>,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
|
@ -145,7 +143,7 @@ export const hitElementBoundingBoxOnly = <
|
|||
);
|
||||
};
|
||||
|
||||
export const hitElementBoundText = <Point extends GlobalPoint | LocalPoint>(
|
||||
export const hitElementBoundText = <Point extends GenericPoint>(
|
||||
x: number,
|
||||
y: number,
|
||||
textShape: GeometricShape<Point> | null,
|
||||
|
|
|
@ -12,6 +12,7 @@ import type {
|
|||
} from "@excalidraw/excalidraw/types";
|
||||
|
||||
import type Scene from "@excalidraw/excalidraw/scene/Scene";
|
||||
import type { GenericPoint } from "@excalidraw/math";
|
||||
|
||||
import type { NonDeletedExcalidrawElement } from "@excalidraw/element/types";
|
||||
|
||||
|
@ -208,10 +209,7 @@ export const dragNewElement = ({
|
|||
/** whether to keep given aspect ratio when `isResizeWithSidesSameLength` is
|
||||
true */
|
||||
widthAspectRatio?: number | null;
|
||||
originOffset?: {
|
||||
x: number;
|
||||
y: number;
|
||||
} | null;
|
||||
originOffset?: GenericPoint | null;
|
||||
informMutation?: boolean;
|
||||
}) => {
|
||||
if (shouldMaintainAspectRatio && newElement.type !== "selection") {
|
||||
|
@ -285,11 +283,12 @@ export const dragNewElement = ({
|
|||
};
|
||||
}
|
||||
|
||||
const [originOffsetX, originOffsetY] = originOffset ?? [0, 0];
|
||||
mutateElement(
|
||||
newElement,
|
||||
{
|
||||
x: newX + (originOffset?.x ?? 0),
|
||||
y: newY + (originOffset?.y ?? 0),
|
||||
x: newX + originOffsetX,
|
||||
y: newY + originOffsetY,
|
||||
width,
|
||||
height,
|
||||
...textAutoResize,
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
vectorCross,
|
||||
vectorFromPoint,
|
||||
vectorScale,
|
||||
type GenericPoint,
|
||||
type GlobalPoint,
|
||||
type LocalPoint,
|
||||
} from "@excalidraw/math";
|
||||
|
@ -1642,7 +1643,7 @@ const pathTo = (start: Node, node: Node) => {
|
|||
return path;
|
||||
};
|
||||
|
||||
const m_dist = (a: GlobalPoint | LocalPoint, b: GlobalPoint | LocalPoint) =>
|
||||
const m_dist = (a: GenericPoint, b: GenericPoint) =>
|
||||
Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
|
||||
|
||||
/**
|
||||
|
@ -2291,7 +2292,7 @@ const getHoveredElement = (
|
|||
const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean =>
|
||||
a[0] === b[0] && a[1] === b[1];
|
||||
|
||||
export const validateElbowPoints = <P extends GlobalPoint | LocalPoint>(
|
||||
export const validateElbowPoints = <P extends GenericPoint>(
|
||||
points: readonly P[],
|
||||
tolerance: number = DEDUP_TRESHOLD,
|
||||
) =>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { arrayToMap } from "@excalidraw/common";
|
||||
import { isPointWithinBounds, pointFrom } from "@excalidraw/math";
|
||||
import {
|
||||
type GenericPoint,
|
||||
isPointWithinBounds,
|
||||
pointFrom,
|
||||
} from "@excalidraw/math";
|
||||
import { doLineSegmentsIntersect } from "@excalidraw/utils/bbox";
|
||||
import { elementsOverlappingBBox } from "@excalidraw/utils/withinBounds";
|
||||
|
||||
|
@ -152,11 +156,8 @@ export const elementOverlapsWithFrame = (
|
|||
);
|
||||
};
|
||||
|
||||
export const isCursorInFrame = (
|
||||
cursorCoords: {
|
||||
x: number;
|
||||
y: number;
|
||||
},
|
||||
export const isCursorInFrame = <Point extends GenericPoint>(
|
||||
cursorCoords: Point,
|
||||
frame: NonDeleted<ExcalidrawFrameLikeElement>,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
|
@ -164,7 +165,7 @@ export const isCursorInFrame = (
|
|||
|
||||
return isPointWithinBounds(
|
||||
pointFrom(fx1, fy1),
|
||||
pointFrom(cursorCoords.x, cursorCoords.y),
|
||||
cursorCoords,
|
||||
pointFrom(fx2, fy2),
|
||||
);
|
||||
};
|
||||
|
|
|
@ -13,10 +13,10 @@ import {
|
|||
} from "@excalidraw/math";
|
||||
|
||||
import type {
|
||||
LocalPoint,
|
||||
GlobalPoint,
|
||||
Triangle,
|
||||
Vector,
|
||||
GenericPoint,
|
||||
} from "@excalidraw/math";
|
||||
|
||||
import { getCenterForBounds, type Bounds } from "./bounds";
|
||||
|
@ -43,12 +43,10 @@ export const vectorToHeading = (vec: Vector): Heading => {
|
|||
return HEADING_UP;
|
||||
};
|
||||
|
||||
export const headingForPoint = <P extends GlobalPoint | LocalPoint>(
|
||||
p: P,
|
||||
o: P,
|
||||
) => vectorToHeading(vectorFromPoint<P>(p, o));
|
||||
export const headingForPoint = <P extends GenericPoint>(p: P, o: P) =>
|
||||
vectorToHeading(vectorFromPoint<P>(p, o));
|
||||
|
||||
export const headingForPointIsHorizontal = <P extends GlobalPoint | LocalPoint>(
|
||||
export const headingForPointIsHorizontal = <P extends GenericPoint>(
|
||||
p: P,
|
||||
o: P,
|
||||
) => headingIsHorizontal(headingForPoint<P>(p, o));
|
||||
|
|
|
@ -3,8 +3,6 @@ import {
|
|||
pointFrom,
|
||||
pointRotateRads,
|
||||
pointsEqual,
|
||||
type GlobalPoint,
|
||||
type LocalPoint,
|
||||
pointDistance,
|
||||
vectorFromPoint,
|
||||
} from "@excalidraw/math";
|
||||
|
@ -26,7 +24,12 @@ import Scene from "@excalidraw/excalidraw/scene/Scene";
|
|||
|
||||
import type { Store } from "@excalidraw/excalidraw/store";
|
||||
|
||||
import type { Radians } from "@excalidraw/math";
|
||||
import type {
|
||||
GlobalPoint,
|
||||
LocalPoint,
|
||||
GenericPoint,
|
||||
Radians,
|
||||
} from "@excalidraw/math";
|
||||
|
||||
import type {
|
||||
AppState,
|
||||
|
@ -106,7 +109,7 @@ export class LinearElementEditor {
|
|||
/** index */
|
||||
lastClickedPoint: number;
|
||||
lastClickedIsEndPoint: boolean;
|
||||
origin: Readonly<{ x: number; y: number }> | null;
|
||||
origin: Readonly<GenericPoint> | null;
|
||||
segmentMidpoint: {
|
||||
value: GlobalPoint | null;
|
||||
index: number | null;
|
||||
|
@ -117,7 +120,7 @@ export class LinearElementEditor {
|
|||
/** whether you're dragging a point */
|
||||
public readonly isDragging: boolean;
|
||||
public readonly lastUncommittedPoint: LocalPoint | null;
|
||||
public readonly pointerOffset: Readonly<{ x: number; y: number }>;
|
||||
public readonly pointerOffset: Readonly<GenericPoint>;
|
||||
public readonly startBindingElement:
|
||||
| ExcalidrawBindableElement
|
||||
| null
|
||||
|
@ -139,7 +142,7 @@ export class LinearElementEditor {
|
|||
this.selectedPointsIndices = null;
|
||||
this.lastUncommittedPoint = null;
|
||||
this.isDragging = false;
|
||||
this.pointerOffset = { x: 0, y: 0 };
|
||||
this.pointerOffset = pointFrom(0, 0);
|
||||
this.startBindingElement = "keep";
|
||||
this.endBindingElement = "keep";
|
||||
this.pointerDownState = {
|
||||
|
@ -242,14 +245,14 @@ export class LinearElementEditor {
|
|||
/**
|
||||
* @returns whether point was dragged
|
||||
*/
|
||||
static handlePointDragging(
|
||||
static handlePointDragging<Point extends GenericPoint>(
|
||||
event: PointerEvent,
|
||||
app: AppClassProperties,
|
||||
scenePointerX: number,
|
||||
scenePointerY: number,
|
||||
maybeSuggestBinding: (
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
pointSceneCoords: { x: number; y: number }[],
|
||||
pointSceneCoords: Point[],
|
||||
) => void,
|
||||
linearElementEditor: LinearElementEditor,
|
||||
scene: Scene,
|
||||
|
@ -320,11 +323,13 @@ export class LinearElementEditor {
|
|||
},
|
||||
]);
|
||||
} else {
|
||||
const [pointerOffsetX, pointerOffsetY] =
|
||||
linearElementEditor.pointerOffset;
|
||||
const newDraggingPointPosition = LinearElementEditor.createPointAt(
|
||||
element,
|
||||
elementsMap,
|
||||
scenePointerX - linearElementEditor.pointerOffset.x,
|
||||
scenePointerY - linearElementEditor.pointerOffset.y,
|
||||
scenePointerX - pointerOffsetX,
|
||||
scenePointerY - pointerOffsetY,
|
||||
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
|
||||
);
|
||||
|
||||
|
@ -339,8 +344,8 @@ export class LinearElementEditor {
|
|||
? LinearElementEditor.createPointAt(
|
||||
element,
|
||||
elementsMap,
|
||||
scenePointerX - linearElementEditor.pointerOffset.x,
|
||||
scenePointerY - linearElementEditor.pointerOffset.y,
|
||||
scenePointerX - pointerOffsetX,
|
||||
scenePointerY - pointerOffsetY,
|
||||
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
|
||||
)
|
||||
: pointFrom(
|
||||
|
@ -363,7 +368,7 @@ export class LinearElementEditor {
|
|||
|
||||
// suggest bindings for first and last point if selected
|
||||
if (isBindingElement(element, false)) {
|
||||
const coords: { x: number; y: number }[] = [];
|
||||
const coords: Point[] = [];
|
||||
|
||||
const firstSelectedIndex = selectedPointsIndices[0];
|
||||
if (firstSelectedIndex === 0) {
|
||||
|
@ -511,7 +516,7 @@ export class LinearElementEditor {
|
|||
? [pointerDownState.lastClickedPoint]
|
||||
: selectedPointsIndices,
|
||||
isDragging: false,
|
||||
pointerOffset: { x: 0, y: 0 },
|
||||
pointerOffset: pointFrom(0, 0),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -586,9 +591,9 @@ export class LinearElementEditor {
|
|||
editorMidPointsCache.zoom = appState.zoom.value;
|
||||
};
|
||||
|
||||
static getSegmentMidpointHitCoords = (
|
||||
static getSegmentMidpointHitCoords = <Point extends GenericPoint>(
|
||||
linearElementEditor: LinearElementEditor,
|
||||
scenePointer: { x: number; y: number },
|
||||
[scenePointerX, scenePointerY]: Point,
|
||||
appState: AppState,
|
||||
elementsMap: ElementsMap,
|
||||
): GlobalPoint | null => {
|
||||
|
@ -601,8 +606,8 @@ export class LinearElementEditor {
|
|||
element,
|
||||
elementsMap,
|
||||
appState.zoom,
|
||||
scenePointer.x,
|
||||
scenePointer.y,
|
||||
scenePointerX,
|
||||
scenePointerY,
|
||||
);
|
||||
if (!isElbowArrow(element) && clickedPointIndex >= 0) {
|
||||
return null;
|
||||
|
@ -630,7 +635,7 @@ export class LinearElementEditor {
|
|||
existingSegmentMidpointHitCoords[0],
|
||||
existingSegmentMidpointHitCoords[1],
|
||||
),
|
||||
pointFrom(scenePointer.x, scenePointer.y),
|
||||
pointFrom(scenePointerX, scenePointerY),
|
||||
);
|
||||
if (distance <= threshold) {
|
||||
return existingSegmentMidpointHitCoords;
|
||||
|
@ -644,7 +649,7 @@ export class LinearElementEditor {
|
|||
if (midPoints[index] !== null) {
|
||||
const distance = pointDistance(
|
||||
midPoints[index]!,
|
||||
pointFrom(scenePointer.x, scenePointer.y),
|
||||
pointFrom(scenePointerX, scenePointerY),
|
||||
);
|
||||
if (distance <= threshold) {
|
||||
return midPoints[index];
|
||||
|
@ -656,7 +661,7 @@ export class LinearElementEditor {
|
|||
return null;
|
||||
};
|
||||
|
||||
static isSegmentTooShort<P extends GlobalPoint | LocalPoint>(
|
||||
static isSegmentTooShort<P extends GenericPoint>(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
startPoint: P,
|
||||
endPoint: P,
|
||||
|
@ -747,11 +752,11 @@ export class LinearElementEditor {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static handlePointerDown(
|
||||
static handlePointerDown<Point extends GenericPoint>(
|
||||
event: React.PointerEvent<HTMLElement>,
|
||||
app: AppClassProperties,
|
||||
store: Store,
|
||||
scenePointer: { x: number; y: number },
|
||||
scenePointer: Point,
|
||||
linearElementEditor: LinearElementEditor,
|
||||
scene: Scene,
|
||||
): {
|
||||
|
@ -762,6 +767,7 @@ export class LinearElementEditor {
|
|||
const appState = app.state;
|
||||
const elementsMap = scene.getNonDeletedElementsMap();
|
||||
const elements = scene.getNonDeletedElements();
|
||||
const [scenePointerX, scenePointerY] = scenePointer;
|
||||
|
||||
const ret: ReturnType<typeof LinearElementEditor["handlePointerDown"]> = {
|
||||
didAddPoint: false,
|
||||
|
@ -801,8 +807,8 @@ export class LinearElementEditor {
|
|||
LinearElementEditor.createPointAt(
|
||||
element,
|
||||
elementsMap,
|
||||
scenePointer.x,
|
||||
scenePointer.y,
|
||||
scenePointerX,
|
||||
scenePointerY,
|
||||
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
|
||||
),
|
||||
],
|
||||
|
@ -816,7 +822,7 @@ export class LinearElementEditor {
|
|||
prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices,
|
||||
lastClickedPoint: -1,
|
||||
lastClickedIsEndPoint: false,
|
||||
origin: { x: scenePointer.x, y: scenePointer.y },
|
||||
origin: pointFrom(scenePointerX, scenePointerY),
|
||||
segmentMidpoint: {
|
||||
value: segmentMidpoint,
|
||||
index: segmentMidpointIndex,
|
||||
|
@ -842,8 +848,8 @@ export class LinearElementEditor {
|
|||
element,
|
||||
elementsMap,
|
||||
appState.zoom,
|
||||
scenePointer.x,
|
||||
scenePointer.y,
|
||||
scenePointerX,
|
||||
scenePointerY,
|
||||
);
|
||||
// if we clicked on a point, set the element as hitElement otherwise
|
||||
// it would get deselected if the point is outside the hitbox area
|
||||
|
@ -897,7 +903,7 @@ export class LinearElementEditor {
|
|||
prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices,
|
||||
lastClickedPoint: clickedPointIndex,
|
||||
lastClickedIsEndPoint: clickedPointIndex === element.points.length - 1,
|
||||
origin: { x: scenePointer.x, y: scenePointer.y },
|
||||
origin: pointFrom(scenePointerX, scenePointerY),
|
||||
segmentMidpoint: {
|
||||
value: segmentMidpoint,
|
||||
index: segmentMidpointIndex,
|
||||
|
@ -906,17 +912,17 @@ export class LinearElementEditor {
|
|||
},
|
||||
selectedPointsIndices: nextSelectedPointsIndices,
|
||||
pointerOffset: targetPoint
|
||||
? {
|
||||
x: scenePointer.x - targetPoint[0],
|
||||
y: scenePointer.y - targetPoint[1],
|
||||
}
|
||||
: { x: 0, y: 0 },
|
||||
? pointFrom(
|
||||
scenePointerX - targetPoint[0],
|
||||
scenePointerY - targetPoint[1],
|
||||
)
|
||||
: pointFrom(0, 0),
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static arePointsEqual<Point extends LocalPoint | GlobalPoint>(
|
||||
static arePointsEqual<Point extends GenericPoint>(
|
||||
point1: Point | null,
|
||||
point2: Point | null,
|
||||
) {
|
||||
|
@ -977,11 +983,13 @@ export class LinearElementEditor {
|
|||
height + lastCommittedPoint[1],
|
||||
);
|
||||
} else {
|
||||
const [pointerOffsetX, pointerOffsetY] =
|
||||
appState.editingLinearElement.pointerOffset;
|
||||
newPoint = LinearElementEditor.createPointAt(
|
||||
element,
|
||||
elementsMap,
|
||||
scenePointerX - appState.editingLinearElement.pointerOffset.x,
|
||||
scenePointerY - appState.editingLinearElement.pointerOffset.y,
|
||||
scenePointerX - pointerOffsetX,
|
||||
scenePointerY - pointerOffsetY,
|
||||
event[KEYS.CTRL_OR_CMD] || isElbowArrow(element)
|
||||
? null
|
||||
: app.getEffectiveGridSize(),
|
||||
|
@ -1376,10 +1384,7 @@ export class LinearElementEditor {
|
|||
}
|
||||
|
||||
const origin = linearElementEditor.pointerDownState.origin!;
|
||||
const dist = pointDistance(
|
||||
pointFrom(origin.x, origin.y),
|
||||
pointFrom(pointerCoords.x, pointerCoords.y),
|
||||
);
|
||||
const dist = pointDistance(origin, pointerCoords);
|
||||
if (
|
||||
!appState.editingLinearElement &&
|
||||
dist < DRAGGING_THRESHOLD / appState.zoom.value
|
||||
|
@ -1412,11 +1417,12 @@ export class LinearElementEditor {
|
|||
selectedPointsIndices: linearElementEditor.selectedPointsIndices,
|
||||
};
|
||||
|
||||
const [pointerX, pointerY] = pointerCoords;
|
||||
const midpoint = LinearElementEditor.createPointAt(
|
||||
element,
|
||||
elementsMap,
|
||||
pointerCoords.x,
|
||||
pointerCoords.y,
|
||||
pointerX,
|
||||
pointerY,
|
||||
snapToGrid && !isElbowArrow(element) ? app.getEffectiveGridSize() : null,
|
||||
);
|
||||
const points = [
|
||||
|
@ -1528,31 +1534,28 @@ export class LinearElementEditor {
|
|||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
elementsMap: ElementsMap,
|
||||
referencePoint: LocalPoint,
|
||||
scenePointer: GlobalPoint,
|
||||
[scenePointerX, scenePointerY]: GlobalPoint,
|
||||
gridSize: NullableGridSize,
|
||||
) {
|
||||
const referencePointCoords = LinearElementEditor.getPointGlobalCoordinates(
|
||||
element,
|
||||
referencePoint,
|
||||
elementsMap,
|
||||
);
|
||||
const [referencePointCoordsX, referencePointCoordsY] =
|
||||
LinearElementEditor.getPointGlobalCoordinates(
|
||||
element,
|
||||
referencePoint,
|
||||
elementsMap,
|
||||
);
|
||||
|
||||
if (isElbowArrow(element)) {
|
||||
return [
|
||||
scenePointer[0] - referencePointCoords[0],
|
||||
scenePointer[1] - referencePointCoords[1],
|
||||
scenePointerX - referencePointCoordsX,
|
||||
scenePointerY - referencePointCoordsY,
|
||||
];
|
||||
}
|
||||
|
||||
const [gridX, gridY] = getGridPoint(
|
||||
scenePointer[0],
|
||||
scenePointer[1],
|
||||
gridSize,
|
||||
);
|
||||
const [gridX, gridY] = getGridPoint(scenePointerX, scenePointerY, gridSize);
|
||||
|
||||
const { width, height } = getLockedLinearCursorAlignSize(
|
||||
referencePointCoords[0],
|
||||
referencePointCoords[1],
|
||||
referencePointCoordsX,
|
||||
referencePointCoordsY,
|
||||
gridX,
|
||||
gridY,
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
|
||||
import { SIDE_RESIZING_THRESHOLD } from "@excalidraw/common";
|
||||
|
||||
import type { GlobalPoint, LineSegment, LocalPoint } from "@excalidraw/math";
|
||||
import type { GenericPoint, LineSegment } from "@excalidraw/math";
|
||||
|
||||
import type { AppState, Device, Zoom } from "@excalidraw/excalidraw/types";
|
||||
|
||||
|
@ -43,7 +43,7 @@ const isInsideTransformHandle = (
|
|||
y >= transformHandle[1] &&
|
||||
y <= transformHandle[1] + transformHandle[3];
|
||||
|
||||
export const resizeTest = <Point extends GlobalPoint | LocalPoint>(
|
||||
export const resizeTest = <Point extends GenericPoint>(
|
||||
element: NonDeletedExcalidrawElement,
|
||||
elementsMap: ElementsMap,
|
||||
appState: AppState,
|
||||
|
@ -152,9 +152,7 @@ export const getElementWithTransformHandleType = (
|
|||
}, null as { element: NonDeletedExcalidrawElement; transformHandleType: MaybeTransformHandleType } | null);
|
||||
};
|
||||
|
||||
export const getTransformHandleTypeFromCoords = <
|
||||
Point extends GlobalPoint | LocalPoint,
|
||||
>(
|
||||
export const getTransformHandleTypeFromCoords = <Point extends GenericPoint>(
|
||||
[x1, y1, x2, y2]: Bounds,
|
||||
scenePointerX: number,
|
||||
scenePointerY: number,
|
||||
|
@ -271,7 +269,7 @@ export const getCursorForResizingElement = (resizingElement: {
|
|||
return cursor ? `${cursor}-resize` : "";
|
||||
};
|
||||
|
||||
const getSelectionBorders = <Point extends LocalPoint | GlobalPoint>(
|
||||
const getSelectionBorders = <Point extends GenericPoint>(
|
||||
[x1, y1]: Point,
|
||||
[x2, y2]: Point,
|
||||
center: Point,
|
||||
|
|
|
@ -13,8 +13,7 @@ import {
|
|||
pointFromPair,
|
||||
pointRotateRads,
|
||||
pointsEqual,
|
||||
type GlobalPoint,
|
||||
type LocalPoint,
|
||||
type GenericPoint,
|
||||
} from "@excalidraw/math";
|
||||
import {
|
||||
getClosedCurveShape,
|
||||
|
@ -46,7 +45,7 @@ import type {
|
|||
* get the pure geometric shape of an excalidraw elementw
|
||||
* which is then used for hit detection
|
||||
*/
|
||||
export const getElementShape = <Point extends GlobalPoint | LocalPoint>(
|
||||
export const getElementShape = <Point extends GenericPoint>(
|
||||
element: ExcalidrawElement,
|
||||
elementsMap: ElementsMap,
|
||||
): GeometricShape<Point> => {
|
||||
|
@ -98,7 +97,7 @@ export const getElementShape = <Point extends GlobalPoint | LocalPoint>(
|
|||
}
|
||||
};
|
||||
|
||||
export const getBoundTextShape = <Point extends GlobalPoint | LocalPoint>(
|
||||
export const getBoundTextShape = <Point extends GenericPoint>(
|
||||
element: ExcalidrawElement,
|
||||
elementsMap: ElementsMap,
|
||||
): GeometricShape<Point> | null => {
|
||||
|
@ -126,9 +125,7 @@ export const getBoundTextShape = <Point extends GlobalPoint | LocalPoint>(
|
|||
return null;
|
||||
};
|
||||
|
||||
export const getControlPointsForBezierCurve = <
|
||||
P extends GlobalPoint | LocalPoint,
|
||||
>(
|
||||
export const getControlPointsForBezierCurve = <P extends GenericPoint>(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
endPoint: P,
|
||||
) => {
|
||||
|
@ -170,7 +167,7 @@ export const getControlPointsForBezierCurve = <
|
|||
return controlPoints;
|
||||
};
|
||||
|
||||
export const getBezierXY = <P extends GlobalPoint | LocalPoint>(
|
||||
export const getBezierXY = <P extends GenericPoint>(
|
||||
p0: P,
|
||||
p1: P,
|
||||
p2: P,
|
||||
|
@ -187,7 +184,7 @@ export const getBezierXY = <P extends GlobalPoint | LocalPoint>(
|
|||
return pointFrom(tx, ty);
|
||||
};
|
||||
|
||||
const getPointsInBezierCurve = <P extends GlobalPoint | LocalPoint>(
|
||||
const getPointsInBezierCurve = <P extends GenericPoint>(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
endPoint: P,
|
||||
) => {
|
||||
|
@ -217,7 +214,7 @@ const getPointsInBezierCurve = <P extends GlobalPoint | LocalPoint>(
|
|||
return pointsOnCurve;
|
||||
};
|
||||
|
||||
const getBezierCurveArcLengths = <P extends GlobalPoint | LocalPoint>(
|
||||
const getBezierCurveArcLengths = <P extends GenericPoint>(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
endPoint: P,
|
||||
) => {
|
||||
|
@ -236,7 +233,7 @@ const getBezierCurveArcLengths = <P extends GlobalPoint | LocalPoint>(
|
|||
return arcLengths;
|
||||
};
|
||||
|
||||
export const getBezierCurveLength = <P extends GlobalPoint | LocalPoint>(
|
||||
export const getBezierCurveLength = <P extends GenericPoint>(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
endPoint: P,
|
||||
) => {
|
||||
|
@ -245,7 +242,7 @@ export const getBezierCurveLength = <P extends GlobalPoint | LocalPoint>(
|
|||
};
|
||||
|
||||
// This maps interval to actual interval t on the curve so that when t = 0.5, its actually the point at 50% of the length
|
||||
export const mapIntervalToBezierT = <P extends GlobalPoint | LocalPoint>(
|
||||
export const mapIntervalToBezierT = <P extends GenericPoint>(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
endPoint: P,
|
||||
interval: number, // The interval between 0 to 1 for which you want to find the point on the curve,
|
||||
|
@ -340,7 +337,7 @@ export const aabbForElement = (
|
|||
return bounds;
|
||||
};
|
||||
|
||||
export const pointInsideBounds = <P extends GlobalPoint | LocalPoint>(
|
||||
export const pointInsideBounds = <P extends GenericPoint>(
|
||||
p: P,
|
||||
bounds: Bounds,
|
||||
): boolean =>
|
||||
|
|
|
@ -37,26 +37,28 @@ export const isElementInViewport = (
|
|||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
const [x1, y1, x2, y2] = getElementBounds(element, elementsMap); // scene coordinates
|
||||
const topLeftSceneCoords = viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft,
|
||||
clientY: viewTransformations.offsetTop,
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
const bottomRightSceneCoords = viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft + width,
|
||||
clientY: viewTransformations.offsetTop + height,
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
const [topLeftSceneCoordsX, topLeftSceneCoordsY] =
|
||||
viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft,
|
||||
clientY: viewTransformations.offsetTop,
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
const [bottomRightSceneCoordsX, bottomRightSceneCoordsY] =
|
||||
viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft + width,
|
||||
clientY: viewTransformations.offsetTop + height,
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
|
||||
return (
|
||||
topLeftSceneCoords.x <= x2 &&
|
||||
topLeftSceneCoords.y <= y2 &&
|
||||
bottomRightSceneCoords.x >= x1 &&
|
||||
bottomRightSceneCoords.y >= y1
|
||||
topLeftSceneCoordsX <= x2 &&
|
||||
topLeftSceneCoordsY <= y2 &&
|
||||
bottomRightSceneCoordsX >= x1 &&
|
||||
bottomRightSceneCoordsY >= y1
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -75,26 +77,29 @@ export const isElementCompletelyInViewport = (
|
|||
padding?: Offsets,
|
||||
) => {
|
||||
const [x1, y1, x2, y2] = getCommonBounds(elements, elementsMap); // scene coordinates
|
||||
const topLeftSceneCoords = viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft + (padding?.left || 0),
|
||||
clientY: viewTransformations.offsetTop + (padding?.top || 0),
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
const bottomRightSceneCoords = viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft + width - (padding?.right || 0),
|
||||
clientY: viewTransformations.offsetTop + height - (padding?.bottom || 0),
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
const [topLeftSceneCoordsX, topLeftSceneCoordsY] =
|
||||
viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft + (padding?.left || 0),
|
||||
clientY: viewTransformations.offsetTop + (padding?.top || 0),
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
const [bottomRightSceneCoordsX, bottomRightSceneCoordsY] =
|
||||
viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft + width - (padding?.right || 0),
|
||||
clientY:
|
||||
viewTransformations.offsetTop + height - (padding?.bottom || 0),
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
|
||||
return (
|
||||
x1 >= topLeftSceneCoords.x &&
|
||||
y1 >= topLeftSceneCoords.y &&
|
||||
x2 <= bottomRightSceneCoords.x &&
|
||||
y2 <= bottomRightSceneCoords.y
|
||||
x1 >= topLeftSceneCoordsX &&
|
||||
y1 >= topLeftSceneCoordsY &&
|
||||
x2 <= bottomRightSceneCoordsX &&
|
||||
y2 <= bottomRightSceneCoordsY
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue