先放一张简单的效果图
?原理
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函数来让振幅也可以高高低低变化。
?最后
案例简单实现
参考链接