Fast & Furious (#655)

* [WIP] Fast & Furious

* ensure we translate before scaling

* implement canvas caching for rest of elements

* remove unnecessary ts-ignore

* fix for devicePixelRatio

* initialize missing element props on restore

* factor out canvas padding

* remove unnecessary filtering

* simplify renderElement

* regenerate canvas on prop changes

* revert swapping shape resetting with canvas

* fix blurry rendering

* apply devicePixelRatio when clearing canvas

* improve blurriness; fix arrow canvas offset

* revert canvas clearing changes in anticipation of merge

* normalize scrollX/Y on update

* fix getDerivedStateFromProps

* swap derivedState for type brands

* tweak types

* remove renderScene offsets

* move selection element translations to renderElement

* dry out canvas zoom transformations

* fix padding offset

* Render cached canvas based on the zoom level

Co-authored-by: David Luzar <luzar.david@gmail.com>
Co-authored-by: Preet <833927+pshihn@users.noreply.github.com>
This commit is contained in:
Christopher Chedeau 2020-02-19 08:25:01 -08:00 committed by GitHub
parent d39c7d4421
commit 5256096d76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 269 additions and 114 deletions

View file

@ -6,7 +6,7 @@ import {
clearAppStateForLocalStorage,
} from "../appState";
import { AppState } from "../types";
import { AppState, FlooredNumber } from "../types";
import { ExportType } from "./types";
import { exportToCanvas, exportToSvg } from "./export";
import nanoid from "nanoid";
@ -59,17 +59,21 @@ export function serializeAsJSON(
);
}
export function normalizeScroll(pos: number) {
return Math.floor(pos) as FlooredNumber;
}
export function calculateScrollCenter(
elements: readonly ExcalidrawElement[],
): { scrollX: number; scrollY: number } {
): { scrollX: FlooredNumber; scrollY: FlooredNumber } {
const [x1, y1, x2, y2] = getCommonBounds(elements);
const centerX = (x1 + x2) / 2;
const centerY = (y1 + y2) / 2;
return {
scrollX: window.innerWidth / 2 - centerX,
scrollY: window.innerHeight / 2 - centerY,
scrollX: normalizeScroll(window.innerWidth / 2 - centerX),
scrollY: normalizeScroll(window.innerHeight / 2 - centerY),
};
}
@ -383,6 +387,10 @@ function restore(
? 100
: element.opacity,
points,
shape: null,
canvas: null,
canvasOffsetX: element.canvasOffsetX || 0,
canvasOffsetY: element.canvasOffsetY || 0,
};
});
@ -430,7 +438,9 @@ export function saveToLocalStorage(
localStorage.setItem(
LOCAL_STORAGE_KEY,
JSON.stringify(
elements.map(({ shape, ...element }: ExcalidrawElement) => element),
elements.map(
({ shape, canvas, ...element }: ExcalidrawElement) => element,
),
),
);
localStorage.setItem(

View file

@ -3,6 +3,7 @@ import { ExcalidrawElement } from "../element/types";
import { getCommonBounds } from "../element/bounds";
import { renderScene, renderSceneToSvg } from "../renderer/renderScene";
import { distance, SVG_NS } from "../utils";
import { normalizeScroll } from "./data";
export function exportToCanvas(
elements: readonly ExcalidrawElement[],
@ -42,15 +43,14 @@ export function exportToCanvas(
tempCanvas,
{
viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
scrollX: 0,
scrollY: 0,
scrollX: normalizeScroll(-minX + exportPadding),
scrollY: normalizeScroll(-minY + exportPadding),
zoom: 1,
},
{
offsetX: -minX + exportPadding,
offsetY: -minY + exportPadding,
renderScrollbars: false,
renderSelection: false,
renderOptimizations: false,
},
);
return tempCanvas;

View file

@ -1,5 +1,6 @@
import { ExcalidrawElement } from "../element/types";
import { getCommonBounds } from "../element";
import { FlooredNumber } from "../types";
const SCROLLBAR_MARGIN = 4;
export const SCROLLBAR_WIDTH = 6;
@ -14,8 +15,8 @@ export function getScrollBars(
scrollY,
zoom,
}: {
scrollX: number;
scrollY: number;
scrollX: FlooredNumber;
scrollY: FlooredNumber;
zoom: number;
},
) {
@ -93,8 +94,8 @@ export function isOverScrollBars(
scrollY,
zoom,
}: {
scrollX: number;
scrollY: number;
scrollX: FlooredNumber;
scrollY: FlooredNumber;
zoom: number;
},
) {

View file

@ -1,16 +1,17 @@
import { ExcalidrawTextElement } from "../element/types";
import { FlooredNumber } from "../types";
export type SceneState = {
scrollX: number;
scrollY: number;
scrollX: FlooredNumber;
scrollY: FlooredNumber;
// null indicates transparent bg
viewBackgroundColor: string | null;
zoom: number;
};
export type SceneScroll = {
scrollX: number;
scrollY: number;
scrollX: FlooredNumber;
scrollY: FlooredNumber;
};
export interface Scene {