Drawing function
This commit is contained in:
parent
6bff62c0c2
commit
a088bff7be
3 changed files with 116 additions and 6 deletions
|
@ -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>
|
||||
)
|
||||
|
|
64
leaky-ships/hooks/useDraw.ts
Normal file
64
leaky-ships/hooks/useDraw.ts
Normal 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 }
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue