simplify distance helper and factor out common bounds helper (#581)
* simplify distance helper * factor out common bounds helper
This commit is contained in:
parent
5853fba821
commit
7b842fc330
@ -57,3 +57,20 @@ export function getLinePoints(element: ExcalidrawElement) {
|
|||||||
|
|
||||||
return [x1, y1, x2, y2];
|
return [x1, y1, x2, y2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCommonBounds(elements: readonly ExcalidrawElement[]) {
|
||||||
|
let minX = Infinity;
|
||||||
|
let maxX = -Infinity;
|
||||||
|
let minY = Infinity;
|
||||||
|
let maxY = -Infinity;
|
||||||
|
|
||||||
|
elements.forEach(element => {
|
||||||
|
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||||
|
minX = Math.min(minX, x1);
|
||||||
|
minY = Math.min(minY, y1);
|
||||||
|
maxX = Math.max(maxX, x2);
|
||||||
|
maxY = Math.max(maxY, y2);
|
||||||
|
});
|
||||||
|
|
||||||
|
return [minX, minY, maxX, maxY];
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export { newElement, newTextElement, duplicateElement } from "./newElement";
|
export { newElement, newTextElement, duplicateElement } from "./newElement";
|
||||||
export {
|
export {
|
||||||
getElementAbsoluteCoords,
|
getElementAbsoluteCoords,
|
||||||
|
getCommonBounds,
|
||||||
getDiamondPoints,
|
getDiamondPoints,
|
||||||
getArrowPoints,
|
getArrowPoints,
|
||||||
getLinePoints,
|
getLinePoints,
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
isInvisiblySmallElement,
|
isInvisiblySmallElement,
|
||||||
isTextElement,
|
isTextElement,
|
||||||
textWysiwyg,
|
textWysiwyg,
|
||||||
getElementAbsoluteCoords,
|
getCommonBounds,
|
||||||
getCursorForResizingElement,
|
getCursorForResizingElement,
|
||||||
getPerfectElementSize,
|
getPerfectElementSize,
|
||||||
resizePerfectLineForNWHandler,
|
resizePerfectLineForNWHandler,
|
||||||
@ -1388,24 +1388,10 @@ export class App extends React.Component<any, AppState> {
|
|||||||
) {
|
) {
|
||||||
elements = clearSelection(elements);
|
elements = clearSelection(elements);
|
||||||
|
|
||||||
let subCanvasX1 = Infinity;
|
const [minX, minY, maxX, maxY] = getCommonBounds(parsedElements);
|
||||||
let subCanvasX2 = -Infinity;
|
|
||||||
let subCanvasY1 = Infinity;
|
|
||||||
let subCanvasY2 = -Infinity;
|
|
||||||
|
|
||||||
const minX = Math.min(...parsedElements.map(element => element.x));
|
const elementsCenterX = distance(minX, maxX) / 2;
|
||||||
const minY = Math.min(...parsedElements.map(element => element.y));
|
const elementsCenterY = distance(minY, maxY) / 2;
|
||||||
|
|
||||||
parsedElements.forEach(parsedElement => {
|
|
||||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(parsedElement);
|
|
||||||
subCanvasX1 = Math.min(subCanvasX1, x1);
|
|
||||||
subCanvasY1 = Math.min(subCanvasY1, y1);
|
|
||||||
subCanvasX2 = Math.max(subCanvasX2, x2);
|
|
||||||
subCanvasY2 = Math.max(subCanvasY2, y2);
|
|
||||||
});
|
|
||||||
|
|
||||||
const elementsCenterX = distance(subCanvasX1, subCanvasX2) / 2;
|
|
||||||
const elementsCenterY = distance(subCanvasY1, subCanvasY2) / 2;
|
|
||||||
|
|
||||||
const dx =
|
const dx =
|
||||||
cursorX -
|
cursorX -
|
||||||
|
@ -7,6 +7,7 @@ import { ExportType } from "./types";
|
|||||||
import { getExportCanvasPreview } from "./getExportCanvasPreview";
|
import { getExportCanvasPreview } from "./getExportCanvasPreview";
|
||||||
import nanoid from "nanoid";
|
import nanoid from "nanoid";
|
||||||
import { fileOpen, fileSave } from "browser-nativefs";
|
import { fileOpen, fileSave } from "browser-nativefs";
|
||||||
|
import { getCommonBounds } from "../element";
|
||||||
|
|
||||||
import i18n from "../i18n";
|
import i18n from "../i18n";
|
||||||
|
|
||||||
@ -43,35 +44,14 @@ export function serializeAsJSON(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateScroll(
|
function calculateScrollCenter(
|
||||||
elements: readonly ExcalidrawElement[],
|
elements: readonly ExcalidrawElement[],
|
||||||
): { scrollX: number; scrollY: number } {
|
): { scrollX: number; scrollY: number } {
|
||||||
// Bounding box of all elements
|
let [x1, y1, x2, y2] = getCommonBounds(elements);
|
||||||
let top = Number.MAX_SAFE_INTEGER;
|
|
||||||
let left = Number.MAX_SAFE_INTEGER;
|
const centerX = (x1 + x2) / 2;
|
||||||
let bottom = -Number.MAX_SAFE_INTEGER;
|
const centerY = (y1 + y2) / 2;
|
||||||
let right = -Number.MAX_SAFE_INTEGER;
|
|
||||||
|
|
||||||
for (const element of elements) {
|
|
||||||
left = Math.min(
|
|
||||||
left,
|
|
||||||
element.width > 0 ? element.x : element.x + element.width,
|
|
||||||
);
|
|
||||||
top = Math.min(
|
|
||||||
top,
|
|
||||||
element.height > 0 ? element.y : element.y + element.height,
|
|
||||||
);
|
|
||||||
right = Math.max(
|
|
||||||
right,
|
|
||||||
element.width > 0 ? element.x + element.width : element.x,
|
|
||||||
);
|
|
||||||
bottom = Math.max(
|
|
||||||
bottom,
|
|
||||||
element.height > 0 ? element.y + element.height : element.y,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const centerX = left + (right - left) / 2;
|
|
||||||
const centerY = top + (bottom - top) / 2;
|
|
||||||
return {
|
return {
|
||||||
scrollX: window.innerWidth / 2 - centerX,
|
scrollX: window.innerWidth / 2 - centerX,
|
||||||
scrollY: window.innerHeight / 2 - centerY,
|
scrollY: window.innerHeight / 2 - centerY,
|
||||||
@ -136,7 +116,9 @@ export async function loadFromJSON() {
|
|||||||
}
|
}
|
||||||
const { elements, appState } = updateAppState(contents);
|
const { elements, appState } = updateAppState(contents);
|
||||||
return new Promise<DataState>(resolve => {
|
return new Promise<DataState>(resolve => {
|
||||||
resolve(restore(elements, { ...appState, ...calculateScroll(elements) }));
|
resolve(
|
||||||
|
restore(elements, { ...appState, ...calculateScrollCenter(elements) }),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +169,7 @@ export async function importFromBackend(id: string | null) {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return restore(elements, { ...appState, ...calculateScroll(elements) });
|
return restore(elements, { ...appState, ...calculateScrollCenter(elements) });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function exportCanvas(
|
export async function exportCanvas(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import rough from "roughjs/bin/rough";
|
import rough from "roughjs/bin/rough";
|
||||||
import { ExcalidrawElement } from "../element/types";
|
import { ExcalidrawElement } from "../element/types";
|
||||||
import { getElementAbsoluteCoords } from "../element/bounds";
|
import { getCommonBounds } from "../element/bounds";
|
||||||
import { renderScene } from "../renderer/renderScene";
|
import { renderScene } from "../renderer/renderScene";
|
||||||
import { distance } from "../utils";
|
import { distance } from "../utils";
|
||||||
|
|
||||||
@ -28,21 +28,10 @@ export function getExportCanvasPreview(
|
|||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
// calculate smallest area to fit the contents in
|
// calculate smallest area to fit the contents in
|
||||||
let subCanvasX1 = Infinity;
|
const [minX, minY, maxX, maxY] = getCommonBounds(elements);
|
||||||
let subCanvasX2 = -Infinity;
|
const width = distance(minX, maxX) + exportPadding * 2;
|
||||||
let subCanvasY1 = Infinity;
|
const height = distance(minY, maxY) + exportPadding * 2;
|
||||||
let subCanvasY2 = -Infinity;
|
|
||||||
|
|
||||||
elements.forEach(element => {
|
|
||||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
|
||||||
subCanvasX1 = Math.min(subCanvasX1, x1);
|
|
||||||
subCanvasY1 = Math.min(subCanvasY1, y1);
|
|
||||||
subCanvasX2 = Math.max(subCanvasX2, x2);
|
|
||||||
subCanvasY2 = Math.max(subCanvasY2, y2);
|
|
||||||
});
|
|
||||||
|
|
||||||
const width = distance(subCanvasX1, subCanvasX2) + exportPadding * 2;
|
|
||||||
const height = distance(subCanvasY1, subCanvasY2) + exportPadding * 2;
|
|
||||||
const tempCanvas: any = createCanvas(width, height);
|
const tempCanvas: any = createCanvas(width, height);
|
||||||
tempCanvas.getContext("2d")?.scale(scale, scale);
|
tempCanvas.getContext("2d")?.scale(scale, scale);
|
||||||
|
|
||||||
@ -56,8 +45,8 @@ export function getExportCanvasPreview(
|
|||||||
scrollY: 0,
|
scrollY: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
offsetX: -subCanvasX1 + exportPadding,
|
offsetX: -minX + exportPadding,
|
||||||
offsetY: -subCanvasY1 + exportPadding,
|
offsetY: -minY + exportPadding,
|
||||||
renderScrollbars: false,
|
renderScrollbars: false,
|
||||||
renderSelection: false,
|
renderSelection: false,
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ExcalidrawElement } from "../element/types";
|
import { ExcalidrawElement } from "../element/types";
|
||||||
import { getElementAbsoluteCoords } from "../element";
|
import { getCommonBounds } from "../element";
|
||||||
|
|
||||||
const SCROLLBAR_MIN_SIZE = 15;
|
const SCROLLBAR_MIN_SIZE = 15;
|
||||||
const SCROLLBAR_MARGIN = 4;
|
const SCROLLBAR_MARGIN = 4;
|
||||||
@ -13,23 +13,13 @@ export function getScrollBars(
|
|||||||
scrollX: number,
|
scrollX: number,
|
||||||
scrollY: number,
|
scrollY: number,
|
||||||
) {
|
) {
|
||||||
let minX = Infinity;
|
let [minX, minY, maxX, maxY] = getCommonBounds(elements);
|
||||||
let maxX = -Infinity;
|
|
||||||
let minY = Infinity;
|
|
||||||
let maxY = -Infinity;
|
|
||||||
|
|
||||||
elements.forEach(element => {
|
|
||||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
|
||||||
minX = Math.min(minX, x1);
|
|
||||||
minY = Math.min(minY, y1);
|
|
||||||
maxX = Math.max(maxX, x2);
|
|
||||||
maxY = Math.max(maxY, y2);
|
|
||||||
});
|
|
||||||
|
|
||||||
minX += scrollX;
|
minX += scrollX;
|
||||||
maxX += scrollX;
|
maxX += scrollX;
|
||||||
minY += scrollY;
|
minY += scrollY;
|
||||||
maxY += scrollY;
|
maxY += scrollY;
|
||||||
|
|
||||||
const leftOverflow = Math.max(-minX, 0);
|
const leftOverflow = Math.max(-minX, 0);
|
||||||
const rightOverflow = Math.max(-(canvasWidth - maxX), 0);
|
const rightOverflow = Math.max(-(canvasWidth - maxX), 0);
|
||||||
const topOverflow = Math.max(-minY, 0);
|
const topOverflow = Math.max(-minY, 0);
|
||||||
|
@ -88,5 +88,5 @@ export function removeSelection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function distance(x: number, y: number) {
|
export function distance(x: number, y: number) {
|
||||||
return Math.abs(x > y ? x - y : y - x);
|
return Math.abs(x - y);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user