为什么setTimeout游戏循环在touchstart事件触发时遇到延迟?

时间:2015-09-07 22:20:47

标签: javascript android google-chrome debugging game-loop

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

应用版本: Chrome 45.0.2454.84

操作系统: Android 4.4.4; XT1031 Build / 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上的错误,还是他们正在做一些新的事情而且我不是我的基础,但事实仍然是我的游戏循环中存在明显的滞后{{1}事件火灾。

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

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

如果您有Android手机,我建议您更新Chrome并访问该链接以查看我的意思。如果这是一个很大的错误,那么考虑到touchstart的价值以及移动设备setTimeout的重要程度。如果它不是一个bug,我真的很想知道我做错了什么。

感谢您的时间!

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:1)

“返回假”;在touchstart功能结束时。

用于在不使用jquerymobile的情况下滑动以下jquery ..

$("#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中的位置..希望这也是你需要的......