⽤css3和canvas实现的蜂窝动画效果
最近⼯作时研究了⼀下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动画来调⽤动画就可以实现这种效果了
<pre name="code" class="html">.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 || ElementById(this.canvasId) || ElementById('#canvas');
< = Context('2d');
this.canvasWidth = BoundingClientRect().width;
this.canvasHeight = BoundingClientRect().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;
// load = function () {
// }
},
这个⽅法很简单吧,只不过是简单的偏移了⼀半的宽⾼,再调⽤canvas的默认绘制函数
接下来的⽅法是获取所需要绘制矩形的中⼼点位置了,先看代码:
// 获取所有显⽰⼩图⽚的中⼼点位置
getPoints : function (width, height) {
// var width = parseInt(w), height = parseInt(h);
var numW = il(100 / width), numH = il(100 / height);
var result = [];
for (var i = -il(numW * 0.5); i <= il(numW * 0.5); i++) {
var x = 50 + width * i;
for (var j = -il(numH * 0.5); j <= il(numH * 0.5); j++) {
var y = 50 + height * j;
result.push({x: x * this.canvasWidth / 100, y: y * this.canvasHeight / 100});
}
}
return result;
},
js控制css3动画触发其实原来就是从canvas的中⼼点50, 50出发,numW, numH分别表⽰在⽔平⽅向和垂直⽅向所需要画的矩形个数,这⾥要注意使⽤il向上取整,是为了确保能够撑满整个canvas,然后x = 50 + width * i;代表在x⽅向上减去width的值,就等于中⼼点左边第⼏个x值,同理y⽅向上也⼀样,最后函数返回⼀个包含所有坐标点的数组。接下来就是使⽤这个数组和上⾯提供的绘制⽅法,来⼀个⼀个的将所有图⽚绘制出来。
完整的模块源码如下:
define(function (require, exports, module) {
var RAF = questAnimationFrame ||
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 || ElementById(this.canvasId) || ElementById('#canvas');
< = Context('2d');
this.canvasWidth = BoundingClientRect().width;
this.canvasHeight = BoundingClientRect().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,
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;
// load = function () {
// }
},
// 获取所有显⽰⼩图⽚的中⼼点位置
getPoints : function (width, height) {
// var width = parseInt(w), height = parseInt(h);
var numW = il(100 / width), numH = il(100 / height);
var result = [];
for (var i = -il(numW * 0.5); i <= il(numW * 0.5); i++) {
var x = 50 + width * i;
for (var j = -il(numH * 0.5); j <= il(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 = Points(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 () {
}
};
return Honey;
})
这⾥使⽤requestAnimatioFrame来循环调⽤,⽽不是常见的setTimeout,具体原因⼤家还是Google吧。使⽤canvas来绘制会⽐较耗性能,不介意⼤家使⽤,但是如果是在写canvas动画时,⼤家可以考虑添加这么⼀个动画效果。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。