为什么当touchstart事件触发时setTimeout游戏循环会出现延迟

Why is setTimeout game loop experiencing lag when touchstart event fires?

本文关键字:循环 游戏 延迟 setTimeout touchstart 事件 为什么      更新时间:2023-09-26

这是我遇到的一个相当具体的问题。这个故障似乎只出现在最新的Android版Chrome中,所以这里是规格:

应用程序版本:Chrome 45.0.2454.84

操作系统:Android 4.4.4;XT1031构建/KXB21.14-L2.4

我用的是Moto G,但运行同一版本Chrome的三星手机也出现了这个问题。无论如何,问题显然是touchstart事件打断了我的window.setTimeout游戏循环。下面是代码:

(
    function rafTouchGlitch() {
        /////////////////
        /* FUNCTIONS. */
        ///////////////
        function touchStartWindow(event_) {
            event_.preventDefault();
        }
        ///////////////////////
        /* OBJECT LITERALS. */
        /////////////////////
        var engine = {
            /* FUNCTIONS. */
            start : function(interval_) {
                var handle = this;
                (function update() {
                    handle.timeout = window.setTimeout(update, interval_);
                    /* Draw the background and the red square. */
                    display.fillStyle = "#303030";
                    display.fillRect(0, 0, display.canvas.width, display.canvas.height);
                    display.fillStyle = "#f00000";
                    display.fillRect(red_square.x, red_square.y, 20, 20);
                    /* Update the square's position. */
                    red_square.x++;
                    if (red_square.x > display.canvas.width) {
                        red_square.x = -20;
                    }
                })();
            },
            /* VARIABLES. */
            timeout : undefined
        };
        red_square = {
            /* VARIABLES. */
            x : 0,
            y : 0
        };
        /////////////////
        /* VARIABLES. */
        ///////////////
        var display = document.getElementById("canvas").getContext("2d");
        //////////////////
        /* INITIALIZE. */
        ////////////////
        window.addEventListener("touchstart", touchStartWindow);
        engine.start(1000 / 60);
    })();

这段代码在任何其他浏览器中都可以正常工作,甚至在以前版本的Chrome中。它在上一个版本中工作得很好,但由于某种原因,现在有一个问题。我不确定这是否是Chrome端的一个bug,或者如果他们正在做一些新的事情,我是一个没有覆盖我的基础,但事实仍然是,当touchstart事件发生时,我的游戏循环中有一个明显的滞后。

这里有一个小提琴:https://jsfiddle.net/dhjsqqxn/

点击屏幕,看看红色方块是如何滞后的!这是荒谬的。你可以通过快速点击屏幕来冻结Timeout对象。

如果你用的是安卓手机,我强烈建议你升级Chrome浏览器,并访问链接来了解我的意思。如果这是一个漏洞,那也是一个巨大的漏洞,考虑到setTimeout的价值和touchstart在移动设备上的重要性。如果不是bug,我真的很想知道我做错了什么。

谢谢你的时间!

参见https://bugs.chromium.org/p/chromium/issues/detail?id=567800

Android Chrome在touchmove期间不运行预定的(setTimeout/setInterval)回调。

作为一种解决方法,你可以尝试window.requestAnimationFrame()或在touchmove事件中手动运行回调,这将需要保留/检查最后运行时间

在touchstart函数结束时执行"return false;"

为滑动下面的jquery没有jquerymobile..

$("#id").on({'touchstart' : functionforstart, 'touchmove' :onmove, 'touchend' : functionforend});
functionforstart(e){ e.originalEvent.touches[0].pageX usw.. return false;}
function onmove(e){lastMove=e}
function functionforend(){lastMove.originalEvent.touches[0].pageX} usw..    e.prefentDefault(); }

这对我来说很有用。var lastMove必须是全局的,你需要一个touchmove步骤来获得touchend的位置。希望这也是你所需要的。