Drawing function

This commit is contained in:
aronmal 2023-05-26 18:25:14 +02:00
parent 6bff62c0c2
commit a088bff7be
Signed by: aronmal
GPG key ID: 816B7707426FC612
3 changed files with 116 additions and 6 deletions

View file

@ -1,12 +1,13 @@
// import Bluetooth from './Bluetooth'
// import FogImages from './FogImages'
import { Hit, MouseCursor, Target } from "../../interfaces/frontend"
import { Draw, Hit, MouseCursor, Target } from "../../interfaces/frontend"
// import Bluetooth from "./Bluetooth"
// import FogImages from "./FogImages"
import Labeling from "./Labeling"
import Ships from "./Ships"
import BorderTiles from "@components/Gamefield/BorderTiles"
import EventBar from "@components/Gamefield/EventBar"
import HitElems from "@components/Gamefield/HitElems"
import Targets from "@components/Gamefield/Targets"
import { useDraw } from "@hooks/useDraw"
import {
hitReducer,
initlialTarget,
@ -52,17 +53,15 @@ function Gamefield() {
} else if (!overlapsWithAnyBorder(targetPreview, mode))
setTarget({ show: true, x, y })
},
[hits, mode, targetPreview]
[hits, mode, target, targetPreview]
)
useEffect(() => {
console.log(1)
const { x, y, show } = target
const { shouldShow, ...position } = mouseCursor
if (!shouldShow || overlapsWithAnyBorder(position, mode))
setTargetPreview((e) => ({ ...e, show: false }))
else {
console.log(2, position)
setTargetPreview({
...position,
show: !show || x !== position.x || y !== position.y,
@ -70,6 +69,29 @@ function Gamefield() {
}
}, [mode, mouseCursor, target])
const [color, setColor] = useState<string>("#f00")
const [disable, setDisable] = useState(false)
const { canvasRef, onMouseDown, clear } = useDraw(drawLine)
function drawLine({ prevPoint, currentPoint, ctx }: Draw) {
const { x: currX, y: currY } = currentPoint
const lineColor = color
const lineWidth = 5
let startPoint = prevPoint ?? currentPoint
ctx.beginPath()
ctx.lineWidth = lineWidth
ctx.strokeStyle = lineColor
ctx.moveTo(startPoint.x, startPoint.y)
ctx.lineTo(currX, currY)
ctx.stroke()
ctx.fillStyle = lineColor
ctx.beginPath()
ctx.arc(startPoint.x, startPoint.y, 2, 0, 2 * Math.PI)
ctx.fill()
}
return (
<div id="gamefield">
{/* <Bluetooth /> */}
@ -95,7 +117,20 @@ function Gamefield() {
<Targets props={{ target, targetPreview, mode, hits }} />
{/* <span id='dev-debug' style={{gridArea: '1 / 12 / 1 / 15', backgroundColor: 'red', zIndex: 3} as CSSProperties}>Debug</span> */}
<canvas
style={
{
pointerEvents: !disable ? "auto" : "none",
} as CSSProperties
}
ref={canvasRef}
onMouseDown={onMouseDown}
width="648"
height="648"
/>
</div>
<button onClick={() => setDisable((e) => !e)}>toggle disable</button>
<button onClick={clear}>Clear</button>
<EventBar props={{ setMode, setTarget }} />
</div>
)

View file

@ -0,0 +1,64 @@
import { Draw, Point } from "../interfaces/frontend"
import { useEffect, useRef, useState } from "react"
export const useDraw = (
onDraw: ({ ctx, currentPoint, prevPoint }: Draw) => void
) => {
const [mouseDown, setMouseDown] = useState(false)
const canvasRef = useRef<HTMLCanvasElement>(null)
const prevPoint = useRef<null | Point>(null)
const onMouseDown = () => setMouseDown(true)
const clear = () => {
const canvas = canvasRef.current
if (!canvas) return
const ctx = canvas.getContext("2d")
if (!ctx) return
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
useEffect(() => {
const handler = (e: MouseEvent) => {
if (!mouseDown) return
const currentPoint = computePointInCanvas(e)
const ctx = canvasRef.current?.getContext("2d")
if (!ctx || !currentPoint) return
onDraw({ ctx, currentPoint, prevPoint: prevPoint.current })
prevPoint.current = currentPoint
}
const computePointInCanvas = (e: MouseEvent) => {
const canvas = canvasRef.current
if (!canvas) return
const rect = canvas.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
return { x, y }
}
const mouseUpHandler = () => {
setMouseDown(false)
prevPoint.current = null
}
// Add event listeners
canvasRef.current?.addEventListener("mousemove", handler)
window.addEventListener("mouseup", mouseUpHandler)
// Remove event listeners
return () => {
canvasRef.current?.removeEventListener("mousemove", handler)
window.removeEventListener("mouseup", mouseUpHandler)
}
}, [onDraw])
return { canvasRef, onMouseDown, clear }
}

View file

@ -47,3 +47,14 @@ interface removeMissile {
}
export type HitDispatch = fireMissile | removeMissile
export interface Point {
x: number
y: number
}
export interface Draw {
ctx: CanvasRenderingContext2D
currentPoint: Point
prevPoint: Point | null
}