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

如何基于时间间隔实现用户按键控制的网页图片平滑移动效果

问题根源
  • 代码逻辑错误:setInterval的第一个参数传入了addEventListener的返回值,等于每100毫秒就重复注册一次keydown事件监听器,最终会有几百个重复的监听器同时执行,不仅卡顿还会造成性能泄漏
  • 依赖keydown事件触发位移:系统原生的keydown事件有默认的首触发延迟,按住按键后会先等几百毫秒才会连续触发,这是卡顿的核心原因
  • 没有使用浏览器原生的帧动画API:setInterval的计时精度低,而且不会和浏览器的渲染节奏对齐,容易出现掉帧
修复方案

核心逻辑是:用keydown和keyup事件记录当前按键状态,再用requestAnimationFrame(和浏览器渲染帧对齐的API)每帧更新位移,即可实现丝滑的移动效果。

修复后完整代码:

<!DOCTYPE html>
<html>
    <head>
        <style>
            #avaOne {position: absolute; left: 0px; width: 50px;}
        </style>
    </head>
    <body>
        <img id="avaOne" src="avaOne.png"/>
    </body>
    <script>
        var xPos = 300;
        // 按键状态标记,记录当前是否按住左右键
        var isLeftPressed = false;
        var isRightPressed = false;
        // 移动速度:每帧移动的像素值,数值越大移动越快
        var moveSpeed = 2;

        // 监听按键按下,更新状态
        window.addEventListener("keydown", function(event) {
            if (event.keyCode == 37) {
                isLeftPressed = true;
            } else if (event.keyCode == 39) {
                isRightPressed = true;
            }
        });

        // 监听按键松开,更新状态
        window.addEventListener("keyup", function(event) {
            if (event.keyCode == 37) {
                isLeftPressed = false;
            } else if (event.keyCode == 39) {
                isRightPressed = false;
            }
        });

        // 帧更新函数,和浏览器渲染节奏对齐,每秒执行约60次
        function updatePosition() {
            if (isLeftPressed) {
                xPos -= moveSpeed;
            }
            if (isRightPressed) {
                xPos += moveSpeed;
            }
            document.getElementById("avaOne").style.left = xPos + "px";
            // 递归调用,持续更新
            requestAnimationFrame(updatePosition);
        }

        // 启动帧更新
        requestAnimationFrame(updatePosition);
    </script>
</html>
额外优化建议

如果要进一步提升流畅度,可以把修改left属性改成修改transform,不会触发页面重排,性能更高:

// 把原来的style.left赋值换成下面的代码
document.getElementById("avaOne").style.transform = `translateX(${xPos}px)`;
// 对应的css里可以删掉left:0px的初始值,xPos初始值对应位移距离即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:45:00