You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GSAP悬停动画异常:仅渲染时元素在视口才生效的问题求助

问题修复方案

问题现象

  • 从页面顶部加载后滚动至目标区域,鼠标悬停动画无响应
  • 页面加载时已处于目标区域,动画可正常触发

问题原因

你的HoverButton类仅在初始化和窗口 resize时调用calculatePosition()计算元素位置,但页面滚动时,元素的视口位置会发生变化,getBoundingClientRect()返回的坐标已失效,导致鼠标位置与元素中心的距离计算错误,无法触发hover逻辑。

修复代码

在attachEventsListener方法中添加scroll事件监听,每次滚动时重新计算元素位置:

(function() {
    class HoverButton {
        constructor(el) {
            this.el = el;
            this.hover = false;
            this.attachEventsListener();
            this.calculatePosition();
        }

        attachEventsListener() {
            window.addEventListener('mousemove', e => this.onMouseMove(e));
            window.addEventListener('resize', e => this.calculatePosition(e));
            // 添加scroll事件监听,滚动时重新计算元素位置
            window.addEventListener('scroll', e => this.calculatePosition(e));
        }

        calculatePosition() {
            gsap.set(this.el, {
                x: 0,
                y: 0,
                scale: 1
            });
          
            const box = this.el.getBoundingClientRect();
            this.x = box.left + (box.width * 0.5);
            this.y = box.top + (box.height * 0.5);
            this.width = box.width;
            this.height = box.height;
        }

        onMouseMove(e) {
            let hover = false;
            let hoverArea = (this.hover ? 0.7 : 0.5);
            let x = e.clientX - this.x;
            let y = e.clientY - this.y;
            let distance = Math.sqrt(x * x + y * y);
          
            if (distance < (this.width * hoverArea)) {
                hover = true;
                if (!this.hover) {
                    this.hover = true;
                }
                this.onHover(e.clientX, e.clientY);
            }

            if (!hover && this.hover) {
                this.onLeave();
                this.hover = false;
            }
        }

        onHover(x, y) {
            gsap.to(this.el, {
                x: (x - this.x) * 0.4,
                y: (y - this.y) * 0.4,
                scale: 1.15,
                ease: 'power2.out',
                duration: 0.4
            });
            this.el.style.zIndex = 10;
        }
        onLeave() {
            gsap.to(this.el, {
                x: 0,
                y: 0,
                scale: 1,
                ease: 'elastic.out(1.2, 0.4)',
                duration: 0.7
            });
            this.el.style.zIndex = 10;
        }
    }

    const btn1 = document.querySelector('.under-splash__item--left>div:first-child');
    new HoverButton(btn1);

    const btn2 = document.querySelector('.under-splash__item--right>div:first-child');
    new HoverButton(btn2);

    const btn3 = document.querySelector('.products__item--air-purification>img');
    new HoverButton(btn3);

    const btn4 = document.querySelector('.products__item--hvac-services>img');
    new HoverButton(btn4);
})();

额外优化建议

频繁的scroll事件会触发大量计算,可通过防抖函数优化性能,避免页面卡顿:

// 添加防抖工具函数
function debounce(func, delay = 100) {
    let timeoutId;
    return function(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func.apply(this, args), delay);
    };
}

// 在attachEventsListener中修改scroll监听
window.addEventListener('scroll', debounce(e => this.calculatePosition(e)));

内容的提问来源于stack exchange,提问作者dc89

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 10:15:34