admin管理员组

文章数量:1122832

I want the animation of the hovered ball to pause, others should keep animating. Chat GPT has no clue. According to css hover should also reveal the 2nd image - > this only works when i remove javascript altogether.

Here's the codepen

const balls = document.querySelectorAll('.ball');

// Function to animate the sway of a ball
function swayBall(ball, offsetAngle) {
    const amplitude = Math.random() * 1 + 1; 
    const speed = Math.random() * 0.02 + 0.01; 

    let angle = offsetAngle; 
    let isHovered = false; 
    let animationId; // 

    function animate() {
        if (!isHovered) {
            angle += speed; 
            const swayAngle = Math.sin(angle) * amplitude; 
            ball.style.transform = `rotate(${swayAngle}deg)`; 
        }
        animationId = requestAnimationFrame(animate); 
    }

    // Start animation
    animate();

    // Stop animation on hover
    ball.addEventListener('mouseenter', () => {
        isHovered = true; // Stop animation
        cancelAnimationFrame(animationId); 
        ball.style.transform = ''; 
        console.log(`Hover started on:`, ball); 
    });

    // Resume animation on mouse leave
    ball.addEventListener('mouseleave', () => {
        isHovered = false; 
        animate(); 
        console.log(`Hover ended on:`, ball); 
    });
}

balls.forEach((ball, index) => {
    const offsetAngle = Math.random() * Math.PI * 2; 
    swayBall(ball, offsetAngle);
});

Animation works fine, but it does not stop on hover, nor does it reveal the image below.

I want the animation of the hovered ball to pause, others should keep animating. Chat GPT has no clue. According to css hover should also reveal the 2nd image - > this only works when i remove javascript altogether.

Here's the codepen

const balls = document.querySelectorAll('.ball');

// Function to animate the sway of a ball
function swayBall(ball, offsetAngle) {
    const amplitude = Math.random() * 1 + 1; 
    const speed = Math.random() * 0.02 + 0.01; 

    let angle = offsetAngle; 
    let isHovered = false; 
    let animationId; // 

    function animate() {
        if (!isHovered) {
            angle += speed; 
            const swayAngle = Math.sin(angle) * amplitude; 
            ball.style.transform = `rotate(${swayAngle}deg)`; 
        }
        animationId = requestAnimationFrame(animate); 
    }

    // Start animation
    animate();

    // Stop animation on hover
    ball.addEventListener('mouseenter', () => {
        isHovered = true; // Stop animation
        cancelAnimationFrame(animationId); 
        ball.style.transform = ''; 
        console.log(`Hover started on:`, ball); 
    });

    // Resume animation on mouse leave
    ball.addEventListener('mouseleave', () => {
        isHovered = false; 
        animate(); 
        console.log(`Hover ended on:`, ball); 
    });
}

balls.forEach((ball, index) => {
    const offsetAngle = Math.random() * Math.PI * 2; 
    swayBall(ball, offsetAngle);
});

Animation works fine, but it does not stop on hover, nor does it reveal the image below.

Share Improve this question edited Nov 22, 2024 at 21:41 Paweł Dżabba asked Nov 22, 2024 at 21:37 Paweł DżabbaPaweł Dżabba 32 bronze badges 0
Add a comment  | 

2 Answers 2

Reset to default 1

Your code and animation looks fine to me. But the angle is lost on hover. The reveal is working as I am seeing it. Edit: this was a test in Firefox.

I removed three lines of code and the pendulum keeps its angle.

  1. In your "mouseenter" event listener
//cancelAnimationFrame(animationId); 
//ball.style.transform = ''; 
  1. In your "mouseleave" event listener
//animate(); 

Edit: I changed the order of your elements to provide "correct" DOM-Order. The video is in the background, should IMHO be first. Then removed the z-index altogether, since DOM order is correct.

I gave the balls a display: inline-block; to avoid messing with static heights and fitting to content.

Changed positions to absolute to align with your video-frame.

Works for me in chrome.

const balls = document.querySelectorAll('.ball');

// Function to animate the sway of a ball
function swayBall(ball, offsetAngle) {
    const amplitude = Math.random() * 1 + 1; 
    const speed = Math.random() * 0.02 + 0.01; 

    let angle = offsetAngle; 
    let isHovered = false; 
    let animationId; // 

    function animate() {
        if (!isHovered) {
            angle += speed; 
            const swayAngle = Math.sin(angle) * amplitude; 
            ball.style.transform = `rotate(${swayAngle}deg)`; 
        }
        animationId = requestAnimationFrame(animate); 
    }

    // Start animation
    animate();

    // Stop animation on hover
    ball.addEventListener('mouseenter', () => {
        isHovered = true; // Stop animation
        //cancelAnimationFrame(animationId); 
        //ball.style.transform = ''; 
        console.log(`Hover started on:`, ball); 
    });

    // Resume animation on mouse leave
    ball.addEventListener('mouseleave', () => {
        isHovered = false; 
        //animate(); 
        console.log(`Hover ended on:`, ball); 
    });
}

balls.forEach((ball, index) => {
    const offsetAngle = Math.random() * Math.PI * 2; 
    swayBall(ball, offsetAngle);
});
.video-banner {
    width: 1600px;
    height: 600px;
    border-radius: 20px;
    overflow: hidden;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
}

.video-banner video {
    position: absolute;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hanging-balls {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    display: flex;
    justify-content: space-evenly;
    align-items: flex-start;
    pointer-events: none;
}

.ball {
    display: inline-block;
    position: relative;
    width: 16%;
    transform-origin: top center;
    pointer-events: auto; /* Allow hover */
}

.ball img {
    width: 100%;
    height: auto;
    position: absolute;
    top: 0;
    left: 0;
    transition: opacity 0.3s ease-in-out;
}

.ball img.default {
   /* z-index: 1; *//* Default image starts on top */
}

.ball img.reveal {
    /*z-index: 2; *//* Reveal image appears above */
    opacity: 0; /* Initially invisible */
    pointer-events: none; /* Prevent interaction when not visible */
}

.ball:hover img.default {
    opacity: 0; /* Fade out the default image */
}

.ball:hover img.reveal {
    opacity: 1; /* Fade in the reveal image */
}
<div class="video-banner">
    <video autoplay muted playsinline id="banner-video" poster="https://i.ibb.co/QjnMSLG/bground.jpg" >
        <source src="https://i.ibb.co/QjnMSLG/bground.jpg" type="video/mp4">
        Your browser does not support the video tag.
    </video>
    <div class="hanging-balls">
        <div class="ball">
            <img class="default" src="https://i.ibb.co/ZJsMGhn/ball1.png" alt="Red Ball">
            <img class="reveal" src="https://i.ibb.co/yVBdBG1/ball1-reveal.png" alt="Red Ball Reveal">
        </div>
        <div class="ball">
            <img class="default" src="https://i.ibb.co/Hnm7NL5/ball2.png" alt="Green Ball">
            <img class="reveal" src="https://i.ibb.co/N9gmg85/ball2-reveal.png" alt="Green Ball Reveal">
        </div>
        <div class="ball">
            <img class="default" src="https://i.ibb.co/mGxgyPb/ball3.png" alt="Blue Ball">
            <img class="reveal" src=https://i.ibb.co/hDwJvbG/ball3-reveal.png" alt="Blue Ball Reveal">
        </div>
        <div class="ball">
            <img class="default" src="https://i.ibb.co/4fx06NW/ball4.png" alt="Gold Ball">
            <img class="reveal" src="https://i.ibb.co/xf5DWh0/ball4-reveal.png" alt="Gold Ball Reveal">
        </div>
    </div>
</div>

that's happening because "hanging-balls" div has no height at all. So in reality you are not hovering to the balls. you could just give it a fixed height or 100%. I'm pretty sure that's the problem

本文标签: javascriptPause asynchronous animation on hoverStack Overflow