diff --git a/src/components/LessonRunner.tsx b/src/components/LessonRunner.tsx index fb3fa5f..6579ba4 100644 --- a/src/components/LessonRunner.tsx +++ b/src/components/LessonRunner.tsx @@ -159,7 +159,7 @@ export default function LessonRunner({ if (!loggedIn) return; const c = canvasRef.current; if (!c || !hasContent()) return; - saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c)); + saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c, 800, false)); } function scheduleSave() { if (!loggedIn) return; @@ -198,7 +198,7 @@ export default function LessonRunner({ redraw(); force((n) => n + 1); const c = canvasRef.current; - if (loggedIn && c) saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c)); + if (loggedIn && c) saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c, 800, false)); } function undo() { strokesRef.current.pop(); diff --git a/src/components/ShadingRunner.tsx b/src/components/ShadingRunner.tsx index d01cf8b..3df5f2c 100644 --- a/src/components/ShadingRunner.tsx +++ b/src/components/ShadingRunner.tsx @@ -125,7 +125,7 @@ export default function ShadingRunner({ if (!loggedIn) return; const c = canvasRef.current; if (!c || !hasContent()) return; - saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c)); + saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c, 800, false)); } function scheduleSave() { if (!loggedIn) return; @@ -158,7 +158,7 @@ export default function ShadingRunner({ redraw(); force((n) => n + 1); const c = canvasRef.current; - if (loggedIn && c) saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c)); + if (loggedIn && c) saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c, 800, false)); } function undo() { strokesRef.current.pop(); redraw(); force((n) => n + 1); scheduleSave(); } diff --git a/src/components/TraceRunner.tsx b/src/components/TraceRunner.tsx index e150838..fc81505 100644 --- a/src/components/TraceRunner.tsx +++ b/src/components/TraceRunner.tsx @@ -86,14 +86,14 @@ export default function TraceRunner({ meta, steps, loggedIn, username, completed useEffect(() => { setPlaying(true); setPlayKey((k) => k + 1); }, [idx]); function hasContent() { return strokesRef.current.length > 0 || !!baseImgRef.current; } - function flushSave() { if (!loggedIn) return; const c = canvasRef.current; if (!c || !hasContent()) return; saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c)); } + function flushSave() { if (!loggedIn) return; const c = canvasRef.current; if (!c || !hasContent()) return; saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c, 800, false)); } function scheduleSave() { if (!loggedIn) return; clearTimeout(saveTimer.current); saveTimer.current = setTimeout(flushSave, 1200); } function pe(e: React.PointerEvent): Point { const r = canvasRef.current!.getBoundingClientRect(); return { x: (e.clientX - r.left) / r.width, y: (e.clientY - r.top) / r.height }; } function onDown(e: React.PointerEvent) { if (finished) return; (e.target as Element).setPointerCapture?.(e.pointerId); const s: Stroke = { color, size, points: [pe(e)] }; drawingRef.current = s; strokesRef.current.push(s); } function onMove(e: React.PointerEvent) { const s = drawingRef.current; if (!s) return; s.points.push(pe(e)); redraw(); } function onUp() { drawingRef.current = null; force((n) => n + 1); scheduleSave(); } - function clearCanvas() { strokesRef.current = []; baseImgRef.current = null; redraw(); force((n) => n + 1); const c = canvasRef.current; if (loggedIn && c) saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c)); } + function clearCanvas() { strokesRef.current = []; baseImgRef.current = null; redraw(); force((n) => n + 1); const c = canvasRef.current; if (loggedIn && c) saveProgressDrawing(meta.level, meta.sublevel, exportCanvasToDataURL(c, 800, false)); } function undo() { strokesRef.current.pop(); redraw(); force((n) => n + 1); scheduleSave(); } async function saveStep(stepN: number, badgeKey?: string) { diff --git a/src/components/drawingPersistence.ts b/src/components/drawingPersistence.ts index 3d2fb4e..082399a 100644 --- a/src/components/drawingPersistence.ts +++ b/src/components/drawingPersistence.ts @@ -42,7 +42,7 @@ export async function saveFinalDrawing( } /** Composite the (transparent) canvas onto white and downscale, returning a PNG data URL. */ -export function exportCanvasToDataURL(canvas: HTMLCanvasElement, maxW = 800): string { +export function exportCanvasToDataURL(canvas: HTMLCanvasElement, maxW = 800, white = true): string { const scale = Math.min(1, maxW / canvas.width); const w = Math.round(canvas.width * scale); const h = Math.round(canvas.height * scale); @@ -50,8 +50,12 @@ export function exportCanvasToDataURL(canvas: HTMLCanvasElement, maxW = 800): st out.width = w; out.height = h; const ctx = out.getContext("2d")!; - ctx.fillStyle = "#ffffff"; - ctx.fillRect(0, 0, w, h); + // White background for saved/gallery images; transparent for in-progress canvases that are + // restored as a base layer (so the faint guide and the line-by-line video still show through). + if (white) { + ctx.fillStyle = "#ffffff"; + ctx.fillRect(0, 0, w, h); + } ctx.drawImage(canvas, 0, 0, w, h); return out.toDataURL("image/png"); }