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

使用window.requestAnimationFrame迁移jQuery横向滚动代码遇向左滚动失效问题

问题分析与修复方案

核心问题

你的原生JS代码仅向右滚动有效,向左滚动失效的原因是滚动终止条件判断错误:

  • 向右滚动时,目标位置endLocation大于起始位置startLocation,window.pageXOffset <= endLocation的条件能正常触发动画循环;
  • 向左滚动时,endLocation小于startLocation,初始的window.pageXOffset(起始位置)就不满足<= endLocation,导致动画只执行一次就停止。

另外还有两个细节问题:

  1. 原代码仅给第一个匹配的图片绑定了点击事件,和jQuery版本的“所有图片绑定”逻辑不一致;
  2. 基于固定步数的增量计算不够稳定,不同设备上的动画时长会有差异。

修复后的代码

下面是兼容左右滚动、匹配jQuery原逻辑、动画时长稳定的原生JS实现:

// 给所有匹配的图片绑定点击事件
document.querySelectorAll('.page-template-format-horizontal .exhibit-image').forEach(img => {
    img.addEventListener('click', function (e) {
        // 计算目标滚动位置,和jQuery逻辑一致
        const slideWidth = e.currentTarget.getBoundingClientRect().width;
        const windowWidth = window.innerWidth;
        const scrollTo = e.currentTarget.offsetLeft;
        const targetOffset = scrollTo - (windowWidth / 2) + (slideWidth / 2);

        const duration = 500; // 和jQuery一致的500ms动画时长
        const startX = window.pageXOffset;
        const distance = targetOffset - startX;
        const startTime = performance.now();

        // 基于时间驱动的动画步骤,保证时长稳定
        function animateScroll(currentTime) {
            const elapsed = currentTime - startTime;
            // 计算动画进度(0到1),这里用线性缓动,可替换为其他缓动函数
            const progress = Math.min(elapsed / duration, 1);
            // 计算当前需要滚动到的位置
            const currentX = startX + distance * progress;
            
            window.scrollTo(currentX, window.pageYOffset);
            
            // 进度未到1则继续执行动画
            if (progress < 1) {
                window.requestAnimationFrame(animateScroll);
            }
        }

        window.requestAnimationFrame(animateScroll);
        e.preventDefault();
    });
});

关键改进点

  1. 滚动条件修复:用progress < 1作为循环终止条件,不管滚动方向都能正常触发动画;
  2. 批量绑定事件:使用querySelectorAll遍历所有图片,和jQuery的事件绑定逻辑对齐;
  3. 时间驱动动画:通过performance.now()计算动画进度,保证在不同设备上都能稳定维持500ms的动画时长;
  4. 可扩展缓动:如果需要更自然的滚动效果,可以替换progress的计算逻辑,比如使用ease-in-out缓动:
    // ease-in-out缓动函数
    const progress = elapsed / duration;
    const easedProgress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:00:34