1

I am using react and drawing a fire works.

There is a mousemove function to get new x y coordinate. Also, there is a function init(). It pushes new object into array.

console.log(MousePosition.left, MousePosition.top) shown the x y coordinate value. Therefore, the mousemove function is worked.

However, the function init() seems cannot catch the value of x y coordinate.

Finally, the fire works started at x:0 y:0 ...

How to solve? Thank you.

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

export default function Canvas() {
    const [MousePosition, setMousePosition] = useState({
        left: 0,
        top: 0
    })
    function handleMouseMove(event) {
        setMousePosition({ left: event.clientX, top: event.clientY });
console.log(MousePosition.left, MousePosition.top)
    }
    const canvasRef = useRef(null);
    var Balls = [];
    var preloaderEffect = true;
    const [canvasOn, setCanvasOn] = useState(true);

    useEffect(() => {
        const canvas = canvasRef.current;
        const c = canvas.getContext('2d');

        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        //
        var color = [
            'rgb(65%, 16%, 16%)', 'rgb(80%, 20%, 20%)', 'rgb(75%, 15%, 15%)', 'rgb(70%, 13%, 13%)', 'rgb(80%, 15%, 15%)', 'rgb(86%, 16%, 16%)', 'rgb(94%, 50%, 50%)', 'rgb(93%, 39%, 39%)'
        ];
        var radius = [5, 6, 7, 8, 9, 10];
        //
        class ball {
            constructor(x, y, colorCode, r) {
                this.position = {
                    x: x,
                    y: y
                };
                this.color = colorCode;
                this.r = r;
                this.velocity = {
                    x: Math.round(Math.random() * 1) * 2 - 1,
                    y: Math.round(Math.random() * 1) * 2 - 1
                };
                this.speed = {
                    x: 20 * Math.random(),
                    y: 20 * Math.random()
                };
                this.ease = 0.9;

            };
            draw() {
                c.beginPath();
                c.shadowBlur = 30;
                c.shadowColor = this.color;
                c.fillStyle = this.color;
                c.arc(this.position.x, this.position.y, this.r, 0, 2 * Math.PI, false);
                c.fill();
                c.closePath();
                c.shadowBlur = 0;
            };
            update() {
                this.draw();
                this.position.x += this.velocity.x * this.speed.x;
                this.position.y += this.velocity.y * this.speed.y;
                this.speed.x *= this.ease;
                this.speed.y *= this.ease;
            };
        };
        //
        function animate() {
            if (preloaderEffect !== true) return
            requestAnimationFrame(animate);
            /*   c.clearRect(0, 0, c.width, c.height) */
            c.fillStyle = 'rgba(0,0,0,0.1)';
            c.fillRect(0, 0, c.width, c.height);

            Balls.forEach((x) => {
                x.update();
            });
        };
        //
        function init() {
            setInterval(() => {
                if (preloaderEffect !== true) { return };
                var a = Math.round(Math.random() * (color.length - 1));
                var b = Math.round(Math.random() * (radius.length - 1));
                for (var i = 0; i < 5; i++) {
                    Balls.push(new ball(MousePosition.left, MousePosition.top, color[a], radius[b]));
                    if (Balls.length > 100) {
                        Balls.shift();
                    };
                };
            }, 100)
        };
        //
        setTimeout(() => {
            preloaderEffect = false;
            setCanvasOn(false);
        }, 5000);
        animate();
        init();
    }, [])

    return (
        <div>
            {canvasOn &&
                <canvas ref={canvasRef} style={{ background: 'black' }} onMouseMove={(event) => handleMouseMove(event)}></canvas>}
        </div>
    )
}



TomFan
  • 113
  • 9
  • 1
    Most of the code here isn't relevant. I recommend stripping down to a [mcve], but basically should be a dupe of https://stackoverflow.com/questions/63224151/how-can-i-access-state-in-an-useeffect-without-re-firing-the-useeffect if I'm not mistaken. You're trying to read state from a `useEffect` that only runs once so it'll only ever see the initial value that the state was in. The overall design here should probably be reconsidered. – ggorlen Jun 16 '22 at 14:56

0 Answers0