canvas可以說是html5其中的一大亮點,有了它,我們可以基于canvas畫布實現(xiàn)很多之前只有flash和視頻才能實現(xiàn)的效果。廢話少說,先上效果。
canvas結(jié)合三角函數(shù)實現(xiàn)一個視頻直播效果
* {
margin: 0;
padding: 0;
}
html,
body {
font-size: 0;
height: 100%;
}
canvas {
background: #000;
}
(function (document) {
class Point {
constructor(option) {
this.x = option.context.canvas.width / 1.5;//對象的X坐標(biāo)
this.y = Math.random() * option.context.canvas.height/2 + option.context.canvas.height / 2 ;//對象的Y坐標(biāo)
this.defaultX = this.x;
this.defaultY = this.y;
this.img = option.img;
this.angle = Math.random()*360 | 0;
this.context = option.context;
this.width = this.context.canvas.width;
this.height = this.context.canvas.height;
this.speedX = 0;//元素在x軸上的速度,下面要通過三角函數(shù)來實現(xiàn)。
this.speedY = -4* Math.random() - 8;
this.alpha = 1;
this.render();
}
render() {
var {
context,
img,
x,
y
} = this;
context.save();
context.globalAlpha = this.alpha ;
context.drawImage(img, x, y,img.width/2,img.height/2);
context.restore();
}
animate() {
this.angle +=3;
this.angle %= 360;
this.speedX = 4* Math.sin(this.angle/180*Math.PI*2);
this.x += this.speedX;
this.y += this.speedY;
var {width,height} = this;
this.alpha = this.y / height / 2 + .2;
if (Math.abs(this.y <= height / 2)) {
this.y = height;
this.angle = Math.random() * 360 | 0;
this.alpha = 1;
this.x = this.defaultX;
}
this.render();
}
}
var zmitiUtil = {
viewW: window.innerWidth,
viewH: window.innerHeight,
init() {
this.setSize();
this.createParticals();
this.animate();
},
setSize() {
this.canvas = document.querySelector('#canvas');
this.context = this.canvas.getContext('2d');
this.canvas.width = this.viewW;
this.canvas.height = this.viewH;
},
createParticals(){
this.particals = [];
var img = new Image();
var self = this;
img.onload = function(){
var _this = this;//這里面this指向的是img對象
for (var i = 0; i < 30; i++) {
self.particals.push(new Point({
img: _this,
context: self.context
}))
}
}
img.src = './images/heart.png';
},
animate(){
var _this = this;
(function render(){//這里面this 發(fā)生了變化,請注意哦,因為出現(xiàn)了function 哦
requestAnimationFrame(render);
_this.context.clearRect(0,0,_this.viewW,_this.viewH);
_this.particals.forEach(partical => {
partical.animate();
})
})();
}
};
zmitiUtil.init();
})(document);
技術(shù)總結(jié):
先來簡單回顧下高中的正弦曲線
我們會發(fā)現(xiàn),圖中的曲線和我們的效果是反著來的,所以我們要把x,y對應(yīng)的調(diào)換下位置即可,運動起來就會在X軸的速度上體現(xiàn)出來了。具體可參考下源代碼。
簡單的解釋下 this.speedX = 4* Math.sin(this.angle/180*Math.PI); this.angle為當(dāng)前的角度,取值范圍為:[0,360],js提供的三角函數(shù)是要接收一下弧度的,所以我們需要轉(zhuǎn)一下。
解釋 this.angle = Math.random() * 360 | 0; // 有的可能不太知道后面的 ”| 0“是什么意思,本屌之前也不知道是什么意思,自己試,多試幾次,于是就知道了,這個是去掉了小數(shù)的部分,相當(dāng)于 Math.floor() , 但要問這是什么原理,好像是二進(jìn)制的算法,其實我也不知道,但我知道這個用法就行了。
注意下這個代碼里在的有幾個地方涉及到了this的指向問題哦。我在代碼中已有注釋。
像這種粒子動畫的實現(xiàn)原理,先實現(xiàn)一個粒子的動畫,然后循環(huán)生成一堆,把所有的push到一個數(shù)組中去。然后用動畫函數(shù)遍歷數(shù)組,執(zhí)行數(shù)組中的每一個對象的運動函數(shù)。
html5 canvas 畫布一是無狀態(tài)的機制。像類似 context 的 globalAlpha,translate,rotate等一些屬性在操作之前需要加上context.save();在后面再context.restore();代碼中也有體現(xiàn)。如果我們不加上context.save()那么,會給所有的粒子都設(shè)置了相同的透明試,這可不是我想要的。
ES6的類的創(chuàng)建,解構(gòu)賦值。
寫在最后:
我們可以看到很漂亮的數(shù)學(xué)曲線,應(yīng)用到web頁面上,充分體現(xiàn)出了數(shù)學(xué)之美。希望大家在學(xué)習(xí)上遇到一些自己不懂的寫法,一定要自己先去嘗試,一定要自己嘗試,還要要想盡辦法應(yīng)該到你們的項目中,這樣我們印象才深刻。