Search code examples
javascripthtmlcssdrawing

Element.animate only if coordinate is in defined range


The animated balls are moving into my "About" section. However, I want to have the same behavior as if they were leaving the "page" to the top, left, or right. So the balls should not be drawn when their coordinate is out of range.

My idea is to either stop drawing it or try to move the about section somehow to the foreground. But I am not experienced in CSS/Javascript. So maybe you have a better/easier idea how to achieve my goal?

Thanks

<!DOCTYPE html>
<html>
<head>
    <link href="https://fonts.cdnfonts.com/css/monaco" rel="stylesheet">
    <meta charset="utf-8" />
    <title>Test</title>
    <style>
        body {
            margin: 0;
            width: 100%;
        }

        #header {
            position: relative;
            height: 580px;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        #about {
            position: relative;
            height: auto;
            background-color: #f9f9f9;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        .subtitle {
            position: relative;
            top: 40px;
            left: 10%;
            font-family: Monaco;
            color: #1e9912;
            font-size: 30px;
            font-weight: 200;
            width: fit-content;
            margin-right: 0px;
        }

        .ball {
            position: absolute;
            border-radius: 100%;
            opacity: 0.7;
        }

        #bio {
            top: 10px;
            position: relative;
            left: 20%;
            width: 70%;
            font-family: Monaco;
            font-size: 20px;
            line-height: 1.6;
            padding-bottom: 30px;
            margin-right: 0px;
        }
    </style>

</head>

<body>
    <div id="header">
    </div>
    <div id="about">
        <h3 class="subtitle">About</h3>
        <div id="bio">
            <p>Long text.</p>
            <p>continue long text.</p>
        </div>
    </div>
    <script>
        // Some random colors
        const colors = ["#3CC157", "#2AA7FF", "#1B1B1B", "#FCBC0F", "#F85F36"];
        const numBalls = 100;


        let balls = [];

        function initializeBalls() {
            for (let i = 0; i < numBalls; i++) {
                let ball = document.createElement("div");
                let parent = document.getElementById("header");
                ball.classList.add("ball");
                ball.style.background = colors[Math.floor(Math.random() * colors.length)];
                ball.style.left = `${Math.floor(Math.random() * parent.offsetWidth)}px`;
                ball.style.top = `${Math.floor(Math.random() * parent.offsetHeight)}px`;
                ball.style.transform = `scale(${Math.random()})`;
                ball.style.width = `${Math.random()}em`;
                ball.style.height = ball.style.width;

                balls.push(ball);
                document.body.append(ball);
            }

            // Keyframes
            balls.forEach((el, i, ra) => {
                let to = {
                    x: Math.random() * (i % 2 === 0 ? -110 : 110),
                    y: Math.random() * 120
                };

                let anim = el.animate(
                    [
                        { transform: "translate(0, 0)" },
                        { transform: `translate(${to.x}px, ${to.y}px)` }
                    ],
                    {
                        duration: (Math.random() + 1) * 2000, // random duration
                        direction: "alternate",
                        fill: "both",
                        iterations: Infinity,
                        easing: "ease-in-out"
                    }
                );
            });
        }
        initializeBalls();
    </script>
</body>
</html>

Solution

  • add z-index: 2; to your #about section in CSS

    <!DOCTYPE html>
    <html>
    <head>
        <link href="https://fonts.cdnfonts.com/css/monaco" rel="stylesheet">
        <meta charset="utf-8" />
        <title>Test</title>
        <style>
            body {
                margin: 0;
                width: 100%;
            }
    
            #header {
                position: relative;
                height: 580px;
                width: 100%;
                margin: 0;
                padding: 0;
            }
    
            #about {
                position: relative;
                height: auto;
                background-color: #f9f9f9;
                width: 100%;
                margin: 0;
                padding: 0;
                z-index: 2;
            }
    
            .subtitle {
                position: relative;
                top: 40px;
                left: 10%;
                font-family: Monaco;
                color: #1e9912;
                font-size: 30px;
                font-weight: 200;
                width: fit-content;
                margin-right: 0px;
            }
    
            .ball {
                position: absolute;
                border-radius: 100%;
                opacity: 0.7;
            }
    
            #bio {
                top: 10px;
                position: relative;
                left: 20%;
                width: 70%;
                font-family: Monaco;
                font-size: 20px;
                line-height: 1.6;
                padding-bottom: 30px;
                margin-right: 0px;
            }
        </style>
    
    </head>
    
    <body>
        <div id="header">
        </div>
        <div id="about">
            <h3 class="subtitle">About</h3>
            <div id="bio">
                <p>Long text.</p>
                <p>continue long text.</p>
            </div>
        </div>
        <script>
            // Some random colors
            const colors = ["#3CC157", "#2AA7FF", "#1B1B1B", "#FCBC0F", "#F85F36"];
            const numBalls = 100;
    
    
            let balls = [];
    
            function initializeBalls() {
                for (let i = 0; i < numBalls; i++) {
                    let ball = document.createElement("div");
                    let parent = document.getElementById("header");
                    ball.classList.add("ball");
                    ball.style.background = colors[Math.floor(Math.random() * colors.length)];
                    ball.style.left = `${Math.floor(Math.random() * parent.offsetWidth)}px`;
                    ball.style.top = `${Math.floor(Math.random() * parent.offsetHeight)}px`;
                    ball.style.transform = `scale(${Math.random()})`;
                    ball.style.width = `${Math.random()}em`;
                    ball.style.height = ball.style.width;
    
                    balls.push(ball);
                    document.body.append(ball);
                }
    
                // Keyframes
                balls.forEach((el, i, ra) => {
                    let to = {
                        x: Math.random() * (i % 2 === 0 ? -110 : 110),
                        y: Math.random() * 120
                    };
    
                    let anim = el.animate(
                        [
                            { transform: "translate(0, 0)" },
                            { transform: `translate(${to.x}px, ${to.y}px)` }
                        ],
                        {
                            duration: (Math.random() + 1) * 2000, // random duration
                            direction: "alternate",
                            fill: "both",
                            iterations: Infinity,
                            easing: "ease-in-out"
                        }
                    );
                });
            }
            initializeBalls();
        </script>
    </body>
    </html>