简体   繁体   English

如何防止IE11和Microsoft Edge积极地限制事件?

[英]How to prevent IE11 and Microsoft Edge from throttling events aggressively?

Background 背景

I have a pannable app window which works by listening for mousemove events and then using transform: translate3d(...) to move the screen accordingly. 我有一个pannable应用程序窗口,通过监听mousemove事件然后使用transform: translate3d(...)来相应地移动屏幕。 It's a large app and there is considerable UI work associated to facilitate this functionality. 它是一个大型应用程序,并且有相当多的UI工作可以促进此功能。 Here comes the MCVE, in which the real workload is mocked by a dummy for loop: 这是MCVE,其中真正的工作负载被虚拟for循环模拟:

 var container = document.getElementById("container"); var contents = document.getElementById("contents"); var input = document.getElementById("iterations"); var posX = 50; var posY = 50; var previousX = null; var previousY = null; var mousedownHandler = function (e) { window.onmousemove = globalMousemoveHandler; window.onmouseup = globalMouseupHandler; previousX = e.clientX; previousY = e.clientY; } var globalMousemoveHandler = function (e) { var now = Date.now(); for (var i = 0, n = parseInt(input.value); i < n; i++); var elapsed = Date.now() - now; posX += e.clientX - previousX; posY += e.clientY - previousY; previousX = e.clientX; previousY = e.clientY; contents.style.transform = "translate3d(" + posX + "px, " + posY + "px, 0)"; contents.innerText = elapsed + "ms"; } var globalMouseupHandler = function (e) { window.onmousemove = null; window.onmouseup = null; previousX = null; previousY = null; } container.onmousedown = mousedownHandler; contents.style.transform = "translate3d(" + posX + "px, " + posY + "px, 0)"; 
 #container { height: 180px; width: 600px; background-color: #ccc; overflow: hidden; cursor: -webkit-grab; cursor: -moz-grab; cursor: grab; -moz-user-select: none; -ms-user-select: none; -webkit-user-select: none; user-select: none; } #container:active { cursor: move; cursor: -webkit-grabbing; cursor: -moz-grabbing; cursor: grabbing; } 
 <label>Iterations: <input id="iterations" type="number" value="20000000" step="5000000" /></label> <div id="container"> <div id="contents"> Pannable container contents... </div> </div> 

JSFiddle example with larger drag-area JSFiddle示例具有更大的拖动区域

Please hold and drag the example. 请按住并拖动示例。

This rudimentary snippet runs a dummy for loop every time mousemove fires, and the duration it takes for the loop to complete is displayed in the draggable container. 每次mousemove触发时,这个基本片段都会运行一个虚拟for循环,并且循环完成所需的持续时间将显示在可拖动容器中。 This is needed to demonstrate the problem below. 这需要证明下面的问题。 You may need to adjust the number of iterations, so that the loop takes somewhere above 10ms to run, but not much longer. 您可能需要调整迭代次数,以便循环运行时间超过10ms,但不会太长。

Problem 问题

This snippet runs as fast as possible in Google Chrome, no problems there. 此代码段在Google Chrome中尽可能快地运行,没有任何问题。 Untested in Firefox. 在Firefox中未经测试。

However, in Microsoft Edge (and presumably, IE11 as well) if globalMousemoveHandler runs for longer than about 10ms, the browser starts throttling the event mercillesly, making it fire much less frequently, and obliterating the panning progress down to a crawl. 但是,在Microsoft Edge (也可能是IE11)中,如果globalMousemoveHandler运行时间超过10毫秒,则浏览器会开始重新限制事件,使其频繁发生火灾,并消除平移进度到爬行状态。

Also quite strange is that the for loop actually runs faster in Microsoft Edge than in Chrome (almost 50% faster), but the event still fires much less frequently. 同样奇怪的是, for循环实际上在Microsoft Edge中运行速度比在Chrome中快得多(几乎快50%),但事件的发生频率仍然得多。

This is observable in the above snippet when viewed from the mentioned browsers. 当从上述浏览器中查看时,在上面的片段中可以观察到这一点。 Now I understand the theoretical desire behind this functionality, but it renders my application unusable on these browsers -- I also don't really understand what's the point for the throttling to kick in below 16ms (I'm well under the 60 FPS frame budget) , but that's besides the question now (although I'd be glad to hear some details about this) . 现在我理解了这个功能背后的理论愿望,但是它使我的应用程序在这些浏览器上无法使用 - 我也不太明白在16ms以下限制的重点是什么(我在60 FPS帧预算之下) ,但现在除了问题之外(虽然我很高兴听到一些关于此的细节)

How can I prevent this from happening? 我怎样才能防止这种情况发生?

Here is an example that uses requestAnimationFrame . 这是一个使用requestAnimationFrame的示例。

 var container = document.getElementById("container"); var contents = document.getElementById("contents"); var input = document.getElementById("iterations"); var posX = 50; var posY = 50; var previousX = null; var previousY = null; var mousedownHandler = function (e) { window.onmousemove = globalMousemoveHandler; window.onmouseup = globalMouseupHandler; previousX = e.clientX; previousY = e.clientY; } var globalMousemoveHandler = function (e) { posX += e.clientX - previousX; posY += e.clientY - previousY; previousX = e.clientX; previousY = e.clientY; window.requestAnimationFrame(function () { var now = Date.now(); for (var i = 0, n = parseInt(input.value); i < n; i++); var elapsed = Date.now() - now; contents.style.transform = "translate3d(" + posX + "px, " + posY + "px, 0)"; contents.innerText = elapsed + "ms"; }); } var globalMouseupHandler = function (e) { window.onmousemove = null; window.onmouseup = null; previousX = null; previousY = null; } container.onmousedown = mousedownHandler; contents.style.transform = "translate3d(" + posX + "px, " + posY + "px, 0)"; 
 #container { height: 180px; width: 600px; background-color: #ccc; overflow: hidden; cursor: -webkit-grab; cursor: -moz-grab; cursor: grab; -moz-user-select: none; -ms-user-select: none; -webkit-user-select: none; user-select: none; } #container:active { cursor: move; cursor: -webkit-grabbing; cursor: -moz-grabbing; cursor: grabbing; } 
 <label>Iterations: <input id="iterations" type="number" value="20000000" step="5000000" /></label> <div id="container"> <div id="contents"> Pannable container contents... </div> </div> 

This stops the heavy lifting from blocking the handler function, effectively preventing the issue from happening, at the cost of a 16ms increased latency. 这可以阻止繁重的阻止处理程序功能,有效地防止问题的发生,代价是延迟增加16ms。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM