使用canvas繪製dribble風格水波浪

ouzz發表於2019-03-01

先放一張簡單的效果圖

使用canvas繪製dribble風格水波浪

傳送門

?原理

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函式來讓振幅也可以高高低低變化。

?最後

案例簡單實現

使用canvas繪製dribble風格水波浪

傳送門

參考連結

codepen.io/waynecz/pen…

dribbble.com/shots/36529…

dribbble.com/shots/37814…

相關文章