123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- import type { FC } from 'react'
- import { useCallback, useEffect, useRef } from 'react'
- type GridMaskProps = {
- children: React.ReactNode
- wrapperClassName?: string
- canvasClassName?: string
- gradientClassName?: string
- }
- const GridMask: FC<GridMaskProps> = ({
- children,
- wrapperClassName,
- canvasClassName,
- gradientClassName,
- }) => {
- const canvasRef = useRef<HTMLCanvasElement | null>(null)
- const ctxRef = useRef<CanvasRenderingContext2D | null>(null)
- const initCanvas = () => {
- const dpr = window.devicePixelRatio || 1
- if (canvasRef.current) {
- const { width: cssWidth, height: cssHeight } = canvasRef.current?.getBoundingClientRect()
- canvasRef.current.width = dpr * cssWidth
- canvasRef.current.height = dpr * cssHeight
- const ctx = canvasRef.current.getContext('2d')
- if (ctx) {
- ctx.scale(dpr, dpr)
- ctx.strokeStyle = '#D1E0FF'
- ctxRef.current = ctx
- }
- }
- }
- const drawRecord = useCallback(() => {
- const canvas = canvasRef.current!
- const ctx = ctxRef.current!
- const rowNumber = parseInt(`${canvas.width / 24}`)
- const colNumber = parseInt(`${canvas.height / 24}`)
- ctx.clearRect(0, 0, canvas.width, canvas.height)
- ctx.beginPath()
- for (let i = 0; i < rowNumber; i++) {
- for (let j = 0; j < colNumber; j++) {
- const x = i * 24
- const y = j * 24
- if (j === 0) {
- ctx.moveTo(x, y + 2)
- ctx.arc(x + 2, y + 2, 2, Math.PI, Math.PI * 1.5)
- ctx.lineTo(x + 22, y)
- ctx.arc(x + 22, y + 2, 2, Math.PI * 1.5, Math.PI * 2)
- ctx.lineTo(x + 24, y + 22)
- ctx.arc(x + 22, y + 22, 2, 0, Math.PI * 0.5)
- ctx.lineTo(x + 2, y + 24)
- ctx.arc(x + 2, y + 22, 2, Math.PI * 0.5, Math.PI)
- }
- else {
- ctx.moveTo(x + 2, y)
- ctx.arc(x + 2, y + 2, 2, Math.PI * 1.5, Math.PI, true)
- ctx.lineTo(x, y + 22)
- ctx.arc(x + 2, y + 22, 2, Math.PI, Math.PI * 0.5, true)
- ctx.lineTo(x + 22, y + 24)
- ctx.arc(x + 22, y + 22, 2, Math.PI * 0.5, 0, true)
- ctx.lineTo(x + 24, y + 2)
- ctx.arc(x + 22, y + 2, 2, 0, Math.PI * 1.5, true)
- }
- }
- }
- ctx.stroke()
- ctx.closePath()
- }, [])
- const handleStartDraw = () => {
- if (canvasRef.current && ctxRef.current)
- drawRecord()
- }
- useEffect(() => {
- initCanvas()
- handleStartDraw()
- }, [])
- return (
- <div className={`relative bg-white ${wrapperClassName}`}>
- <canvas ref={canvasRef} className={`absolute inset-0 w-full h-full ${canvasClassName}`} />
- <div className={`absolute w-full h-full z-[1] bg-gradient-to-b from-white/80 to-white rounded-lg ${gradientClassName}`} />
- <div className='relative z-[2]'>{children}</div>
- </div>
- )
- }
- export default GridMask
|