標籤:
移動端最高頻耗記憶體的的操作 莫屬 touchmove 與scroll事件 兩者需要 微觀的 最佳化;
這裡 我們 講述 touchmove;touchmove 事件發生很頻繁,會比螢幕重新整理率快,導致無效的渲染和重繪;
幀數 –顯示裝置通常的重新整理率通常是50~60Hz –1000ms / 60 ≈ 16.6ms(1毫秒的最佳化意味著 6%的效能提升)
瀏覽器對每一幀畫面的渲染工作需要在16毫秒(1秒 / 60 = 16.66毫秒)之內完成 ;如果超過了這個時間限度,頁面的渲染就會出現卡頓效果,也就是常說的jank;我們需要在 正確的時間 做正確的渲染;
拖拽的都會寫,先看看效果;
大概瞭解一下 Timeline 查看看渲染情況 舊版如下
在看看 幀模式 渲染情況;
那些沒必要的 move 什麼也不需要做;沒必要在16.6毫秒內多餘的event對象計算;
關於幀模式:
附上原始碼:
1 function drag(element){ 2 3 var startX=0, 4 startY=0, 5 ticking=false, 6 raf, 7 doc=document; 8 9 element.addEventListener("touchstart",function(e){10 11 12 var e=e||window.event,13 touchs = e.touches[0];14 e.preventDefault(); //低端安卓 touch事件 有的導致touchend事件時效 必須開始 就加 e.preventDefault();15 // text a ipnut textarea 幾個 等標籤除外 16 // ,另外自訂移動端touchstart touchend組合的 hover事件,建議不加這個,不然頁面無法滾動17 //touchmove 開始 就加 不然抖動一下,才能touchmove, 然後才正常 尤其早些的 三星 系列內建瀏覽器18 19 20 startX=parseInt(touchs.pageX-(element.lefts||0));21 startY=parseInt(touchs.pageY-(element.tops||0));22 23 doc.addEventListener("touchmove",update,false);24 doc.addEventListener("touchend",end,false);25 26 },false);27 28 29 30 31 32 var update=function (e) {33 34 var e=e||window.event;35 if (e.touches.length > 1 || e.scale && e.scale !== 1) return;36 e.preventDefault();37 38 //cancelAnimationFrame(raf);39 if(!ticking) {40 41 var touchs = e.changedTouches[0];42 43 //1先觸摸移動 44 element.lefts = touchs.pageX - startX;45 element.tops = touchs.pageY - startY;46 47 //2交給requestAnimationFrame 更新位置48 //raf=requestAnimationFrame(function(){draw();});49 raf=requestAnimationFrame(draw);50 51 }52 53 ticking = true;54 };55 56 57 58 59 var draw= function (){ 60 ticking = false;61 var nowLeft=parseInt(element.lefts); //滑動的距離 touchmove時候,如果加阻力,可能有細小的抖動;我想應該是移動端 部分支援0.5px的緣故; parseInt的轉化有點牽強;62 var nowTop=parseInt (element.tops); //滑動的距離 63 64 element.style.webkitTransform=element.style.transform = "translate3D(" + nowLeft + "px," + nowTop + "px,0px)";65 66 };67 68 var end=function(){69 var endLeft= parseInt(element.lefts); //滑動的距離 70 var endTop= parseInt(element.tops); //滑動的距離71 72 //element.style.webkitTransform=element.style.transform = "translate(" + endLeft+ "px," + endTop + "px)"; 73 74 doc.removeEventListener("touchmove",update,false);75 doc.removeEventListener("touchend",end,false);76 // cancelAnimationFrame(raf);77 78 }79 80 };81 注意點:RequestAnimationFrame的相容
;(function(){var lastTime=0;var vendors=["ms","moz","webkit","o"];for(var x=0;x<vendors.length&&!window.requestAnimationFrame;++x){window.requestAnimationFrame=window[vendors[x]+"RequestAnimationFrame"];window.cancelAnimationFrame=window[vendors[x]+"CancelAnimationFrame"]||window[vendors[x]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame){window.requestAnimationFrame=function(callback,element){var currTime=new Date().getTime();var timeToCall=Math.max(0,16-(currTime-lastTime));var id=window.setTimeout(function(){callback(currTime+timeToCall)},timeToCall);lastTime=currTime+timeToCall;return id}}if(!window.cancelAnimationFrame){window.cancelAnimationFrame=function(id){clearTimeout(id)}}}());RequestAnimationFrame的簡易動畫庫 requestAnimationFrame 節流函數
var rafThrottle=function(fn){ //touchmove scroll節流 var ticking=false; var update=function () { ticking = false; fn&&fn.apply(this,arguments); } function requestTick() { if(!ticking) { requestAnimationFrame(update); } ticking = true; } requestTick();};
參考網站:
Google開發人員,非常專業:https://developers.google.com/web/fundamentals/getting-started/?hl=zh-cn 需要FQ;
Web前端效能最佳化的微觀分析 http://velocity.oreilly.com.cn/2013/ppts/16_ms_optimization--web_front-end_performance_optimization.pdf
移動端效能調優:ttps://speakerdeck.com/baofen14787/yi-dong-duan-xing-neng-diao-you-ji-16msyou-hua
總結:做的東西多了,得 整理一下以;
移動端 scroll,touchmove的事件用的還是比較多的;有時間還是要 細細最佳化的;雖然感覺很微觀 ,甚至覺得 最佳化的幾乎看不出來;但是你去最佳化好,還是費不少時間 的;
requestAnimationFrame是個移動端的利器;動畫盡量用它或者除集合css3實現;
移動端 touchmove高頻事件與requestAnimationFrame的結合最佳化