@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"
22import { socket } from "./socket"
33import { distanceBetweenTwoPoints } from "./utils"
44import "./App.css"
5-
5+ import { type Pointer } from "./types"
66const CANVAS_HEIGHT = 300
77const CANVAS_WIDTH = 300
88
@@ -37,7 +37,6 @@ const SOCKET_EVENTS_OUTBOUND = {
3737enum GameMode {
3838 OneLine = "One Line" ,
3939 LineLengthLimit = "Line Length Limit" ,
40- TimeLimit = "Time Limit" ,
4140}
4241
4342const App : React . FC = ( ) => {
@@ -53,10 +52,10 @@ const App: React.FC = () => {
5352 const [ lineLengthLimit , setLineLengthLimit ] = useState < number | undefined > (
5453 undefined
5554 )
56- const [ lastX , setLastX ] = useState < number | undefined | null > ( undefined )
57- const [ lastY , setLastY ] = useState < number | undefined | null > ( undefined )
5855 const [ currentLineLength , setCurrentLineLength ] = useState < number > ( 0 )
5956
57+ const [ ongoingPointer , setOngoingPointer ] = useState < Pointer | undefined | null > ( undefined )
58+
6059 const shouldShowCanvas = gameMode !== undefined && gameMode !== null
6160 const isMyTurn = socket . id === turnPlayer
6261
@@ -168,12 +167,18 @@ const App: React.FC = () => {
168167 }
169168 } , [ ] )
170169
171- const startDrawing = ( event : React . MouseEvent < HTMLCanvasElement > ) => {
170+ const startDrawing = ( event : React . PointerEvent < HTMLCanvasElement > ) => {
172171 if ( ! isMyTurn ) return
173172
174- const { offsetX, offsetY } = event . nativeEvent
175- setLastX ( offsetX )
176- setLastY ( offsetY )
173+ const { pageX, pageY, pointerId } = event
174+ const canvas = canvasRef . current
175+ if ( ! canvas ) {
176+ console . error ( NO_CANVAS_ERROR )
177+ return
178+ }
179+ const rect = canvas . getBoundingClientRect ( )
180+ const relativeX = pageX - rect . left
181+ const relativeY = pageY - rect . top
177182
178183 const context = contextRef . current
179184 if ( ! context ) {
@@ -184,58 +189,73 @@ const App: React.FC = () => {
184189 setIsDrawing ( true )
185190
186191 context . beginPath ( )
187- context . lineTo ( offsetX , offsetY )
192+ context . moveTo ( relativeX , relativeY )
193+ context . lineTo ( relativeX , relativeY )
188194 context . stroke ( )
195+ setOngoingPointer ( {
196+ [ pointerId ] : {
197+ relativeX,
198+ relativeY,
199+ } ,
200+ } )
189201
190202 socket ?. emit (
191203 SOCKET_EVENTS_OUTBOUND . DRAW ,
192204 context . getImageData ( 0 , 0 , CANVAS_WIDTH , CANVAS_HEIGHT ) . data
193205 )
194206 }
195207
196- const draw = ( event : React . MouseEvent < HTMLCanvasElement > ) => {
208+ const draw = ( event : React . PointerEvent < HTMLCanvasElement > ) => {
197209 if ( ! isDrawing ) return
198210
211+ const pointer = ongoingPointer ?. [ event . pointerId ]
212+ if ( ! pointer ) {
213+ console . error (
214+ `Could not find pointer for ${ event . type } pointer id ${ event . pointerId } `
215+ )
216+ return
217+ }
218+
199219 const context = contextRef . current
200220 if ( ! context ) {
201221 console . error ( NO_CONTEXT_ERROR )
202222 return
203223 }
204224
205- const { offsetX, offsetY } = event . nativeEvent
206- context . lineTo ( offsetX , offsetY )
225+ const { pageX, pageY } = event
226+ const canvas = canvasRef . current
227+ if ( ! canvas ) {
228+ console . error ( NO_CANVAS_ERROR )
229+ return
230+ }
231+ const rect = canvas . getBoundingClientRect ( )
232+ const relativeX = pageX - rect . left
233+ const relativeY = pageY - rect . top
234+
235+ context . beginPath ( )
236+ context . moveTo ( pointer . relativeX , pointer . relativeY )
237+ context . lineTo ( relativeX , relativeY )
207238 context . stroke ( )
208239
209240 if ( gameMode === GameMode . LineLengthLimit ) {
210- if (
211- lastX === undefined ||
212- lastX === null ||
213- lastY === undefined ||
214- lastY === null
215- ) {
216- throw Error ( "lastX or lastY is undefined" )
217- }
218-
219241 if (
220242 lineLengthLimit !== undefined &&
221243 currentLineLength > lineLengthLimit
222244 ) {
223- stopDrawing ( )
245+ stopDrawing ( event )
224246 setCurrentLineLength ( 0 )
225247
226248 return
227249 }
228250
229251 const additionalLength = distanceBetweenTwoPoints ( {
230- x1 : lastX ,
231- y1 : lastY ,
232- x2 : offsetX ,
233- y2 : offsetY ,
252+ x1 : pointer . relativeX ,
253+ y1 : pointer . relativeY ,
254+ x2 : relativeX ,
255+ y2 : relativeY ,
234256 } )
235257
236258 setCurrentLineLength ( ( prev ) => prev + additionalLength )
237- setLastX ( offsetX )
238- setLastY ( offsetY )
239259
240260 socket ?. emit (
241261 SOCKET_EVENTS_OUTBOUND . DRAW ,
@@ -249,11 +269,26 @@ const App: React.FC = () => {
249269 } else {
250270 throw Error ( `Invalid Game Mode '${ gameMode } '` )
251271 }
272+
273+ setOngoingPointer ( {
274+ [ event . pointerId ] : {
275+ relativeX : relativeX ,
276+ relativeY : relativeY ,
277+ } ,
278+ } )
252279 }
253280
254- const stopDrawing = ( ) => {
281+ const stopDrawing = ( event : React . PointerEvent < HTMLCanvasElement > ) => {
255282 if ( ! isDrawing ) return
256283
284+ const pointer = ongoingPointer ?. [ event . pointerId ]
285+ if ( ! pointer ) {
286+ console . error (
287+ `Could not find pointer for ${ event . type } pointer id ${ event . pointerId } `
288+ )
289+ return
290+ }
291+
257292 setIsDrawing ( false )
258293
259294 socket . emit ( SOCKET_EVENTS_OUTBOUND . END_TURN )
@@ -285,10 +320,10 @@ const App: React.FC = () => {
285320 </ div >
286321 < canvas
287322 ref = { canvasRef }
288- onMouseDown = { startDrawing }
289- onMouseMove = { draw }
290- onMouseUp = { stopDrawing }
291- onMouseLeave = { stopDrawing }
323+ onPointerDown = { startDrawing }
324+ onPointerMove = { draw }
325+ onPointerUp = { stopDrawing }
326+ onPointerLeave = { stopDrawing }
292327 className = "drawing-canvas"
293328 />
294329 < button type = "button" onClick = { clearCanvas } className = "clear-button" >
0 commit comments