loading動畫的效能優化-摒棄Canvas,擁抱CSS3-實現點選特效

專案中有個活動頁載入時有個loading動畫,效果如上圖,連續綻放小球,問題就是太卡,經常出現一堆小球抱團卡住,遂進行優化
注意:(僅在頁面載入時卡頓,載入完畢,點選的時候不卡頓)
檢視程式碼發現改動畫時借用的animejs 官網中的效果,通過canvas實現的,按理說canvas應該時效能很好的,不應該出現卡頓,問題在我的活動頁中就是非常卡頓
思考再三,把最終原因歸結於首頁載入時候,瀏覽器要載入資源,渲染dom,耗費cpu,而canvas做幀動畫會做大量的計算,這對cpu肯定是一種消耗,給瀏覽器造成一定壓力,個人見解,不一定準確
我的解決辦法是砍掉canvas,藉助CSS3並觸發硬體加速,只在建立小球的時候做一次運算,幀動畫通過transform集合transition實現,這樣可以大大減少js的運算,下面是核心程式碼實現,通過外掛封裝的方式上傳到github ofollow,noindex">click-colorful ,全部程式碼不到100行,剛興趣可以看一下,覺得可以就star一下,算是鼓勵
定義預設引數
var defaultParams = { colors: ['#eb125f', '#6eff8a', '#6386ff', '#f9f383'], size: 30, maxCount: 30 } 複製程式碼
小球的顏色,大小,數量都可以隨意配置,非常靈活
建構函式
function colorBall(params) { if (params && params.colors) { this.colors = params.colors; } if (params && params.size) { this.size = params.size; } if (params && params.maxCount) { this.size = params.maxCount; } } 複製程式碼
引數的賦值
綻放函式
colorBall.prototype.fly = function (x, y, playCount, loopTimer) { if (playCount === -1) return var ballElements = [] var fragment = document.createDocumentFragment() for(var i=0; i<this.maxCount; i++) { var ball = doc.createElement('i'); ball.className = 'color-ball'; var blurX = Math.random() * 10 if (Math.random() > 0.5) blurX = blurX* -1 var blurY = Math.random() * 10 if (Math.random() > 0.5) blurY = blurY* -1 ball.style.left = (x + blurX) + 'px'; ball.style.top = (y + blurY) + 'px'; ball.style.width = this.size + 'px'; ball.style.height = this.size + 'px'; ball.style.position = 'fixed'; ball.style.borderRadius = '1000px'; ball.style.boxSizing = 'border-box'; ball.style.zIndex = 9999; ball.style.transform = 'translate3d(0px, 0px, 0px) scale(1)'; ball.style.webkitTransform = 'translate3d(0px, 0px, 0px) scale(1)'; ball.style.transition = 'transform 1s ease-out'; ball.style.webkitTransition = 'transform 1s ease-out'; ball.style.backgroundColor = getOneRandom(this.colors); fragment.appendChild(ball); ballElements.push(ball) } doc.body.appendChild(fragment); // 執行動畫 setTimeout(function () { for(var i=0; i<ballElements.length; i++){ _run(ballElements[i]) } }, 10) // 清空dom setTimeout(function () { for(var i=0; i<ballElements.length; i++){ doc.body.removeChild(ballElements[i]) } }, 1500) // 多次播放 if (playCount > 0) { var self = this setTimeout (function () { var last = playCount - 1 self.fly(x, y, last, loopTimer) }, loopTimer) } } //隨機賦值運動軌跡 function _run(ball) { var randomXFlag = Math.random() > 0.5 var randomYFlag = Math.random() > 0.5 var randomX = parseInt(Math.random() * 160); var randomY = parseInt(Math.random() * 160); if (randomXFlag) { randomX = randomX * -1; } if (randomYFlag) { randomY = randomY * -1 } var transform = 'translate3d('+randomX+'px,' + randomY + 'px, 0) scale(0)'; ball.style.webkitTransform = transform; ball.style.MozTransform = transform; ball.style.msTransform = transform; ball.style.OTransform = transform; ball.style.transform = transform; } 複製程式碼
fly函式接受四個引數,x,y程式碼螢幕座標,playCount是執行一次播放幾輪, loopTimer是間隔
_run函式中通過random實現小球隨機向四面八方運動
可以看到這個函式js計算非常少,只有在建立和刪除做了一些迴圈。而且用了createDocumentFragment儘可能的減少了dom操作,對效能提升也有很大幫助
整體結構
function (win, doc) { "use strict"; var defaultParams = { colors: ['#eb125f', '#6eff8a', '#6386ff', '#f9f383'], size: 30, maxCount: 50 } function colorBall(params) { } colorBall.prototype.fly = function (x, y, playCount, loopTimer) { } //相容CommonJs規範 if (typeof module !== 'undefined' && module.exports) { module.exports = colorBall; }; //相容AMD/CMD規範 if (typeof define === 'function') define(function() { return colorBall; }); //註冊全域性變數,相容直接使用script標籤引入外掛 win.colorBall = colorBall; })(window, document) 複製程式碼
至此外掛封裝完畢,下面是使用方式
可選引數配置
var params = { colors: ["#eb125f", "#6eff8a", "#6386ff", "#f9f383"], // 自定義顏色 size: 30, // 小球大小 maxCount: 30 // 小球的數量 } 複製程式碼
使用方式
<script src="click-colorful.js"></script>
//params不傳,則走預設配置 var color = new colorBall(params) // 綻放一次 color.fly(x, y) // 綻放5次,間隔300ms color.fly(x, y, 5, 300) 複製程式碼