84 lines
2.1 KiB
TypeScript
84 lines
2.1 KiB
TypeScript
import React, {
|
|
forwardRef,
|
|
useCallback,
|
|
useEffect,
|
|
useImperativeHandle,
|
|
useRef,
|
|
} from 'react'
|
|
import './HomeBanner.css'
|
|
|
|
type HomeBannerProps = {
|
|
children?: React.ReactNode
|
|
stars: number
|
|
}
|
|
|
|
export type HomeBannerHandle = {
|
|
newStar: () => void
|
|
}
|
|
|
|
export const HomeBanner = forwardRef<HomeBannerHandle, HomeBannerProps>(
|
|
function HomeBanner({ children, stars }: HomeBannerProps, ref) {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null)
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
|
|
const drawStarAtPosition = useCallback(
|
|
(ctx: CanvasRenderingContext2D, x: number, y: number) => {
|
|
let r = 2.5 * Math.random()
|
|
|
|
//Draw the stars;
|
|
ctx.beginPath()
|
|
ctx.fillStyle = 'white'
|
|
ctx.arc(x, y, r, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
},
|
|
[],
|
|
)
|
|
|
|
const drawStar = useCallback(
|
|
(ctx: CanvasRenderingContext2D) => {
|
|
//Random position and size of stars;
|
|
let x = ctx.canvas.width * Math.random()
|
|
let y = ctx.canvas.height * Math.random()
|
|
|
|
drawStarAtPosition(ctx, x, y)
|
|
},
|
|
[drawStarAtPosition],
|
|
)
|
|
|
|
useImperativeHandle(ref, () => {
|
|
return {
|
|
newStar() {
|
|
const context = canvasRef.current?.getContext('2d')
|
|
if (context) {
|
|
drawStar(context)
|
|
}
|
|
},
|
|
}
|
|
}, [drawStar])
|
|
|
|
useEffect(() => {
|
|
if (canvasRef.current) {
|
|
canvasRef.current.width =
|
|
containerRef.current?.clientWidth || window.innerWidth
|
|
canvasRef.current.height = 0.8 * window.innerHeight
|
|
}
|
|
const context = canvasRef.current?.getContext('2d')
|
|
if (context) {
|
|
for (let i = 0; i < stars; i++) {
|
|
//Glow effect;
|
|
context.shadowBlur = 10
|
|
context.shadowColor = 'white'
|
|
|
|
setTimeout(() => drawStar(context), i * 100)
|
|
}
|
|
}
|
|
}, [drawStar, stars])
|
|
|
|
return (
|
|
<div className="splash-bg" ref={containerRef}>
|
|
<canvas ref={canvasRef} className="stars"></canvas>
|
|
<div className="splash">{children}</div>
|
|
</div>
|
|
)
|
|
},
|
|
)
|