近期工作時研究了一下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%;
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繪制的原理非常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動畫時,大家能夠考慮加入這么一個動畫效果。
