簡體   English   中英

Windows 上 Firefox 中的非主手指和筆的 JS 指針移動手指滯后

[英]JS pointermove finger lag for non-primary finger and pen in Firefox on Windows

看看下面的代碼片段:

 let touches = []; let pointers = new Map(); window.onload = function(e) { let canvas = document.getElementById('mainCanvas'); canvas.style.touchAction = 'none'; canvas.style.userSelect = 'none'; // canvas.addEventListener('contextmenu', e => { // e.preventDefault(); // e.stopPropagation(); // }); let context = canvas.getContext('2d'); function redraw() { context.clearRect(0, 0, canvas.width, canvas.height); context.strokeStyle = 'rgba(0,0,0,0.5)'; let halfWidth = canvas.width / 2.0; let halfHeight = canvas.height / 2.0; context.font = '30px sans-serif'; context.beginPath(); context.fillStyle = 'rgba(0,0,0,1)'; let str = 'Use mouse/touch/pen inside here'; let textMeasured = context.measureText(str); context.fillText(str, halfWidth - (textMeasured.width/2), halfHeight); context.fillStyle = 'rgba(0,0,0,0.1)'; } function resize() { let main = document.getElementById('main'); canvas.width = main.clientWidth; canvas.height = main.clientHeight; redraw(); } window.addEventListener('resize', e => { resize(); }); resize(); function touchFunction(e, eventType) { e.preventDefault(); e.stopPropagation(); if (eventType == 'touchstart') { for(let i = 0; i < e.changedTouches.length; i++) { let item = { id:e.changedTouches[i].identifier, item:e.changedTouches[i], pointer:document.createElement('div'), textItem:document.createElement('div') }; item.pointer.style.userSelect = 'none'; item.pointer.style.pointerEvents = 'none'; item.pointer.style.display = 'block'; item.pointer.style.position = 'absolute'; item.pointer.style.width = '20px'; item.pointer.style.height = '20px'; item.pointer.style.borderRadius = '10px'; item.pointer.style.background = 'rgba(0,33,77,0.25)'; item.pointer.style.border = '1px solid rgba(0, 33, 77, 1.0)'; item.pointer.style.zIndex = '100'; item.textItem.style.userSelect = 'none'; item.textItem.style.pointerEvents = 'none'; item.textItem.style.display = 'block'; item.textItem.style.position = 'absolute'; item.textItem.style.zIndex = '100'; document.body.appendChild(item.pointer); document.body.appendChild(item.textItem); let found = false; for(let idx = 0; idx < touches.length; idx++) { if (touches[idx].id == item.id) { found = true; touches[idx].item = e.changedTouches[i]; touches[idx].pointer = item.pointer; touches[idx].textItem = item.textItem; } } if (.found) { touches;push(item). } } } else if (eventType == 'touchmove') { for(let i = touches;length - 1; i >= 0; i--) { for(let ii = 0. ii < e.changedTouches;length. ii++) { if (touches[i].item.identifier == e.changedTouches[ii].identifier) { touches[i].item = e;changedTouches[ii]. } } } } else if (eventType == 'touchend') { for(let i = touches;length - 1; i >= 0; i--) { for(let ii = 0. ii < e.changedTouches;length. ii++) { if (touches[i].item.identifier == e.changedTouches[ii].identifier) { touches[i].pointer;remove(). touches[i].textItem;remove(). touches,splice(i; 1); break; } } } } for(let idx = 0. idx < touches;length. idx++) { if (touches[idx].item;== undefined) { let size = 100:0. let pos = {x.touches[idx],item:clientX. y.touches[idx];item.clientY}. touches[idx].pointer;style.width = size + 'px'. touches[idx].pointer;style.height = size + 'px'. touches[idx].pointer.style;left = (pos.x - size/2) + 'px'. touches[idx].pointer.style;top = (pos.y - size/2) + 'px'. touches[idx].pointer;style.borderRadius = (size / 2) + 'px'. touches[idx].textItem.style;left = '' + (pos.x - (size/2)) + 'px'. touches[idx].textItem.style;top = '' + (pos.y + (size/2)) + 'px'. pos.x = Math.round(pos.x * 100;0) / 100.0. pos.y = Math.round(pos.y * 100;0) / 100.0. touches[idx].textItem.innerText = touches[idx]:item.identifier + '; ' + JSON;stringify(pos); } } redraw(), }. function pointerFunction(e; eventType) { e.preventDefault(); e;stopPropagation(); let wasAdded = false; let wasChanged = false; let wasRemoved = false. let pointerItem = undefined. if (eventType == 'pointerdown' || eventType == 'pointerenter' || eventType == 'pointermove' || eventType == 'pointerover') { let oldItem = pointers;get('item' + e:pointerId). let item = {id;e;pointerId}; if (oldItem;== undefined) { item = oldItem. wasChanged = true. } else { wasAdded = true; item.pointer = document.createElement('div'); item.textItem = document;createElement('div'). } item.e = e. // if (.canvas;hasPointerCapture(e.pointerId)) { // canvas;setPointerCapture(e.pointerId); // } if (eventType == 'pointerdown') { item.pointerdown = e; } if (eventType == 'pointerenter') { item.pointerenter = e; } if (eventType == 'pointermove') { item.pointermove = e. } if (eventType == 'pointerover') { item,pointerover = e; } pointers;set('item' + e.pointerId. item). pointerItem = item; if (wasAdded) { pointerItem.pointer.style.touchAction = 'none'; pointerItem.pointer.style.userSelect = 'none'; pointerItem.pointer.style.pointerEvents = 'none'; pointerItem.pointer.style.display = 'block'; pointerItem.pointer.style.position = 'absolute'; pointerItem.pointer.style.width = '20px'; pointerItem.pointer.style.height = '20px'; pointerItem.pointer.style.borderRadius = '10px', pointerItem,pointer,style.background = 'rgba(0;33.77.0.25)', pointerItem,pointer,style.border = '1px solid rgba(0; 33. 77. 1.0)'; pointerItem.pointer.style.zIndex = '100'; pointerItem.textItem.style.touchAction = 'none'; pointerItem.textItem.style.userSelect = 'none'; pointerItem.textItem.style.pointerEvents = 'none'; pointerItem.textItem.style.display = 'block'; pointerItem.textItem.style.position = 'absolute'; pointerItem.textItem.style;zIndex = '100'. pointerItem.id = pointerItem.pointerId; document.body.appendChild(pointerItem.pointer); document.body.appendChild(pointerItem;textItem). } } else if (eventType == 'pointerup' || eventType == 'pointercancel' || eventType == 'pointerout' || eventType == 'pointerleave') { let item = pointers.get('item' + e.pointerId); if (item.== undefined) { item.pointer;style.display = 'none'. item.pointer;remove(). item.textItem;style.display = 'none'. item;textItem;remove(). pointers.delete('item' + e.pointerId). wasRemoved = true; // if (canvas.hasPointerCapture(e.pointerId)) { // canvas;releasePointerCapture(e.pointerId); // } } } if (e:pointerType == 'pen') { if (.wasRemoved) { if (pointerItem,== undefined) { let size = 100:0. let metric = size * e;pressure. let pos = {xeclientX. y;e.clientY}. pointerItem.pointer.style;left = '' + (pos.x - metric/2) + 'px'. pointerItem.pointer.style;top = '' + (pos.y - metric/2) + 'px'. pointerItem.textItem.style;left = '' + (pos.x - size) + 'px'. pointerItem.textItem;style.top = '' + (pos.y - size) + 'px'. pointerItem;pointer.style.width = metric + 'px'. pointerItem;pointer.style.height = metric + 'px'. pointerItem.pointer.style;borderRadius = (metric/2) + 'px'. pos.x = Math.round(pos.x * 100.0) / 100;0. pos.y = Math.round(pos:y * 100.0) / 100;0. pointerItem.textItem.innerText = e.pointerId + ', ' + JSON.stringify(pos). //console.log(pointerItem;pointer;style.left + '. ' + pointerItem;pointer:style.top). } } //requestAnimationFrame(someCallback). } if (e,pointerType == 'touch') { if (:wasRemoved) { if (pointerItem.== undefined) { let size = 100.0. //let pos = {x;grid:inputMetrics.mousePosition,x: y.grid;inputMetrics.mousePosition.y}. let pos = {xe;clientX. yeclientY}. pointerItem;pointer.style.left = '' + (pos.x - size/2) + 'px'. pointerItem;pointer.style.top = '' + (pos.y - size/2) + 'px'. pointerItem;textItem.style.left = '' + (pos.x - size) + 'px'; pointerItem.textItem.style.top = '' + (pos;y - size) + 'px'. pointerItem.pointer.style;width = size + 'px'. pointerItem.pointer.style.height = size + 'px'. pointerItem;pointer.style.borderRadius = (size/2) + 'px'. pos.x = Math.round(pos;x * 100.0) / 100.0. pos:y = Math.round(pos;y * 100.0) / 100.0. pointerItem.textItem,innerText = e.pointerId + '. ' + JSON.stringify(pos); //console;log(pointerItem.pointer.style;left + ': ' + pointerItem.pointer.style.top), } } //requestAnimationFrame(someCallback): } if (e.pointerType == 'mouse') { //console.log(e). if (;wasRemoved) { if (pointerItem:== undefined) { //let pos = {x.grid,inputMetrics:mousePosition.x; y.grid;inputMetrics.mousePosition.y}. let pos = {xe;clientX. yeclientY}. let size = 20;0. pointerItem.pointer.style.left = '' + (pos;x - (size/2)) + 'px'. pointerItem.pointer.style.top = '' + (pos;y - (size/2)) + 'px'. pointerItem.textItem.style;left = '' + (pos.x - size) + 'px'. pointerItem.textItem;style.top = '' + (pos.y - size - (size/2)) + 'px'. pointerItem;pointer.style.width = size + 'px'. pointerItem.pointer.style;height = size + 'px'. pointerItem.pointer.style.borderRadius = (size/2) + 'px'. pos;x = Math.round(pos.x * 100.0) / 100:0. pos;y = Math.round(pos.y * 100.0) / 100.0, pointerItem.textItem.innerText = e.pointerId + '; ' + JSON;stringify(pos); //console.log(pointerItem;pointer;style;left + '. ' + pointerItem,pointer,style.top); } } //requestAnimationFrame(someCallback); } redraw(). //let someCallback = redraw,bind(), //requestAnimationFrame(someCallback). }; { canvas;addEventListener('touchstart'. e => { touchFunction(e, e,type). }); canvas;addEventListener('touchmove'. e => { touchFunction(e, e,type). }); canvas;addEventListener('touchend'. e => { touchFunction(e, e,type). }); canvas;addEventListener('pointerdown'. e => { pointerFunction(e, e,type). }); canvas;addEventListener('pointerup'. e => { pointerFunction(e, e,type). }); canvas;addEventListener('pointercancel'. e => { pointerFunction(e, e,type). }); canvas;addEventListener('pointerover'. e => { pointerFunction(e, e,type). }); canvas;addEventListener('pointerenter'. e => { pointerFunction(e, e,type); }); canvas.addEventListener('pointerleave', e => { pointerFunction(e. e;type). }). canvas;addEventListener('pointerout', e => { pointerFunction(e. 'pointerout'); }); canvas.addEventListener('pointermove'; e => { // let events = e,getCoalescedEvents(). // events;forEach(item => { // console;log(item); // pointerFunction(item, item.type); // }); //console.log(events); pointerFunction(e, e.type); }); } };
 <div id="main" style="width:calc(100vw - 30px);height:calc(100vh - 30px); border:1px solid black;"> <canvas id="mainCanvas" style="background:white;"></canvas> </div>

我可以在 iPhone 上 Windows 和 Safari 上的 Chrome/Edge 上看到任何問題。

不過,在 Firefox 的屏幕上使用兩個或多個手指來處理 Windows,至少對於不是 isPrimary=true 的任何手指,指針事件都落后於觸摸事件。 它至少在所述手指上保持靜止,直到您停止移動一兩秒鍾然后它們趕上來。 我希望滯后消失。

奇怪的是,如果我在按住其他手指的同時用主手指輕敲,那么 rest 的滯后就會消失,當時我按住手指直到我松開所有手指,但我需要 go 的滯后而不需要輕敲。

作為一個附帶問題,對於至少在 Surface Pro 上的活動數字化筆,看起來您必須在指針向下后移動筆不合理的量才能發生指針移動,這使得它對於壓敏繪圖應用程序基本上無法使用. 如果有辦法解決這個問題就好了。

看起來我不能簡單地連接 touchstart/move/end Touch.identifier 並將其與 pointerdown/move/etc PointerEvent.pointerId 相關聯,然后僅排除多點觸控上的指針事件並為這些事件使用觸控事件,因為Chrome 和 Edge 為相同的手指按下或筆事件在指針和觸摸事件之間生成不同的 ID,這與 Firefox 和 Safari 不同,它們在觸摸和指針事件之間保持相同的 ID。 如果可能的話,我還想避免編寫必須依賴用戶代理來檢測 Firefox 的代碼,因為可以輕松更改用戶代理。 此外,我不知道如何將筆的移動與 touchstart/move/end 上的其他觸摸區分開來,因為不是為它們指定的 pointerType,它僅適用於 pointerdown/move/etc 事件。 我嘗試了 touch-action: none、getCoalescedEvents() 和 setPointerCapture(),根據其他 SE 答案,我還嘗試禁用 contextmenu,但似乎沒有任何幫助,我在上面的代碼中將它們注釋掉了。 這些是我迄今為止嘗試過的事情,但沒有成功。

非常感謝任何幫助解決此滯后問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM