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); |
| 6 | 8 | ||
| 9 | + const [mousePosition, setMousePosition] = useState<Vector>({ x:0, y:0 }); | ||
| 10 | + const [isPainting, setIsPainting] = useState(false); | ||
| 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) { |
| 9 | return; | 14 | return; |
| ... | @@ -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