如何最小化触摸移动主线程的等待时间

How to minimise waiting for main thread for touchmove

我的任务是在html页面中拖动一个div,并尽可能快地完成,因为目标平台是移动平台(chrome android) 但我发现它在 chrome (android) 上有点滞后,所以我开始分析应用程序,发现我的触摸事件在华为 p8 上等待主线程大约 10 毫秒。

我的问题是我怎么能把这个时间减到最少,还没找到任何解决办法,看来是不可能的。

这是一个示例 jsfiddle (https://jsfiddle.net/bbvarga/p94btq6e/):

js 部分:

document.addEventListener('touchmove', function(e) {
  e.preventDefault();
})

var box = document.getElementById('box');
var x = 0;
var y = 0;
var px = 0;
var py = 0;
var handler = null;


function paint() {
  box.style.setProperty(
    'transform', 
    `translate3d(${px}0px, ${py}px, 0px)`, 
    'important'
  );
  handler = null;
}

box.addEventListener('touchstart', function(e) {
  console.log('ts');
  x = e.touches[0].pageX;
  y = e.touches[0].pageY;
});

box.addEventListener('touchend', function() {
  console.log('te');
  if (handler) {
    window.cancelAnimationFrame(handler);
    handler = null;
  }
});

box.addEventListener('touchmove', function(e) {
  console.log('tm');
  px = e.touches[0].pageX;
  py = e.touches[0].pageY;
  if (!handler) {
    window.requestAnimationFrame(paint);
  }
});

html:

<div id="container">
  <div id="wrapper">
    <div id="box">
    </div>  
  </div>
</div>

css:

#container {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  color: #efefef;
}
#wrapper {
  width: 100%;
  height: 100%;
  position: relative;
}
#box {
  position: absolute;
  background-color: green;
  width: 100px;
  height: 100px;
}

这是时间线的截图,可以看到Touch Move事件下面的红线很长(那是浏览器在等待主线程的时候,也在Touch Move事件的总结下,您可以在所附屏幕截图的底部看到)。真正的工作,重新计算风格,绘画,排版比等待时间更快。

现在这个简约示例中的帧率是可以接受的,但我觉得如果我有图像,以及其他内容div,一些计算,这些长触摸移动事件会降低我的帧率。

如果你想达到 60fps,你每帧只有 ~17ms,如果等待是 ~10,你只有 7ms 来完成真正的工作。 :(

注意:移动版safari速度很快,感觉不到延迟。

大约10ms的等待是从输入事件进来到主线程在生成下一帧时将其拾取的时间。从 那个 开始,你有大约 16 毫秒的帧预算

您看到的是输入延迟。它不会影响效果的流畅性(您的 JS 处理程序完全在预算之内),但会增加约 1 帧的延迟(因此盒子不会完全粘在手指上)。发生这种情况是因为 OS 将输入事件传递给浏览器进程。然后它被发送到包含您的页面的呈现器进程。从那里开始,它在主线程上排队,但在主线程准备好生成新帧之前不会被拾取(并且每一步都有一些排队)。一旦帧被推送到 GPU,时间轴中的触摸移动就会结束。

不幸的是,其中大部分并不真正在您的控制之下,但只要您的主线程未饱和,它应该相对恒定。