Browse Source

#3 型エラー対応

main
みてるぞ 4 days ago
parent
commit
235814aff7
1 changed files with 10 additions and 27 deletions
  1. +10
    -27
      frontend/src/components/threads/ThreadCanvas.tsx

+ 10
- 27
frontend/src/components/threads/ThreadCanvas.tsx View File

@@ -17,11 +17,11 @@ type Layer = {
image?: ImageItem } image?: ImageItem }


type Line = type Line =
| { mode: Mode.Pen | Mode.Rubber
| { mode: typeof Mode.Pen | typeof Mode.Rubber
points: number[] points: number[]
stroke: string stroke: string
strokeWidth: number } strokeWidth: number }
| { mode: Mode.Paint
| { mode: typeof Mode.Paint
points: number[] points: number[]
stroke: string, stroke: string,
imageSrc: string } imageSrc: string }
@@ -29,7 +29,6 @@ type Line =
const Mode = { const Mode = {
Pen: 'Pen', Pen: 'Pen',
Rubber: 'Rubber', Rubber: 'Rubber',
Image: 'Image',
Paint: 'Paint' } as const Paint: 'Paint' } as const
type Mode = (typeof Mode)[keyof typeof Mode] type Mode = (typeof Mode)[keyof typeof Mode]


@@ -51,7 +50,7 @@ const floodFill = (
const start = getRGBA (data, sx, sy, W) const start = getRGBA (data, sx, sy, W)
const visited = new Uint8Array (W * H) 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 return


const stack: [number, number][] = [[sx, sy]] 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 hexToRgba = (hex: string, alpha = 255): [number, number, number, number] => {
const m = /^#?([0-9a-f]{6})$/i.exec (hex) 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] 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).id === 'string'
&& typeof (obj as Layer).name === 'string' && typeof (obj as Layer).name === 'string'
&& Array.isArray ((obj as Layer).lines) && Array.isArray ((obj as Layer).lines)
&& (obj as Layer).lines.every (isLine)
&& Array.isArray ((obj as Layer).history) && Array.isArray ((obj as Layer).history)
&& Array.isArray ((obj as Layer).future)) && 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 () => { export default () => {
const drawingRef = useRef (false) const drawingRef = useRef (false)
const fileInputRef = useRef<HTMLInputElement> (null) const fileInputRef = useRef<HTMLInputElement> (null)
@@ -143,7 +131,7 @@ export default () => {
const activeLayer = layers.find (l => l.id === activeLayerId) const activeLayer = layers.find (l => l.id === activeLayerId)


const handleMouseDown = (ev: Konva.KonvaEventObject<MouseEvent | TouchEvent>) => { const handleMouseDown = (ev: Konva.KonvaEventObject<MouseEvent | TouchEvent>) => {
if (!(activeLayer))
if (!(activeLayer) || (mode !== Mode.Pen && mode !== Mode.Rubber))
return return


drawingRef.current = true drawingRef.current = true
@@ -222,7 +210,7 @@ export default () => {
fileInputRef.current.value = '' fileInputRef.current.value = ''
} }


const handlePaint = async (ev: Konva.KonvaEventObject<MouseEvent | TouchEvent>) => {
const handlePaint = async () => {
const layer = activeLayer const layer = activeLayer
if (!(layer) || !(stageRef.current)) if (!(layer) || !(stageRef.current))
return return
@@ -245,14 +233,13 @@ export default () => {
$off.width = stageWidth $off.width = stageWidth
$off.height = stageHeight $off.height = stageHeight
const ctx = $off.getContext ('2d') 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) const [r, g, b, a] = hexToRgba (colour, 255)
floodFill (imgData, Math.floor (pos.x), Math.floor (pos.y), { r, g, b, a }) 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') const nextSrc = $off.toDataURL ('image/png')


updateActiveLayerHistory ([...layer.history, layer.lines]) updateActiveLayerHistory ([...layer.history, layer.lines])
@@ -347,11 +334,7 @@ export default () => {
if (!(Array.isArray (parsed))) if (!(Array.isArray (parsed)))
throw new Error 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) if (restored.length === 0)
throw new Error throw new Error




Loading…
Cancel
Save