본문 바로가기
개인프로젝트/unitedPrompt

ContentSectionThree 눈 내리기 추가

by useSword 2024. 1. 20.

 

 

 

ContentSectionThree에 눈내리기를 추가하였다.

snow.jsx

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

class SnowItem {
    static defaultOptions = {
        color: 'white',
        radius: [0.5, 3.0],
        speed: [1, 3],
        wind: [-0.5, 3.0]
    };

    constructor(canvas, options = {}) {
        this.canvas = canvas;
        this.ctx = canvas.getContext('2d');
        this.options = { ...SnowItem.defaultOptions, ...options };
        this.initialize();
    }

    initialize() {
        this.x = Math.random() * this.canvas.offsetWidth;
        this.y = Math.random() * -this.canvas.offsetHeight;
        this.radius = SnowItem.randomBetween(...this.options.radius);
        this.speed = SnowItem.randomBetween(...this.options.speed);
        this.wind = SnowItem.randomBetween(...this.options.wind);
    }

    static randomBetween(min, max) {
        return Math.random() * (max - min) + min;
    }

    update(snowHeight) {
        const distanceToMouse = Math.sqrt(Math.pow(this.x - pointer.x, 2) + Math.pow(this.y - pointer.y, 2));
        const mouseEffectRadius = 50;

        if (distanceToMouse < mouseEffectRadius) {
            this.x = Math.random() * this.canvas.width;
            this.y = -this.radius;
        } else {
            this.y += this.speed;
            this.x += this.wind;
        }

        if (this.y > this.canvas.height) {
            this.x = Math.random() * this.canvas.offsetWidth;
            this.y = -this.radius;
        }
    }

    draw(ctx) {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
        ctx.fillStyle = this.options.color;
        ctx.fill();
        ctx.closePath();
    }
}

const pointer = {
    x: 0,
    y: 0
};

const Snow = ({ count = 200 }) => {
    const canvasRef = useRef(null);
    let snowflakes = [];
    let snowHeight = [];

    const createSnowflakes = () => {
        for (let i = 0; i < count; i++) {
            snowflakes.push(new SnowItem(canvasRef.current));
        }
    };

    const update = () => {
        const canvas = canvasRef.current;
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);

        snowflakes.forEach(flake => {
            flake.update(snowHeight);
            flake.draw(ctx);
        });

        requestAnimationFrame(update);
    };

    const resize = () => {
        const canvas = canvasRef.current;
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        snowHeight = new Array(canvas.width).fill(0);
    };

    useEffect(() => {
        createSnowflakes();
        update();
        window.addEventListener('resize', resize);
        resize();

        return () => {
            window.removeEventListener('resize', resize);
        };
    }, []);

    useEffect(() => {
        const canvas = canvasRef.current;
        const handleMouseMove = (e) => {
            pointer.x = e.clientX;
            pointer.y = e.clientY;
        };
        canvas.addEventListener('mousemove', handleMouseMove);

        return () => {
            canvas.removeEventListener('mousemove', handleMouseMove);
        };
    }, []);

    return <canvas ref={canvasRef} className="snow-canvas" />;
};

export default Snow;

'개인프로젝트 > unitedPrompt' 카테고리의 다른 글

예전 아이콘  (0) 2024.01.20
ContentSectionTwo  (1) 2024.01.19
ContentSectionThree  (0) 2024.01.18