78 lines
1.9 KiB
TypeScript
78 lines
1.9 KiB
TypeScript
"use client"
|
|
import React, {
|
|
forwardRef,
|
|
useCallback,
|
|
useEffect,
|
|
useImperativeHandle,
|
|
useRef,
|
|
} from "react"
|
|
|
|
interface AssistShapeComponentProps {
|
|
size: number
|
|
}
|
|
|
|
const AssistShapeComponent = (
|
|
props: AssistShapeComponentProps,
|
|
ref: React.Ref<unknown> | undefined
|
|
) => {
|
|
const { size } = props
|
|
const canvasRef = useRef<HTMLCanvasElement>(null)
|
|
|
|
const drawAssistShape = useCallback(
|
|
(centerX: number, centerY: number) => {
|
|
const canvas = canvasRef.current
|
|
const ctx = canvas?.getContext("2d")
|
|
if (!canvas || !ctx) return
|
|
|
|
const radius = Math.max(1, size)
|
|
const side = radius * 2
|
|
const left = centerX - radius
|
|
const top = centerY - radius
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
ctx.beginPath()
|
|
ctx.strokeStyle = "#EF4444"
|
|
ctx.lineWidth = 2
|
|
ctx.setLineDash([6, 4])
|
|
ctx.strokeRect(left, top, side, side)
|
|
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2)
|
|
ctx.stroke()
|
|
},
|
|
[size]
|
|
)
|
|
|
|
useEffect(() => {
|
|
const canvas = canvasRef.current
|
|
if (!canvas) return
|
|
canvas.width = window.innerWidth
|
|
canvas.height = window.innerHeight
|
|
const rect = canvas.getBoundingClientRect()
|
|
drawAssistShape(rect.width / 2, rect.height / 2)
|
|
}, [drawAssistShape])
|
|
|
|
const updateAssistShape = (event: { clientX: number; clientY: number }) => {
|
|
const canvas = canvasRef.current
|
|
if (!canvas) return
|
|
const rect = canvas.getBoundingClientRect()
|
|
const centerX = event.clientX - rect.left
|
|
const centerY = event.clientY - rect.top
|
|
drawAssistShape(centerX, centerY)
|
|
}
|
|
|
|
useImperativeHandle(ref, () => ({ updateAssistShape }))
|
|
|
|
return (
|
|
<canvas
|
|
ref={canvasRef}
|
|
style={{
|
|
backgroundColor: "transparent",
|
|
position: "absolute",
|
|
zIndex: 52,
|
|
pointerEvents: "none",
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export default forwardRef(AssistShapeComponent)
|