loading动画的性能优化-摒弃Canvas,拥抱CSS3-实现点击特效

click-colorful
click-colorful

demo演示 coldday.github.io/click-color…javascript

项目中有个活动页加载时有个loading动画,效果如上图,连续绽开小球,问题就是太卡,常常出现一堆小球抱团卡住,遂进行优化java

注意:(仅在页面加载时卡顿,加载完毕,点击的时候不卡顿)

查看代码发现动画借用的animejs 官网中的效果,经过canvas实现的,按理说canvas应该时性能很好的,不该该出现卡顿,问题在个人活动页中就是很是卡顿git

思考再三,把最终缘由归结于首页加载时候,浏览器要加载资源,渲染dom,耗费cpu,而canvas作帧动画会作大量的计算,这对cpu确定是一种消耗,给浏览器形成必定压力,我的看法,不必定准确github

个人解决办法是砍掉canvas,借助CSS3并触发硬件加速,只在建立小球的时候作一次运算,帧动画经过transform集合transition实现,这样能够大大减小js的运算web

插件封装好并开源 github click-colorful ,所有代码不到100行,有兴趣能够看一下,以为能够就 Star 一下,算是鼓励

下面是核心代码实现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 // 小球的数量
  }
复制代码

使用方式

  • 引入click-colorful.js <script src="click-colorful.js"></script>
  • 实力化插件
//params不传,则走默认配置
var color = new colorBall(params)
// 绽开一次
color.fly(x, y)
// 绽开5次,间隔300ms
color.fly(x, y, 5, 300)
复制代码

声明: 并非说canvas很差,只是有的场景不适合用canvas

若是文章哪里写的有问题请指出,谢谢

相关文章
相关标签/搜索