先放一張簡單的效果圖
?原理
sin函式估計大家都會,用到的公式為amplitude * sin(frequency * x) + displacement
我們可以通過改變函式的振幅和頻率來達到控制曲線動畫。
?開始
定義一個Wave
類
“`
class Wave {
constructor(color) {
this.t = 0;
this.step = w / 300;
this.color = color;
this.speed = 0.1;
this.a = 30;
this.f = 20;
this.d = 20;
}
caculate(x) {
this.amplitude = this.a;
this.frequency = this.f * (1 / w);
this.displacement = this.d;
// A*sin(Bx + C) + D
return (
this.amplitude * Math.sin(this.frequency * x + this.t) + this.displacement
);
}
render() {
this.t += this.speed;
ctx.save();
ctx.beginPath();
ctx.translate(0, h / 2);
ctx.lineWidth = 1;
ctx.moveTo(0, 0);
for (let i = this.step; i < w; i += this.step) {
ctx.lineTo(i, this.caculate(i));
}
ctx.lineTo(w, this.caculate(w));
ctx.lineTo(w, h);
ctx.lineTo(0, h);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
ctx.restore();
}
}
“`
這裡面沒有什麼特別的魔法,很容易就能夠畫出一條波浪。
但是稍微有點感覺的人就會發現整個動畫特別僵硬,就像是一張圖片在做平移一樣。作為一個有理想的人怎麼可以忍。
?改進
很容易發現讓人覺得僵硬的原因是波浪的波峰一直是這麼高,如果能讓波峰的大小也隨著改動的畫就OK了。
新增一點小小的細節,定義一個this.k
的值,然後修改
this.amplitude = this.a;
改為
this.amplitude = this.a * sin(((this.t / this.k) * this.k) / 5);
看到這裡你可能會好奇這迷一樣的函式怎麼來的,我們的目標是讓振幅也跟著變動,所以就乘以了一個sin函式來讓振幅也可以高高低低變化。
?最後
案例簡單實現
參考連結