Skip to content

Commit b83febd

Browse files
committed
whiteboard: use a bounded canvas for preview when drawing with pen. Saves memory and makes it possible to use ipad.
1 parent 14d6db1 commit b83febd

File tree

2 files changed

+53
-28
lines changed

2 files changed

+53
-28
lines changed

src/packages/frontend/frame-editors/whiteboard-editor/canvas.tsx

+34-10
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ import {
8888
} from "./math";
8989
import { throttle } from "lodash";
9090
import Draggable from "react-draggable";
91-
import { clearCanvas, drawCurve } from "./elements/pen";
91+
import { clearCanvas, drawCurve, getMaxCanvasSizeScale } from "./elements/pen";
9292

9393
import { getParams } from "./tools/tool-panel";
9494

@@ -98,7 +98,9 @@ import { aspectRatioToNumber } from "./tools/frame";
9898

9999
import Cursors from "./cursors";
100100

101-
const penDPIFactor = 1; // I can't get this to work! :-(
101+
// I can't get this to work! :-(
102+
// When I can, this should be window.devicePixelRatio
103+
const penDPIFactor = 1;
102104

103105
const MIDDLE_MOUSE_BUTTON = 1;
104106

@@ -145,10 +147,20 @@ export default function Canvas({
145147

146148
const navDrag = useRef<null | { x0: number; y0: number }>(null);
147149
const innerCanvasRef = useRef<any>(null);
148-
const transforms = useMemo(
149-
() => getTransforms(elements, margin, canvasScale),
150-
[elements, margin, canvasScale]
151-
);
150+
151+
const canvasScaleRef = useRef<number>(1);
152+
const transforms = useMemo(() => {
153+
const t = getTransforms(elements, margin, canvasScale);
154+
// also update the canvas scale, which is needed to keep
155+
// the canvas preview layer (for the pen) from getting too big
156+
// and wasting memory.
157+
canvasScaleRef.current = getMaxCanvasSizeScale(
158+
penDPIFactor * t.width,
159+
penDPIFactor * t.height
160+
);
161+
return t;
162+
}, [elements, margin, canvasScale]);
163+
152164
const mousePath = useRef<{ x: number; y: number }[] | null>(null);
153165
const handRef = useRef<{
154166
scrollLeft: number;
@@ -852,10 +864,22 @@ export default function Canvas({
852864
if (canvas == null) return;
853865
const ctx = canvas.getContext("2d");
854866
if (ctx == null) return;
867+
const path: Point[] = [];
868+
for (const point of mousePath.current.slice(
869+
mousePath.current.length - 3
870+
)) {
871+
path.push({
872+
x: point.x * canvasScaleRef.current,
873+
y: point.y * canvasScaleRef.current,
874+
});
875+
}
876+
const { color, radius, opacity } = getToolParams("pen");
855877
drawCurve({
856878
ctx,
857-
path: mousePath.current.slice(mousePath.current.length - 2),
858-
...getToolParams("pen"),
879+
path,
880+
color,
881+
radius: canvasScaleRef.current * radius,
882+
opacity,
859883
});
860884
return;
861885
}
@@ -978,8 +1002,8 @@ export default function Canvas({
9781002
{!isNavigator && selectedTool == "pen" && (
9791003
<canvas
9801004
ref={penCanvasRef}
981-
width={penDPIFactor * transforms.width}
982-
height={penDPIFactor * transforms.height}
1005+
width={canvasScaleRef.current * penDPIFactor * transforms.width}
1006+
height={canvasScaleRef.current * penDPIFactor * transforms.height}
9831007
style={{
9841008
width: `${transforms.width}px`,
9851009
height: `${transforms.height}px`,

src/packages/frontend/frame-editors/whiteboard-editor/elements/pen.tsx

+19-18
Original file line numberDiff line numberDiff line change
@@ -52,31 +52,20 @@ export default function Pen({ element }: Props) {
5252
ctx,
5353
path: decompressPath(path, scaleRef.current),
5454
color: color ?? "black",
55-
radius: radius ?? 1,
55+
radius: (radius ?? 1) * scaleRef.current,
5656
opacity,
57-
scale: scaleRef.current,
5857
});
5958
}, [element]);
6059

6160
const w = (element.w ?? 100) + 2 * pad;
6261
const h = (element.h ?? 100) + 2 * pad;
63-
let scale;
64-
if (w * DPIFactor <= MAX_CANVAS_SIZE && w * DPIFactor <= MAX_CANVAS_SIZE) {
65-
scale = 1;
66-
} else {
67-
if (w >= h) {
68-
scale = MAX_CANVAS_SIZE / (w * DPIFactor);
69-
} else {
70-
scale = MAX_CANVAS_SIZE / (h * DPIFactor);
71-
}
72-
}
73-
scaleRef.current = scale;
62+
scaleRef.current = getMaxCanvasSizeScale(w * DPIFactor, h * DPIFactor);
7463
return (
7564
<div>
7665
<canvas
7766
ref={canvasRef}
78-
width={scale * w * DPIFactor}
79-
height={scale * h * DPIFactor}
67+
width={scaleRef.current * w * DPIFactor}
68+
height={scaleRef.current * h * DPIFactor}
8069
style={{
8170
width: `${w}px`,
8271
height: `${h}px`,
@@ -99,14 +88,12 @@ export function drawCurve({
9988
color,
10089
radius,
10190
opacity,
102-
scale = 1,
10391
}: {
10492
ctx;
10593
path: Point[];
10694
color?: string;
10795
radius?: number;
10896
opacity?: number;
109-
scale?: number;
11097
}) {
11198
// There's some useful MIT licensed code at https://github.com/embiem/react-canvas-draw
11299
// that inspired this.
@@ -118,7 +105,7 @@ export function drawCurve({
118105
ctx.globalAlpha = opacity;
119106
}
120107

121-
ctx.lineWidth = 2 * (radius ?? 0.5) * scale;
108+
ctx.lineWidth = 2 * (radius ?? 0.5);
122109

123110
let p1 = path[0];
124111
let p2 = path[1];
@@ -138,3 +125,17 @@ export function drawCurve({
138125
ctx.lineTo(p1.x, p1.y);
139126
ctx.stroke();
140127
}
128+
129+
// Return a single scalar so that multiplying by it transforms
130+
// coordinates
131+
export function getMaxCanvasSizeScale(w: number, h: number): number {
132+
if (w <= MAX_CANVAS_SIZE && w <= MAX_CANVAS_SIZE) {
133+
return 1;
134+
} else {
135+
if (w >= h) {
136+
return MAX_CANVAS_SIZE / w;
137+
} else {
138+
return MAX_CANVAS_SIZE / h;
139+
}
140+
}
141+
}

0 commit comments

Comments
 (0)