Showing
1 changed file
with
98 additions
and
18 deletions
| 1 | -import React, { useCallback, useEffect, useRef, useState } from 'react'; | 1 | +import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; |
| 2 | -import { Vector } from './types'; | 2 | +import SocketContext from '../../contexts/SocketContext'; |
| 3 | +import { MessageType, RawMessage } from '../common/types'; | ||
| 4 | +import { BrushData, Vector } from './types'; | ||
| 3 | 5 | ||
| 4 | // 참고 : https://basketdeveloper.tistory.com/79 | 6 | // 참고 : https://basketdeveloper.tistory.com/79 |
| 5 | 7 | ||
| ... | @@ -8,6 +10,7 @@ interface CanvasProps { | ... | @@ -8,6 +10,7 @@ interface CanvasProps { |
| 8 | } | 10 | } |
| 9 | 11 | ||
| 10 | export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { | 12 | export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { |
| 13 | + const socket = useContext(SocketContext); | ||
| 11 | const canvasRef = useRef<HTMLCanvasElement>(null); | 14 | const canvasRef = useRef<HTMLCanvasElement>(null); |
| 12 | 15 | ||
| 13 | const [mousePosition, setMousePosition] = useState<Vector>({ x:0, y:0 }); | 16 | const [mousePosition, setMousePosition] = useState<Vector>({ x:0, y:0 }); |
| ... | @@ -56,6 +59,22 @@ export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { | ... | @@ -56,6 +59,22 @@ export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { |
| 56 | if (coordinates) { | 59 | if (coordinates) { |
| 57 | setIsPainting(true); | 60 | setIsPainting(true); |
| 58 | setMousePosition(coordinates); | 61 | setMousePosition(coordinates); |
| 62 | + | ||
| 63 | + const rawMessage: RawMessage = { | ||
| 64 | + type: MessageType.DRAW_MOVE, | ||
| 65 | + message: coordinates | ||
| 66 | + }; | ||
| 67 | + socket.emit('msg', rawMessage, () => {}); | ||
| 68 | + | ||
| 69 | + const nextRawMessage: RawMessage = { | ||
| 70 | + type: MessageType.DRAW_SET, | ||
| 71 | + message: { | ||
| 72 | + size: 5, | ||
| 73 | + color: '000000', | ||
| 74 | + drawing: true | ||
| 75 | + } as BrushData | ||
| 76 | + }; | ||
| 77 | + socket.emit('msg', nextRawMessage, () => {}); | ||
| 59 | } | 78 | } |
| 60 | }, []); | 79 | }, []); |
| 61 | 80 | ||
| ... | @@ -69,6 +88,13 @@ export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { | ... | @@ -69,6 +88,13 @@ export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { |
| 69 | const newMousePosition = getCoordinates(event); | 88 | const newMousePosition = getCoordinates(event); |
| 70 | if (mousePosition && newMousePosition) { | 89 | if (mousePosition && newMousePosition) { |
| 71 | drawLine(mousePosition, newMousePosition); | 90 | drawLine(mousePosition, newMousePosition); |
| 91 | + | ||
| 92 | + const rawMessage: RawMessage = { | ||
| 93 | + type: MessageType.DRAW_MOVE, | ||
| 94 | + message: newMousePosition | ||
| 95 | + }; | ||
| 96 | + socket.emit('msg', rawMessage, () => {}); | ||
| 97 | + | ||
| 72 | setMousePosition(newMousePosition); | 98 | setMousePosition(newMousePosition); |
| 73 | } | 99 | } |
| 74 | } | 100 | } |
| ... | @@ -77,32 +103,86 @@ export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { | ... | @@ -77,32 +103,86 @@ export const Canvas: React.FC<CanvasProps> = ({ isDrawer }) => { |
| 77 | ); | 103 | ); |
| 78 | 104 | ||
| 79 | const exitPaint = useCallback(() => { | 105 | const exitPaint = useCallback(() => { |
| 106 | + const rawMessage: RawMessage = { | ||
| 107 | + type: MessageType.DRAW_SET, | ||
| 108 | + message: { | ||
| 109 | + size: 5, | ||
| 110 | + color: '000000', | ||
| 111 | + drawing: false | ||
| 112 | + } as BrushData | ||
| 113 | + }; | ||
| 114 | + socket.emit('msg', rawMessage, () => {}); | ||
| 115 | + | ||
| 80 | setIsPainting(false); | 116 | setIsPainting(false); |
| 81 | }, []); | 117 | }, []); |
| 82 | 118 | ||
| 119 | + const handleDrawSet = useCallback((rawMessage: RawMessage) => { | ||
| 120 | + if (rawMessage.type === MessageType.DRAW_SET) { | ||
| 121 | + const data = rawMessage.message as BrushData; | ||
| 122 | + setIsPainting(data.drawing); | ||
| 123 | + } | ||
| 124 | + }, []); | ||
| 125 | + | ||
| 126 | + const handleDrawMove = useCallback((rawMessage: RawMessage) => { | ||
| 127 | + if (rawMessage.type === MessageType.DRAW_MOVE) { | ||
| 128 | + const data = rawMessage.message as Vector; | ||
| 129 | + if (isPainting) { | ||
| 130 | + drawLine(mousePosition, data); | ||
| 131 | + } | ||
| 132 | + setMousePosition(data); | ||
| 133 | + } | ||
| 134 | + }, [isPainting, mousePosition]) | ||
| 135 | + | ||
| 83 | useEffect(() => { | 136 | useEffect(() => { |
| 84 | - if (canvasRef.current && isDrawer) { | 137 | + if (canvasRef.current) { |
| 85 | - const canvas: HTMLCanvasElement = canvasRef.current; | 138 | + if (isDrawer) { |
| 139 | + const canvas: HTMLCanvasElement = canvasRef.current; | ||
| 86 | 140 | ||
| 87 | - canvas.addEventListener('mousedown', startPaint); | 141 | + canvas.addEventListener('mousedown', startPaint); |
| 88 | - canvas.addEventListener('mousemove', paint); | 142 | + canvas.addEventListener('mousemove', paint); |
| 89 | - canvas.addEventListener('mouseup', exitPaint); | 143 | + canvas.addEventListener('mouseup', exitPaint); |
| 90 | - canvas.addEventListener('mouseleave', exitPaint); | 144 | + canvas.addEventListener('mouseleave', exitPaint); |
| 91 | - | 145 | + |
| 92 | - return () => { | 146 | + return () => { |
| 93 | - canvas.removeEventListener('mousedown', startPaint); | 147 | + canvas.removeEventListener('mousedown', startPaint); |
| 94 | - canvas.removeEventListener('mousemove', paint); | 148 | + canvas.removeEventListener('mousemove', paint); |
| 95 | - canvas.removeEventListener('mouseup', exitPaint); | 149 | + canvas.removeEventListener('mouseup', exitPaint); |
| 96 | - canvas.removeEventListener('mouseleave', exitPaint); | 150 | + canvas.removeEventListener('mouseleave', exitPaint); |
| 97 | - }; | 151 | + }; |
| 98 | - } else { | 152 | + } |
| 99 | - // 받아서 그리기 | ||
| 100 | } | 153 | } |
| 101 | }, [isDrawer, startPaint, paint, exitPaint]); | 154 | }, [isDrawer, startPaint, paint, exitPaint]); |
| 102 | 155 | ||
| 156 | + useEffect(() => { | ||
| 157 | + if (!isDrawer) { | ||
| 158 | + socket.on('msg', handleDrawSet); | ||
| 159 | + socket.on('msg', handleDrawMove); | ||
| 160 | + | ||
| 161 | + return () => { | ||
| 162 | + socket.off('msg', handleDrawSet); | ||
| 163 | + socket.off('msg', handleDrawMove); | ||
| 164 | + } | ||
| 165 | + } | ||
| 166 | + }, [isDrawer, handleDrawMove]); | ||
| 167 | + | ||
| 168 | + const handleClearWhenStart = useCallback((rawMessage: RawMessage) => { | ||
| 169 | + if (rawMessage.type === MessageType.GAME_START) { | ||
| 170 | + clearCanvas(); | ||
| 171 | + setIsPainting(false); | ||
| 172 | + // TODO: 펜 굵기, 색 설정하게 되면 여기에 초기화 넣기 | ||
| 173 | + } | ||
| 174 | + }, []); | ||
| 175 | + | ||
| 176 | + useEffect(() => { | ||
| 177 | + socket.on('msg', handleClearWhenStart); | ||
| 178 | + return () => { | ||
| 179 | + socket.off('msg', handleClearWhenStart); | ||
| 180 | + } | ||
| 181 | + }, []); | ||
| 182 | + | ||
| 103 | return ( | 183 | return ( |
| 104 | <div className='mx-3 px-2 py-1 rounded shadow'> | 184 | <div className='mx-3 px-2 py-1 rounded shadow'> |
| 105 | - <canvas ref={canvasRef} width='512' height='384' /> | 185 | + <canvas ref={canvasRef} width='640' height='480' /> |
| 106 | </div> | 186 | </div> |
| 107 | ); | 187 | ); |
| 108 | } | 188 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment