Javascript

Canvas Crash Effect 기록(react + typescript)

YoYoHa 2022. 12. 7. 18:00
728x90
반응형

Mouse Crash Effect Code 기록

import React, {useEffect, useRef} from 'react';

interface mouseType {
    x?: number,
    y?: number
}


export default function Crash(){

    const canvasRef = useRef<HTMLCanvasElement>(null);

    const mouse: mouseType = { x: undefined, y: undefined }
    const particlesArray: any = [];
    let hue:number = 0;

    useEffect(() => {
        const canvas = canvasRef?.current;

        if (canvas) {

            let ctx = canvas.getContext('2d');

            class Particle {
                private x: number | undefined;
                private y: number | undefined;
                private size: number | undefined;
                private readonly speedX: number | undefined;
                private readonly speedY: number | undefined;
                private readonly color: string | undefined;

                constructor() {
                    if (canvas) {
                        this.x = mouse.x;
                        this.y = mouse.y;
                        this.size = Math.random() * 15 + 1;
                        this.speedX = Math.random() * 3 - 1.5;
                        this.speedY = Math.random() * 3 - 1.5;
                        this.color = 'hsl(' + hue + ', 100%, 50%)'
                    }
                }

                update() {
                    if ( this.x && this.y && this.speedX && this.speedY  ) {
                        this.x += this.speedX;
                        this.y += this.speedY;
                        if (typeof this.size === 'number') if (this.size > 0.2) this.size -= 0.1;
                    }
                }

                draw() {
                    if (ctx) {
                        if (typeof this.color === 'string') ctx.fillStyle = this.color;
                        ctx.beginPath();

                        if (typeof this.size === "number") {
                            ctx.arc(this.x as number, this.y as number, this.size, 0, Math.PI * 2);
                        }
                        ctx.fill();
                    }
                }
            }

            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;

            if (ctx) {
                const animate = () => {
                    if (ctx) {
                        ctx.clearRect(0,0, canvas.width, canvas.height);
                        // ctx.fillStyle = 'rgba(0,0,0,0.02)';
                        // ctx.fillRect(0,0, canvas.width, canvas.height);
                        handleParticles();
                        hue+=2;
                        requestAnimationFrame(animate);
                    }
                };
                const handleParticles = () => {
                    for (let i=0;i<particlesArray.length;i++){
                        particlesArray[i].update();
                        particlesArray[i].draw();

                        for(let j =i;j<particlesArray.length;j++) {
                            const dx = particlesArray[i].x - particlesArray[j].x;
                            const dy = particlesArray[i].y - particlesArray[j].y;
                            const distance = Math.sqrt(dx*dx+dy*dy);
                            if (distance < 100 && ctx) {
                                ctx.beginPath();
                                ctx.strokeStyle = particlesArray[i].color;
                                ctx.lineWidth = 0.5;
                                ctx.moveTo(particlesArray[i].x, particlesArray[i].y)
                                ctx.lineTo(particlesArray[j].x, particlesArray[j].y)
                                ctx.stroke();
                                ctx.closePath();
                            }
                        }
                        if (particlesArray[i].size <= 0.3) {
                            particlesArray.splice(i, 1);
                            i--;
                        }
                    }
                };

                window.addEventListener('resize', () => {
                    canvas.width = window.innerWidth;
                    canvas.height = window.innerHeight;
                });

                canvas.addEventListener('click', (e) => {
                    mouse.x = e.x;
                    mouse.y = e.y;
                    for (let i=0;i < 5; i++) {
                        particlesArray.push(new Particle());
                    }
                });

                canvas.addEventListener('mousemove', (e) => {
                    console.log('111');
                    mouse.x = e.x;
                    mouse.y = e.y;
                    for (let i=0;i < 3; i++) {
                        particlesArray.push(new Particle());
                    }
                    console.log(particlesArray);
                });

                animate();

            } else {
                console.log('null ctx');
            }
        }
    }, []);

    return (
        <canvas className="canvas" ref={canvasRef}></canvas>
    );
};

 

 

 

.canvas{ position: absolute; z-index: 1; background: black; width: 100%; height: 100%; top: 0; left: 0; }

 

 

 

728x90
반응형