requestAnimationFrame節流,優化scroll和touchmove事件
阿新 • • 發佈:2020-08-07
touchmove和scroll事件發生很頻繁, 會比螢幕重新整理率快, 導致無效的渲染和重繪。
可以使用requestAnimationFrame來優化滾動處理, 在一幀中只進行一次重繪。
1. onScroll用requestAnimationFrame來優化
1. onScroll用requestAnimationFrame來優化
// rAF觸發鎖,必須加鎖,多次呼叫raf,會在一幀中多次觸發回撥 var ticking = false; function onScroll(){ if(!ticking) { requestAnimationFrame(realFunc); ticking = true; } } function realFunc(){ // do something... console.log("Success"); ticking = false; } // 滾動事件監聽2. 封裝一個raf的動畫函式window.addEventListener('scroll', onScroll, false);
var lock = {}; function animationFrame (callback = (time) => {}, key = 'default') { if (lock[key]) { return false } lock[key] = true window.requestAnimationFrame((time) => { lock[key] = false callback(time) })3. 封裝一個raf的throttle方法return true } // 呼叫 window.addEventListener('scroll', () => { animationFrame((time) => doAnimation(time)) })
var rafThrottle = function(fn) { var ticking = false; var update = function() { ticking = false; fn && fn.apply(this, arguments); }4. touchmove用requestAnimationFrame優化,一幀只執行一次計算function requestTick() { if (!ticking) { requestAnimationFrame(update); } ticking = true; } requestTick(); }
function drag(element) { var startX = 0, startY = 0, ticking = false, raf, doc = document; element.addEventListener("touchstart", function(e) { var e = e || window.event, touchs = e.touches[0]; e.preventDefault(); //低端安卓touch事件有的導致touchend事件時效,必須開始就加 e.preventDefault(); startX = parseInt(touchs.pageX - (element.lefts || 0)); startY = parseInt(touchs.pageY - (element.tops || 0)); doc.addEventListener("touchmove", update, false); doc.addEventListener("touchend", end, false); }, false); var update = function(e) { var e = e || window.event; if (e.touches.length > 1 || e.scale && e.scale !== 1) return; e.preventDefault(); if (!ticking) { var touchs = e.changedTouches[0]; //1先觸控移動 element.lefts = touchs.pageX - startX; element.tops = touchs.pageY - startY; //2交給requestAnimationFrame 更新位置 raf = requestAnimationFrame(draw); } ticking = true; }; var draw = function() { ticking = false; var nowLeft = parseInt(element.lefts); //滑動的距離touchmove時候,如果加阻力,可能有細小的抖動;我想應該是移動端 部分支援0.5px的緣故;parseInt的轉化有點牽強; var nowTop = parseInt(element.tops); //滑動的距離 element.style.webkitTransform = element.style.transform = "translate3D(" + nowLeft + "px," + nowTop + "px,0px)"; }; var end = function() { var endLeft = parseInt(element.lefts); //滑動的距離 var endTop = parseInt(element.tops); //滑動的距離 doc.removeEventListener("touchmove", update, false); doc.removeEventListener("touchend", end, false); } }參考:https://cloud.tencent.com/developer/article/1613039 https://www.cnblogs.com/coco1s/p/5499469.html http://www.mamicode.com/info-detail-1256974.html