demo演示 coldday.github.io/click-color…javascript
項目中有個活動頁加載時有個loading動畫,效果如上圖,連續綻開小球,問題就是太卡,常常出現一堆小球抱團卡住,遂進行優化java
查看代碼發現動畫借用的animejs 官網中的效果,經過canvas實現的,按理說canvas應該時性能很好的,不該該出現卡頓,問題在個人活動頁中就是很是卡頓git
思考再三,把最終緣由歸結於首頁加載時候,瀏覽器要加載資源,渲染dom,耗費cpu,而canvas作幀動畫會作大量的計算,這對cpu確定是一種消耗,給瀏覽器形成必定壓力,我的看法,不必定準確github
個人解決辦法是砍掉canvas,藉助CSS3並觸發硬件加速,只在建立小球的時候作一次運算,幀動畫經過transform集合transition實現,這樣能夠大大減小js的運算web
下面是核心代碼實現canvas
var defaultParams = { colors: ['#eb125f', '#6eff8a', '#6386ff', '#f9f383'], size: 30, maxCount: 30 } 複製代碼
小球的顏色,大小,數量均可以隨意配置,很是靈活瀏覽器
function colorBall(params) { this.params = Object.assign({}, defaultParams, params) } 複製代碼
參數的賦值性能優化
colorBall.prototype.fly = function (x, y, playCount, loopTimer) { if (!loopTimer) loopTimer = 300 var ballElements = [] var fragment = document.createDocumentFragment() var ballNum = this.params.maxCount; // 修改輪換播放實現方式,改成一次建立全部,經過延遲執行動畫實現 if(playCount) { ballNum = ballNum * playCount; } var loop = 0 for(var i=0; i<ballNum; i++) { var curLoop = parseInt(i/this.params.maxCount) var ball = doc.createElement('i'); ball.className = 'color-ball ball-loop-' + curLoop; 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) + 'px'; ball.style.top = (y) + 'px'; ball.style.width = this.params.size + 'px'; ball.style.height = this.params.size + 'px'; ball.style.position = 'fixed'; ball.style.borderRadius = '1000px'; ball.style.boxSizing = 'border-box'; ball.style.zIndex = 9999; ball.style.opacity = 0; if (curLoop === 0) ball.style.opacity = 1; ball.style.transform = 'translate3d(0px, 0px, 0px) scale(1)'; ball.style.webkitTransform = 'translate3d(0px, 0px, 0px) scale(1)'; ball.style.transition = 'transform 1s ' + curLoop * loopTimer / 1000 + 's ease-out'; ball.style.webkitTransition = 'transform 1s ' + curLoop * loopTimer / 1000 + 's ease-out'; ball.style.backgroundColor = getOneRandom(this.params.colors); fragment.appendChild(ball); ballElements.push(ball) // 性能優化終極版 if (curLoop !== loop) { (function(num){ setTimeout(function(){ var loopBalls = document.getElementsByClassName('ball-loop-' + num) for(var j = 0; j < loopBalls.length; j++) { loopBalls[j].style.opacity = 1 } if (num === loop) { _clear(ballElements) } }, num * loopTimer + 30) })(curLoop) loop = curLoop } } doc.body.appendChild(fragment); // 延遲刪除 !playCount && _clear(ballElements) // 執行動畫 setTimeout(function () { for(var i=0; i<ballElements.length; i++){ _run(ballElements[i]) } }, 10) } // 隨機賦值運動軌跡 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是間隔markdown
經過delay實現循環播放,而不是遞歸分批建立dom,減小頁面迴流,性能很高app
_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) 複製代碼