如何最小化触摸移动主线程的等待时间
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,时间轴中的触摸移动就会结束。
不幸的是,其中大部分并不真正在您的控制之下,但只要您的主线程未饱和,它应该相对恒定。
我的任务是在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,时间轴中的触摸移动就会结束。
不幸的是,其中大部分并不真正在您的控制之下,但只要您的主线程未饱和,它应该相对恒定。