A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

click-colorful
项目中有个活动页加载时有个loading动画,效果如上图,连续绽放小球,问题就是太卡,经常出现一堆小球抱团卡住,遂进行优化
注意:(仅在页面加载时卡顿,加载完毕,点击的时候不卡顿)查看代码发现动画借用的animejs  官网中的效果,通过canvas实现的,按理说canvas应该时性能很好的,不应该出现卡顿,问题在我的活动页中就是非常卡顿
思考再三,把最终原因归结于首页加载时候,浏览器要加载资源,渲染dom,耗费cpu,而canvas做帧动画会做大量的计算,这对cpu肯定是一种消耗,给浏览器造成一定压力,个人见解,不一定准确
我的解决办法是砍掉canvas,借助CSS3并触发硬件加速,只在创建小球的时候做一次运算,帧动画通过transform集合transition实现,这样可以大大减少js的运算
插件封装好并开源 github click-colorful  ,全部代码不到100行,有兴趣可以看一下,觉得可以就 Star 一下,算是鼓励下面是核心代码实现
定义默认参数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 = this.params.maxCount * 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                                                }                                        }, num * loopTimer + 30)                                })(curLoop)                                loop = curLoop                        }                }                doc.body.appendChild(fragment);                // 执行动画                setTimeout(function () {                        for(var i=0; i<ballElements.length; i++){                                _run(ballElements)                        }                        }, 10)                // 清空dom                setTimeout(function () {                        for(var i=0; i<ballElements.length; i++){                                doc.body.removeChild(ballElements)                        }                        }, 3000)        }        //  随机赋值运动轨迹        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是间隔
通过delay实现循环播放,而不是递归分批创建dom,减少页面回流,性能很高
_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 // 小球的数量  }复制代码
使用方式
  • 引入click-colorful.js <script src="click-colorful.js"></script>
  • 实力化插件
//params不传,则走默认配置var color = new colorBall(params)// 绽放一次color.fly(x, y)// 绽放5次,间隔300mscolor.fly(x, y, 5, 300)复制代码声明: 并不是说canvas不好,只是有的场景不适合用canvas

【转载】
作者:杨金凯
链接:https://juejin.im/post/5be3817de51d457844614b42



3 个回复

倒序浏览
~(。≧3≦)ノ⌒☆
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马