feat: image support (#4011)

Co-authored-by: Emil Atanasov <heitara@gmail.com>
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
This commit is contained in:
David Luzar 2021-10-21 22:05:48 +02:00 committed by GitHub
parent 0f0244224d
commit 163ad1f4c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
85 changed files with 3536 additions and 618 deletions

View file

@ -47,9 +47,9 @@ export const transformElements = (
transformHandleType: MaybeTransformHandleType,
selectedElements: readonly NonDeletedExcalidrawElement[],
resizeArrowDirection: "origin" | "end",
isRotateWithDiscreteAngle: boolean,
isResizeCenterPoint: boolean,
shouldKeepSidesRatio: boolean,
shouldRotateWithDiscreteAngle: boolean,
shouldResizeFromCenter: boolean,
shouldMaintainAspectRatio: boolean,
pointerX: number,
pointerY: number,
centerX: number,
@ -62,7 +62,7 @@ export const transformElements = (
element,
pointerX,
pointerY,
isRotateWithDiscreteAngle,
shouldRotateWithDiscreteAngle,
);
updateBoundElements(element);
} else if (
@ -76,7 +76,7 @@ export const transformElements = (
reshapeSingleTwoPointElement(
element,
resizeArrowDirection,
isRotateWithDiscreteAngle,
shouldRotateWithDiscreteAngle,
pointerX,
pointerY,
);
@ -90,7 +90,7 @@ export const transformElements = (
resizeSingleTextElement(
element,
transformHandleType,
isResizeCenterPoint,
shouldResizeFromCenter,
pointerX,
pointerY,
);
@ -98,10 +98,10 @@ export const transformElements = (
} else if (transformHandleType) {
resizeSingleElement(
pointerDownState.originalElements.get(element.id) as typeof element,
shouldKeepSidesRatio,
shouldMaintainAspectRatio,
element,
transformHandleType,
isResizeCenterPoint,
shouldResizeFromCenter,
pointerX,
pointerY,
);
@ -115,7 +115,7 @@ export const transformElements = (
selectedElements,
pointerX,
pointerY,
isRotateWithDiscreteAngle,
shouldRotateWithDiscreteAngle,
centerX,
centerY,
);
@ -142,13 +142,13 @@ const rotateSingleElement = (
element: NonDeletedExcalidrawElement,
pointerX: number,
pointerY: number,
isRotateWithDiscreteAngle: boolean,
shouldRotateWithDiscreteAngle: boolean,
) => {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
const cx = (x1 + x2) / 2;
const cy = (y1 + y2) / 2;
let angle = (5 * Math.PI) / 2 + Math.atan2(pointerY - cy, pointerX - cx);
if (isRotateWithDiscreteAngle) {
if (shouldRotateWithDiscreteAngle) {
angle += SHIFT_LOCKING_ANGLE / 2;
angle -= angle % SHIFT_LOCKING_ANGLE;
}
@ -187,7 +187,7 @@ const getPerfectElementSizeWithRotation = (
export const reshapeSingleTwoPointElement = (
element: NonDeleted<ExcalidrawLinearElement>,
resizeArrowDirection: "origin" | "end",
isRotateWithDiscreteAngle: boolean,
shouldRotateWithDiscreteAngle: boolean,
pointerX: number,
pointerY: number,
) => {
@ -212,7 +212,7 @@ export const reshapeSingleTwoPointElement = (
element.x + element.points[1][0] - rotatedX,
element.y + element.points[1][1] - rotatedY,
];
if (isRotateWithDiscreteAngle) {
if (shouldRotateWithDiscreteAngle) {
[width, height] = getPerfectElementSizeWithRotation(
element.type,
width,
@ -281,28 +281,28 @@ const measureFontSizeFromWH = (
const getSidesForTransformHandle = (
transformHandleType: TransformHandleType,
isResizeFromCenter: boolean,
shouldResizeFromCenter: boolean,
) => {
return {
n:
/^(n|ne|nw)$/.test(transformHandleType) ||
(isResizeFromCenter && /^(s|se|sw)$/.test(transformHandleType)),
(shouldResizeFromCenter && /^(s|se|sw)$/.test(transformHandleType)),
s:
/^(s|se|sw)$/.test(transformHandleType) ||
(isResizeFromCenter && /^(n|ne|nw)$/.test(transformHandleType)),
(shouldResizeFromCenter && /^(n|ne|nw)$/.test(transformHandleType)),
w:
/^(w|nw|sw)$/.test(transformHandleType) ||
(isResizeFromCenter && /^(e|ne|se)$/.test(transformHandleType)),
(shouldResizeFromCenter && /^(e|ne|se)$/.test(transformHandleType)),
e:
/^(e|ne|se)$/.test(transformHandleType) ||
(isResizeFromCenter && /^(w|nw|sw)$/.test(transformHandleType)),
(shouldResizeFromCenter && /^(w|nw|sw)$/.test(transformHandleType)),
};
};
const resizeSingleTextElement = (
element: NonDeleted<ExcalidrawTextElement>,
transformHandleType: "nw" | "ne" | "sw" | "se",
isResizeFromCenter: boolean,
shouldResizeFromCenter: boolean,
pointerX: number,
pointerY: number,
) => {
@ -361,7 +361,7 @@ const resizeSingleTextElement = (
const deltaX2 = (x2 - nextX2) / 2;
const deltaY2 = (y2 - nextY2) / 2;
const [nextElementX, nextElementY] = adjustXYWithRotation(
getSidesForTransformHandle(transformHandleType, isResizeFromCenter),
getSidesForTransformHandle(transformHandleType, shouldResizeFromCenter),
element.x,
element.y,
element.angle,
@ -383,10 +383,10 @@ const resizeSingleTextElement = (
export const resizeSingleElement = (
stateAtResizeStart: NonDeletedExcalidrawElement,
shouldKeepSidesRatio: boolean,
shouldMaintainAspectRatio: boolean,
element: NonDeletedExcalidrawElement,
transformHandleDirection: TransformHandleDirection,
isResizeFromCenter: boolean,
shouldResizeFromCenter: boolean,
pointerX: number,
pointerY: number,
) => {
@ -444,13 +444,13 @@ export const resizeSingleElement = (
let eleNewHeight = element.height * scaleY;
// adjust dimensions for resizing from center
if (isResizeFromCenter) {
if (shouldResizeFromCenter) {
eleNewWidth = 2 * eleNewWidth - eleInitialWidth;
eleNewHeight = 2 * eleNewHeight - eleInitialHeight;
}
// adjust dimensions to keep sides ratio
if (shouldKeepSidesRatio) {
if (shouldMaintainAspectRatio) {
const widthRatio = Math.abs(eleNewWidth) / eleInitialWidth;
const heightRatio = Math.abs(eleNewHeight) / eleInitialHeight;
if (transformHandleDirection.length === 1) {
@ -495,7 +495,7 @@ export const resizeSingleElement = (
}
// Keeps opposite handle fixed during resize
if (shouldKeepSidesRatio) {
if (shouldMaintainAspectRatio) {
if (["s", "n"].includes(transformHandleDirection)) {
newTopLeft[0] = startCenter[0] - newBoundsWidth / 2;
}
@ -523,7 +523,7 @@ export const resizeSingleElement = (
}
}
if (isResizeFromCenter) {
if (shouldResizeFromCenter) {
newTopLeft[0] = startCenter[0] - Math.abs(newBoundsWidth) / 2;
newTopLeft[1] = startCenter[1] - Math.abs(newBoundsHeight) / 2;
}
@ -558,6 +558,18 @@ export const resizeSingleElement = (
...rescaledPoints,
};
if ("scale" in element && "scale" in stateAtResizeStart) {
mutateElement(element, {
scale: [
// defaulting because scaleX/Y can be 0/-0
(Math.sign(scaleX) || stateAtResizeStart.scale[0]) *
stateAtResizeStart.scale[0],
(Math.sign(scaleY) || stateAtResizeStart.scale[1]) *
stateAtResizeStart.scale[1],
],
});
}
if (
resizedElement.width !== 0 &&
resizedElement.height !== 0 &&
@ -692,13 +704,13 @@ const rotateMultipleElements = (
elements: readonly NonDeletedExcalidrawElement[],
pointerX: number,
pointerY: number,
isRotateWithDiscreteAngle: boolean,
shouldRotateWithDiscreteAngle: boolean,
centerX: number,
centerY: number,
) => {
let centerAngle =
(5 * Math.PI) / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);
if (isRotateWithDiscreteAngle) {
if (shouldRotateWithDiscreteAngle) {
centerAngle += SHIFT_LOCKING_ANGLE / 2;
centerAngle -= centerAngle % SHIFT_LOCKING_ANGLE;
}