Showing
1 changed file
with
52 additions
and
0 deletions
1 | import React, { useCallback, useEffect, useRef, useState } from 'react'; | 1 | import React, { useCallback, useEffect, useRef, useState } from 'react'; |
2 | import { Vector } from './types'; | 2 | import { Vector } from './types'; |
3 | 3 | ||
4 | +// 참고 : https://basketdeveloper.tistory.com/79 | ||
5 | + | ||
4 | export const Canvas: React.FC = () => { | 6 | export const Canvas: React.FC = () => { |
5 | const canvasRef = useRef<HTMLCanvasElement>(null); | 7 | const canvasRef = useRef<HTMLCanvasElement>(null); |
8 | + | ||
9 | + const [mousePosition, setMousePosition] = useState<Vector>({ x:0, y:0 }); | ||
10 | + const [isPainting, setIsPainting] = useState(false); | ||
6 | 11 | ||
7 | const getCoordinates = useCallback((event: MouseEvent): Vector | undefined => { | 12 | const getCoordinates = useCallback((event: MouseEvent): Vector | undefined => { |
8 | if (!canvasRef.current) { | 13 | if (!canvasRef.current) { |
... | @@ -33,6 +38,53 @@ export const Canvas: React.FC = () => { | ... | @@ -33,6 +38,53 @@ export const Canvas: React.FC = () => { |
33 | } | 38 | } |
34 | }, []); | 39 | }, []); |
35 | 40 | ||
41 | + const startPaint = useCallback((event: MouseEvent) => { | ||
42 | + const coordinates = getCoordinates(event); | ||
43 | + if (coordinates) { | ||
44 | + setIsPainting(true); | ||
45 | + setMousePosition(coordinates); | ||
46 | + } | ||
47 | + }, []); | ||
48 | + | ||
49 | + const paint = useCallback( | ||
50 | + (event: MouseEvent) => { | ||
51 | + // 드래그 방지 | ||
52 | + event.preventDefault(); | ||
53 | + event.stopPropagation(); | ||
54 | + | ||
55 | + if (isPainting) { | ||
56 | + const newMousePosition = getCoordinates(event); | ||
57 | + if (mousePosition && newMousePosition) { | ||
58 | + drawLine(mousePosition, newMousePosition); | ||
59 | + setMousePosition(newMousePosition); | ||
60 | + } | ||
61 | + } | ||
62 | + }, | ||
63 | + [isPainting, mousePosition] | ||
64 | + ); | ||
65 | + | ||
66 | + const exitPaint = useCallback(() => { | ||
67 | + setIsPainting(false); | ||
68 | + }, []); | ||
69 | + | ||
70 | + useEffect(() => { | ||
71 | + if (canvasRef.current) { | ||
72 | + const canvas: HTMLCanvasElement = canvasRef.current; | ||
73 | + | ||
74 | + canvas.addEventListener('mousedown', startPaint); | ||
75 | + canvas.addEventListener('mousemove', paint); | ||
76 | + canvas.addEventListener('mouseup', exitPaint); | ||
77 | + canvas.addEventListener('mouseleave', exitPaint); | ||
78 | + | ||
79 | + return () => { | ||
80 | + canvas.removeEventListener('mousedown', startPaint); | ||
81 | + canvas.removeEventListener('mousemove', paint); | ||
82 | + canvas.removeEventListener('mouseup', exitPaint); | ||
83 | + canvas.removeEventListener('mouseleave', exitPaint); | ||
84 | + }; | ||
85 | + } | ||
86 | + }, [startPaint, paint, exitPaint]); | ||
87 | + | ||
36 | return ( | 88 | return ( |
37 | <div className='mx-3 px-2 py-1 rounded shadow'> | 89 | <div className='mx-3 px-2 py-1 rounded shadow'> |
38 | <canvas ref={canvasRef} width='512' height='384' /> | 90 | <canvas ref={canvasRef} width='512' height='384' /> | ... | ... |
-
Please register or login to post a comment