zoukankan      html  css  js  c++  java
  • 用css3和canvas实现的蜂窝动画效果

    近期工作时研究了一下css3动画和js动画。主要是工作中为了增强页面的趣味性,大家都有意无意的加入了非常多动画效果。当然大部分都是css3动画效果。能够gpu加速,这会降低移动端的性能需求。

    今天主要说的是蜂窝效果。详细效果大家等下能够执行源代码。这里就不放gif图了。

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

    然后通过设置animation动画来调用动画就能够实现这样的效果了

    <pre name="code" class="html">.honey {
    			position: absolute;
    			top: 0;
    			left: 0;
    			height: 100%;
    			 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绘制的原理非常easy。通过传入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);
    			// }
    		},


    这种方法非常easy吧。仅仅只是是简单的偏移了一半的宽高。再调用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 <= Math.ceil(numW * 0.5); i++) {
    				var x = 50 + width * i;
    				for (var j = -Math.ceil(numH * 0.5); j <= Math.ceil(numH * 0.5); j++) {
    					var y = 50 + height * j;
    					result.push({x: x * this.canvasWidth / 100, y: y * this.canvasHeight / 100});
    				}
    			}
    
    			return result;
    		},
    事实上原来就是从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 <= Math.ceil(numW * 0.5); i++) {
    				var x = 50 + width * i;
    				for (var j = -Math.ceil(numH * 0.5); j <= Math.ceil(numH * 0.5); j++) {
    					var y = 50 + height * j;
    					result.push({x: x * this.canvasWidth / 100, y: y * this.canvasHeight / 100});
    				}
    			}
    
    			return result;
    		},
    
    		init : function () {
    			var width = this.width,
    				height = this.height,
    				dwidth = this.dwidth,
    				dheight = this.dheight,
    				loaded = false;;
    			var self = this;
    			var img = this.img;
    
    			if (!img) {
    				console.log('没有传入图片地址');
    				return;
    			}
    			if (typeof img == 'string') {
    				var image = new Image();
    				image.src = img;
    				img = image;
    				this.img = img;
    			}
    
    			tick();
    			
    			function tick () {
    				if (!self.stopped) {
    					width += dwidth;
    					height += dheight;
    
    					// 防止图片过大缩放,自己主动设置停止标志位
    					if (width >= 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 < len; i++) {
    				var point = points[i];
    				// console.log(point.x, point.y , w * this.canvasWidth / 100, h * this.canvasHeight / 100);
    				self.drawImage(point.x, point.y, w, h);
    			}
    		},
    
    		clear : function () {
    			this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
    		}
    	};
    
    	return Honey;
    })
    这里使用requestAnimatioFrame来循环调用,而不是常见的setTimeout,详细原因大家还是Google吧。使用canvas来绘制会比較耗性能,不介意大家使用。可是假设是在写canvas动画时,大家能够考虑加入这么一个动画效果。

  • 相关阅读:
    java EL表达式中${param.name}详细
    javascript中常用坐标属性offset、scroll、client
    Oralce if ..elsif结构
    VS2013 字符串函数与VC不兼容问题解决方法
    Directory Instruction
    Timestamp
    GetCurrentTime() and CFile option
    MessageBox 参数说明
    单片机红外线接收算法
    IAR for MPS430 V7.12.1 编程规范
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6930675.html
Copyright © 2011-2022 走看看