Compare commits

...

32 Commits

Author SHA1 Message Date
zsviczian
b82a0749b1 fixed maxZoom 2023-04-04 19:14:59 +02:00
zsviczian
a772362599 more detailed debug 2023-04-04 18:55:40 +02:00
zsviczian
3f11ca0a44 debug 2023-04-04 18:47:35 +02:00
zsviczian
808e4711f9 debug total render size 2023-04-04 18:42:34 +02:00
zsviczian
a26e8bade8
Update renderElement.ts 2023-04-04 16:50:48 +02:00
zsviczian
fc7135c5d1
Update renderElement.ts 2023-04-04 16:38:26 +02:00
zsviczian
f017a60101
Update renderElement.ts 2023-04-04 16:17:08 +02:00
zsviczian
17f9f64eda
Update renderElement.ts 2023-04-04 16:12:05 +02:00
zsviczian
619e4061f5
cappedElementCanvasSize 2023-04-04 16:01:47 +02:00
zsviczian
028ad1ee81
Update utils.ts 2023-04-04 13:26:53 +02:00
zsviczian
09a05a4a1c
Update utils.ts 2023-04-04 13:20:11 +02:00
zsviczian
c4738b31fb
Update utils.ts 2023-04-04 13:18:51 +02:00
zsviczian
87e6638e9e
Update utils.ts 2023-04-04 13:16:24 +02:00
zsviczian
0a6d41ecf9
watchdog 2023-04-04 13:15:35 +02:00
zsviczian
11109fcc62
Update renderScene.ts 2023-04-04 10:49:48 +02:00
zsviczian
c7346e3a77 always throttle render 2023-04-03 22:24:18 +02:00
zsviczian
fd030de669 debug 2023-04-03 21:45:38 +02:00
zsviczian
f77975cee5 debug 2023-04-03 21:41:48 +02:00
zsviczian
f994e5d71d debug 2023-04-03 21:36:01 +02:00
zsviczian
77028f4d08 debug 2023-04-03 21:31:35 +02:00
zsviczian
fb29bb4816 debug 2023-04-03 21:26:53 +02:00
zsviczian
23fcddb2a3 debug 2023-04-03 21:22:33 +02:00
zsviczian
b314b939b2 checkpoints 2023-04-03 21:14:31 +02:00
zsviczian
bc687fea1b log renderScene 2023-04-03 21:08:18 +02:00
zsviczian
e15f313fe7 debug 2023-04-03 20:59:37 +02:00
zsviczian
9f02922c91 attempt at catching the point before freeze 2023-04-03 20:52:21 +02:00
zsviczian
2b6819eb2d fix canvas too large 2023-04-03 20:19:13 +02:00
zsviczian
c0e9b8d7bc
Update renderElement.ts 2023-04-03 19:35:28 +02:00
zsviczian
c8c683c025
Update renderElement.ts 2023-04-03 19:28:53 +02:00
zsviczian
2117fbbc57
Update renderElement.ts 2023-04-03 19:26:25 +02:00
zsviczian
3b9953f57f
link 2023-04-03 12:15:11 +02:00
zsviczian
7d1efb7f8b
Attempt at implementing #4036 2023-04-03 12:05:19 +02:00
4 changed files with 119 additions and 30 deletions

View File

@ -1361,6 +1361,10 @@ class App extends React.Component<AppProps, AppState> {
document.querySelector(".excalidraw")!,
).getPropertyValue("--color-selection");
//const now = Date.now();
//if (!this.state.shouldCacheIgnoreZoom) {
// console.log(`renderScene`, now);
//}
renderScene(
{
elements: renderingElements,
@ -1397,11 +1401,14 @@ class App extends React.Component<AppProps, AppState> {
if (this.state.scrolledOutside !== scrolledOutside) {
this.setState({ scrolledOutside });
}
this.scheduleImageRefresh();
//if (!this.state.shouldCacheIgnoreZoom) {
// setTimeout(() => console.log(`after renderScene`, now));
//}
},
},
THROTTLE_NEXT_RENDER && window.EXCALIDRAW_THROTTLE_RENDER === true,
true ||
(THROTTLE_NEXT_RENDER && window.EXCALIDRAW_THROTTLE_RENDER === true),
);
if (!THROTTLE_NEXT_RENDER) {

View File

@ -30,7 +30,7 @@ import { RenderConfig } from "../scene/types";
import { distance, getFontString, getFontFamilyString, isRTL } from "../utils";
import { getCornerRadius, isPathALoop, isRightAngle } from "../math";
import rough from "roughjs/bin/rough";
import { AppState, BinaryFiles, Zoom } from "../types";
import { AppState, BinaryFiles, NormalizedZoomValue, Zoom } from "../types";
import { getDefaultAppState } from "../appState";
import {
BOUND_TEXT_PADDING,
@ -93,6 +93,50 @@ export interface ExcalidrawElementWithCanvas {
boundTextElementVersion: number | null;
}
export const cappedElementCanvasSize = (
element: NonDeletedExcalidrawElement,
zoom: Zoom,
): {
width: number;
height: number;
zoomValue: NormalizedZoomValue;
} => {
const sizelimit = 16777216; // 2^24
const padding = getCanvasPadding(element);
let zoomValue = zoom.value;
if (isLinearElement(element) || isFreeDrawElement(element)) {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
let width = distance(x1, x2) * window.devicePixelRatio + padding * 2;
let height = distance(y1, y2) * window.devicePixelRatio + padding * 2;
const size = width * height * zoomValue * zoomValue;
if (size > sizelimit) {
zoomValue = Math.sqrt(
sizelimit / (width * height),
) as NormalizedZoomValue;
width = distance(x1, x2) * window.devicePixelRatio + padding * 2;
height = distance(y1, y2) * window.devicePixelRatio + padding * 2;
}
width *= zoomValue;
height *= zoomValue;
return { width, height, zoomValue };
}
let width = element.width * window.devicePixelRatio + padding * 2;
let height = element.height * window.devicePixelRatio + padding * 2;
const size = width * height * zoomValue * zoomValue;
if (size > sizelimit) {
zoomValue = Math.sqrt(sizelimit / (width * height)) as NormalizedZoomValue;
width = element.width * window.devicePixelRatio + padding * 2;
height = element.height * window.devicePixelRatio + padding * 2;
}
width *= zoomValue;
height *= zoomValue;
return { width, height, zoomValue };
};
const generateElementCanvas = (
element: NonDeletedExcalidrawElement,
zoom: Zoom,
@ -102,44 +146,35 @@ const generateElementCanvas = (
const context = canvas.getContext("2d")!;
const padding = getCanvasPadding(element);
const { width, height, zoomValue } = cappedElementCanvasSize(element, zoom);
canvas.width = width;
canvas.height = height;
let canvasOffsetX = 0;
let canvasOffsetY = 0;
if (isLinearElement(element) || isFreeDrawElement(element)) {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
canvas.width =
distance(x1, x2) * window.devicePixelRatio * zoom.value +
padding * zoom.value * 2;
canvas.height =
distance(y1, y2) * window.devicePixelRatio * zoom.value +
padding * zoom.value * 2;
const [x1, y1] = getElementAbsoluteCoords(element);
canvasOffsetX =
element.x > x1
? distance(element.x, x1) * window.devicePixelRatio * zoom.value
? distance(element.x, x1) * window.devicePixelRatio * zoomValue
: 0;
canvasOffsetY =
element.y > y1
? distance(element.y, y1) * window.devicePixelRatio * zoom.value
? distance(element.y, y1) * window.devicePixelRatio * zoomValue
: 0;
context.translate(canvasOffsetX, canvasOffsetY);
} else {
canvas.width =
element.width * window.devicePixelRatio * zoom.value +
padding * zoom.value * 2;
canvas.height =
element.height * window.devicePixelRatio * zoom.value +
padding * zoom.value * 2;
}
context.save();
context.translate(padding * zoom.value, padding * zoom.value);
context.translate(padding * zoomValue, padding * zoomValue);
context.scale(
window.devicePixelRatio * zoom.value,
window.devicePixelRatio * zoom.value,
window.devicePixelRatio * zoomValue,
window.devicePixelRatio * zoomValue,
);
const rc = rough.canvas(canvas);
@ -156,7 +191,7 @@ const generateElementCanvas = (
element,
canvas,
theme: renderConfig.theme,
canvasZoom: zoom.value,
canvasZoom: zoomValue,
canvasOffsetX,
canvasOffsetY,
boundTextElementVersion: getBoundTextElement(element)?.version || null,
@ -422,6 +457,11 @@ const generateElementShape = (
// `null` indicates no rc shape applicable for this element type
// (= do not generate anything)
if (shape === undefined) {
const prevElementWithCanvas = elementWithCanvasCache.get(element);
if (prevElementWithCanvas?.canvas) {
prevElementWithCanvas.canvas.width = 0;
prevElementWithCanvas.canvas.height = 0;
}
elementWithCanvasCache.delete(element);
switch (element.type) {
@ -685,7 +725,10 @@ const generateElementWithCanvas = (
zoom,
renderConfig,
);
if (prevElementWithCanvas?.canvas) {
prevElementWithCanvas.canvas.width = 0;
prevElementWithCanvas.canvas.height = 0;
}
elementWithCanvasCache.set(element, elementWithCanvas);
return elementWithCanvas;

View File

@ -29,7 +29,11 @@ import {
} from "../scene/scrollbars";
import { getSelectedElements } from "../scene/selection";
import { renderElement, renderElementToSvg } from "./renderElement";
import {
cappedElementCanvasSize,
renderElement,
renderElementToSvg,
} from "./renderElement";
import { getClientColors } from "../clients";
import { LinearElementEditor } from "../element/linearElementEditor";
import {
@ -407,6 +411,21 @@ export const _renderScene = ({
let editingLinearElement: NonDeleted<ExcalidrawLinearElement> | undefined =
undefined;
const start = Date.now();
const showDebug = false; //!appState.shouldCacheIgnoreZoom && (appState.zoom.value < 0.5);
if (showDebug) {
console.log("start: renderElements");
}
console.log(
visibleElements.length,
appState.zoom.value,
Math.round(
visibleElements.reduce((acc, el) => {
const { width, height } = cappedElementCanvasSize(el, appState.zoom);
return acc + width * height;
}, 0),
),
);
visibleElements.forEach((element) => {
try {
renderElement(element, rc, context, renderConfig, appState);
@ -426,7 +445,9 @@ export const _renderScene = ({
console.error(error);
}
});
if (showDebug) {
console.log(`finish: renderElements ${Date.now() - start}`);
}
if (editingLinearElement) {
renderLinearPointHandles(
context,
@ -636,10 +657,8 @@ export const _renderScene = ({
}
context.restore();
}
// Reset zoom
context.restore();
// Paint remote pointers
for (const clientId in renderConfig.remotePointerViewportCoords) {
let { x, y } = renderConfig.remotePointerViewportCoords[clientId];
@ -787,7 +806,6 @@ export const _renderScene = ({
});
context.restore();
}
context.restore();
return { atLeastOneVisibleElement: visibleElements.length > 0, scrollBars };
};

View File

@ -135,17 +135,24 @@ export const throttleRAF = <T extends any[]>(
let timerId: number | null = null;
let lastArgs: T | null = null;
let lastArgsTrailing: T | null = null;
let watchdog: number | null = null;
const scheduleFunc = (args: T) => {
timerId = window.requestAnimationFrame(() => {
timerId = null;
//console.log("start render in animation frame");
fn(...args);
//console.log("render done in animation frame");
lastArgs = null;
if (lastArgsTrailing) {
//console.log("last args trailing", lastArgsTrailing);
lastArgs = lastArgsTrailing;
lastArgsTrailing = null;
scheduleFunc(lastArgs);
}
if (watchdog) {
clearTimeout(watchdog);
}
});
};
@ -165,6 +172,9 @@ export const throttleRAF = <T extends any[]>(
if (timerId !== null) {
cancelAnimationFrame(timerId);
timerId = null;
if (watchdog) {
clearTimeout(watchdog);
}
}
if (lastArgs) {
fn(...(lastArgsTrailing || lastArgs));
@ -176,8 +186,19 @@ export const throttleRAF = <T extends any[]>(
if (timerId !== null) {
cancelAnimationFrame(timerId);
timerId = null;
if (watchdog) {
clearTimeout(watchdog);
watchdog = null;
}
}
};
watchdog = window.setTimeout(() => {
console.log("watchdog", timerId);
if (timerId !== null) {
cancelAnimationFrame(timerId);
timerId = null;
}
}, 1000);
return ret;
};