热搜:NVER node 开发 php

用css3和canvas实现的蜂窝动画效果_html/css_WEB-ITnose

2024-11-24 13:50:01
用css3和canvas实现的蜂窝动画效果_html/css_WEB-ITnose

最近工作时研究了一下css3动画和js动画,主要是工作中为了增强页面的趣味性,大家都有意无意的添加了很多动画效果,当然大部分都是css3动画效果,可以gpu加速,这会减少移动端的性能需求。

今天主要说的是蜂窝效果,具体效果大家等下可以运行源码,这里就不放gif图了。

css3的原理很简单,就是通过更改background-size,由于css3中的background中可以设置repeat属性,来使背景图片在x,y方向平铺。一开始先设置background-size:10%, 10%,(这个数值可以自由定义,但不介意设置过大,否则效果不明显), 最后更改backg-size:100%, 100%;这样会使背景图片充满整个屏幕,哦,对了不要忘记设置background-position:50% 50%;否则你会感觉怪怪的,设置background-position是为了是背景图片以中心点的位置来平铺,而系统默认会已左上角来平铺。然后通过设置animation动画来调用动画就可以实现这种效果了

.honey {			position: absolute;			top: 0;			left: 0;			height: 100%;			width: 100%;			background: url(2.jpg) repeat;			background-size: 30% 30%;			background-position: center center;			-webkit-animation: honeycomb 3s 1 linear;		}				@-webkit-keyframes honeycomb {			0% {				background-size: 10% 10%;			}			100% {				background-size: 100% 100%;			}		}

使用css3来实现这种蜂窝式的动画效果,原理简单,并且效果很完美,但是唯一一点的不完美在于可能会有一部分手机不兼容。并且通过在animation中修改background-size,这种行为很少,虽然不会引起浏览器的重排,但是也会引起浏览器的局部重绘。

至于使用canvas来实现吗,这个纯属无聊,不建议大家使用这种方法,在这里使用canvas来绘制,完全是属于我的无聊之举,不过若是你对canvas动画有意向,可以留意下面的canvas实现方案。canvas绘制的原理很简单,通过传入width,height的百分比,来计算一共需要画多少个矩形,以及每个矩形的中心点坐标。我把这个代码封装成了一个模块,大家可以一步一步的往下看,首先先定义一个对象honey对象吧

var Honey = function (options) {				for (var i in options) {			if (options.hasOwnProperty(i)) {				this[i] = options[i];			}		}		this.canvas = this.canvasId || document.getElementById(this.canvasId) || document.getElementById('#canvas');		this.ctx = this.canvas.getContext('2d');		this.canvasWidth = document.body.getBoundingClientRect().width;		this.canvasHeight = document.body.getBoundingClientRect().height;		this.canvas.width = this.canvasWidth;		this.canvas.height = this.canvasHeight;		this.stopped = true;		this.width = options['width'] || 10;		this.height = options['height'] || 10;		this.dwidth = options['dwidth'] || 1;		this.dheight = options['dheight'] || 1;		this.img = options.img;		/*if (!options.img) {			console.log('没有传入图片地址');		}*/	};
下面在来定义这个对象中的一些属性,canvas的绘制图像默认是从左上角开始绘制,因此我们需要自己写一个方法来从中心点绘制,可以通过prototype来添加到属性中

drawImage : function (x, y, w, h) {			var width = w * this.canvasWidth / 100,				height = h * this.canvasHeight / 100;			var top = y - height / 2,				left = x - width / 2;			var self = this;			// var img = self.img;			// img.onload = function () {				self.ctx.drawImage(self.img, left, top, width, height);			// }		},


这个方法很简单吧,只不过是简单的偏移了一半的宽高,再调用canvas的默认绘制函数

接下来的方法是获取所需要绘制矩形的中心点位置了,先看代码:

		// 获取所有显示小图片的中心点位置		getPoints : function (width, height) {			// var width = parseInt(w), height = parseInt(h);			var numW = Math.ceil(100 / width), numH = Math.ceil(100 / height);			var result = [];			for (var i = -Math.ceil(numW * 0.5); i  其实原来就是从canvas的中心点50, 50出发,numW, numH分别表示在水平方向和垂直方向所需要画的矩形个数,这里要注意使用Math.ceil向上取整,是为了确保能够撑满整个canvas,然后x = 50 + width * i;代表在x方向上减去width的值,就等于中心点左边第几个x值,同理y方向上也一样,最后函数返回一个包含所有坐标点的数组。接下来就是使用这个数组和上面提供的绘制方法,来一个一个的将所有图片绘制出来。  

完整的模块源码如下:

define(function (require, exports, module) {	var RAF = window.requestAnimationFrame ||			  window.webkietRequestAnimationFrame ||			  function (callback) {			  	setTimeout(callback, 1000/ 60);			  };	var Honey = function (options) {				for (var i in options) {			if (options.hasOwnProperty(i)) {				this[i] = options[i];			}		}		this.canvas = this.canvasId || document.getElementById(this.canvasId) || document.getElementById('#canvas');		this.ctx = this.canvas.getContext('2d');		this.canvasWidth = document.body.getBoundingClientRect().width;		this.canvasHeight = document.body.getBoundingClientRect().height;		this.canvas.width = this.canvasWidth;		this.canvas.height = this.canvasHeight;		this.stopped = true;		this.width = options['width'] || 10;		this.height = options['height'] || 10;		this.dwidth = options['dwidth'] || 1;		this.dheight = options['dheight'] || 1;		this.img = options.img;		/*if (!options.img) {			console.log('没有传入图片地址');		}*/	};	Honey.prototype = {		// 以中心点来画图		drawImage : function (x, y, w, h) {			var width = w * this.canvasWidth / 100,				height = h * this.canvasHeight / 100;			var top = y - height / 2,				left = x - width / 2;			var self = this;			// var img = self.img;			// img.onload = function () {				self.ctx.drawImage(self.img, left, top, width, height);			// }		},		// 获取所有显示小图片的中心点位置		getPoints : function (width, height) {			// var width = parseInt(w), height = parseInt(h);			var numW = Math.ceil(100 / width), numH = Math.ceil(100 / height);			var result = [];			for (var i = -Math.ceil(numW * 0.5); i = 100) {						width = 100;					}					if (height >= 100) {						height = 100;					}					if (width >= 100 && height >= 100) {						self.stopped = true;					}					// 画图					self.animate(width, height);					RAF(function () {						tick();					})				}			}		},		animate : function (w, h) {			var self = this;			var points = self.getPoints(w, h);			// console.log(points.length, w, h);			self.clear();			for (var i = 0, len = points.length; i  这里使用requestAnimatioFrame来循环调用,而不是常见的setTimeout,具体原因大家还是Google吧。使用canvas来绘制会比较耗性能,不介意大家使用,但是如果是在写canvas动画时,大家可以考虑添加这么一个动画效果。