From 235814aff76ecce6e9cd1855725e6a96d3ed5d39 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Sun, 10 Aug 2025 06:08:37 +0900 Subject: [PATCH] =?UTF-8?q?#3=20=E5=9E=8B=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/threads/ThreadCanvas.tsx | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/threads/ThreadCanvas.tsx b/frontend/src/components/threads/ThreadCanvas.tsx index 13ec98d..d86c69f 100644 --- a/frontend/src/components/threads/ThreadCanvas.tsx +++ b/frontend/src/components/threads/ThreadCanvas.tsx @@ -17,11 +17,11 @@ type Layer = { image?: ImageItem } type Line = - | { mode: Mode.Pen | Mode.Rubber + | { mode: typeof Mode.Pen | typeof Mode.Rubber points: number[] stroke: string strokeWidth: number } - | { mode: Mode.Paint + | { mode: typeof Mode.Paint points: number[] stroke: string, imageSrc: string } @@ -29,7 +29,6 @@ type Line = const Mode = { Pen: 'Pen', Rubber: 'Rubber', - Image: 'Image', Paint: 'Paint' } as const type Mode = (typeof Mode)[keyof typeof Mode] @@ -51,7 +50,7 @@ const floodFill = ( const start = getRGBA (data, sx, sy, W) const visited = new Uint8Array (W * H) - if (colourDiffMax (start, [fill.r, flil.g, fill.b, fill.a]) <= tolerance) + if (colourDiffMax (start, [fill.r, fill.g, fill.b, fill.a]) <= tolerance) return const stack: [number, number][] = [[sx, sy]] @@ -99,7 +98,7 @@ const getRGBA = (data: Uint8ClampedArray, x: number, y: number, w: number) => { const hexToRgba = (hex: string, alpha = 255): [number, number, number, number] => { const m = /^#?([0-9a-f]{6})$/i.exec (hex) - const n = parseInt (m[1], 16) + const n = parseInt (m![1], 16) return [(n >> 16) & 255, (n >> 8) & 255, n & 255, alpha] } @@ -110,21 +109,10 @@ const isLayer = (obj: unknown): obj is Layer => ( && typeof (obj as Layer).id === 'string' && typeof (obj as Layer).name === 'string' && Array.isArray ((obj as Layer).lines) - && (obj as Layer).lines.every (isLine) && Array.isArray ((obj as Layer).history) && Array.isArray ((obj as Layer).future)) -const isLine = (obj: unknown): obj is Line => ( - typeof obj === 'object' - && obj !== null - && Array.isArray ((obj as Line).points) - && (obj as Line).points.every (n => typeof n === 'number') - && typeof (obj as Line).stroke === 'string' - && typeof (obj as Line).strokeWidth === 'number' - && Object.values (Mode).includes ((obj as Line).mode)) - - export default () => { const drawingRef = useRef (false) const fileInputRef = useRef (null) @@ -143,7 +131,7 @@ export default () => { const activeLayer = layers.find (l => l.id === activeLayerId) const handleMouseDown = (ev: Konva.KonvaEventObject) => { - if (!(activeLayer)) + if (!(activeLayer) || (mode !== Mode.Pen && mode !== Mode.Rubber)) return drawingRef.current = true @@ -222,7 +210,7 @@ export default () => { fileInputRef.current.value = '' } - const handlePaint = async (ev: Konva.KonvaEventObject) => { + const handlePaint = async () => { const layer = activeLayer if (!(layer) || !(stageRef.current)) return @@ -245,14 +233,13 @@ export default () => { $off.width = stageWidth $off.height = stageHeight const ctx = $off.getContext ('2d') - ctx.drawImage (img, 0, 0, stageWidth, stageHeight) + ctx!.drawImage (img, 0, 0, stageWidth, stageHeight) - const imgData = ctx.getImageData (0, 0, stageWidth, stageHeight) + const imgData = ctx!.getImageData (0, 0, stageWidth, stageHeight) const [r, g, b, a] = hexToRgba (colour, 255) floodFill (imgData, Math.floor (pos.x), Math.floor (pos.y), { r, g, b, a }) - ctx.putImageData (imgData, 0, 0) + ctx!.putImageData (imgData, 0, 0) - const prevImageSrc = layer.image?.src const nextSrc = $off.toDataURL ('image/png') updateActiveLayerHistory ([...layer.history, layer.lines]) @@ -347,11 +334,7 @@ export default () => { if (!(Array.isArray (parsed))) throw new Error - const restored: Layer[] = parsed.filter (isLayer).map (l => ({ - ...l, lines: l.lines.map (s => ({ - ...s, mode: (Object.values (Mode).includes (s.mode) - ? s.mode - : Mode.Pen) })) })) + const restored: Layer[] = parsed.filter (isLayer) if (restored.length === 0) throw new Error