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

touchstart事件导致Canvas游戏卡顿的原因及纯JS解决方案

解决触屏事件导致Canvas动画卡顿的问题

导致卡顿的核心原因有两个:

  • 使用setInterval驱动动画,它的执行时机不与浏览器渲染帧同步,容易出现丢帧和卡顿;
  • 触屏事件会触发浏览器默认行为(如页面滚动、触摸缩放),这些操作会抢占主线程资源,打断动画执行。

以下是修复后的纯JavaScript实现,同时优化了动画流畅性:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <!-- 添加viewport元标签,确保触屏设备页面显示正常 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
</head>
<body>
    <canvas id="cnvs" width="400" height="400"></canvas>

    <script>
        var canvas, canvasContext;
        var x = 0, y = 30;
        var speed = 300; // 每秒移动300像素
        var lastTimestamp = 0;

        window.onload = function() {
            canvas = document.getElementById('cnvs');
            canvasContext = canvas.getContext('2d');

            // 启动浏览器优化的动画循环
            requestAnimationFrame(updateAll);

            canvas.addEventListener('touchstart', touchStart);
            canvas.addEventListener('touchend', touchEnd);
        }

        function touchStart(e) {
            e.preventDefault(); // 阻止浏览器默认触屏行为,避免抢占资源
            console.log(e);
        }

        function touchEnd(e) {
            e.preventDefault(); // 阻止浏览器默认触屏行为
            console.log(e);
        }

        function colorRect(x, y, width, height, color) {
            canvasContext.fillStyle = color;
            canvasContext.fillRect(x, y, width, height);
        }

        function updateAll(timestamp) {
            // 计算时间差,实现基于时间的动画增量,保证不同设备速度一致
            const deltaTime = (timestamp - lastTimestamp) / 1000;
            lastTimestamp = timestamp;

            moveAll(deltaTime);
            drawAll();

            // 持续调度下一帧动画
            requestAnimationFrame(updateAll);
        }

        function moveAll(deltaTime) {
            x += speed * deltaTime;

            if(x > canvas.width - 20 || x < 0) {
                speed = -speed;
            }
        }

        function drawAll() {
            colorRect(0, 0, canvas.width, canvas.height, 'black');
            colorRect(x, y, 20, 20, 'red');
        }
    </script>
</body>
</html>

关键优化点说明:

  • 替换setInterval为requestAnimationFrame:该API由浏览器调度,与屏幕刷新频率同步,能最大程度避免丢帧;
  • 阻止触屏默认行为:通过e.preventDefault()禁用触摸滚动、缩放等操作,防止这些行为抢占主线程打断动画;
  • 基于时间的动画增量:不再用固定步长移动,而是根据帧间隔计算移动距离,确保动画速度在不同帧率设备上一致;
  • 添加viewport元标签:禁用用户缩放,避免额外浏览器行为干扰动画。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:05:10