Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

canvas绘制水波纹 #5

Open
tinet-jutt opened this issue Apr 23, 2021 · 0 comments
Open

canvas绘制水波纹 #5

tinet-jutt opened this issue Apr 23, 2021 · 0 comments
Labels

Comments

@tinet-jutt
Copy link
Owner

tinet-jutt commented Apr 23, 2021

水波纹图

原理

水波纹的外形上与正弦曲线一样,可以通过正弦曲线去分析水波纹的实现原理。

水波纹图

正弦曲线公式为 y = Asin(ωx + φ) + k

A为振幅,改变该值,可改变水波纹波浪的深度,A越大,水波纹越陡,A越小,水波纹越平。

水波纹图

φ为出相,改变该值,可改变水波纹水平方向的位置,φ为正数,水波纹向右移动,φ为负数,水波纹向左移动。

水波纹图

k为偏距,改变改值,可改变水波纹垂直方向的位置。

水波纹图

ω为角速度,改变改值,可改变水波纹波浪的宽度,ω越大,水波纹越窄,ω越小,水波纹越宽。

水波纹图

通过正弦曲线的原理,水波纹进度条由下往上移动,可以通过增大k向上移动实现,水波纹的滚动可以通过φ从右至左移动,水波纹的形状由正弦曲线形成。

实现

绘制曲线


class Wave{
    constructor(el,option){
      // 波形移动的速度,可根据正负决定波形移动方向
      this.speed = 1;
      // 波的默认颜色
      this.color = 'lightblue';
      this.el = el;
      // 振幅,控制水波纹垂直方向的深度
      this.amplitude = 20;
      this._offset = 0;
      Object.assign(this, option);
      this.init();
      this.el.appendChild(this.canvas);
    }
    init(){
      const offset = this.el.getBoundingClientRect();
      // 创建画布
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const { width, height } = offset;
      const { speed } = this;
      // 根据容器的尺寸设置画布的尺寸
      this.width = ctx.width = canvas.width = width;
      this.height = ctx.height = canvas.height = height;
      this.canvas = canvas;
      this.ctx = ctx;
      this.offsetTop = !!this.offsetTop?this.offsetTop:height/2;
      this.animate();
    }
    render(){
      const { ctx, width, height, color, _offset, amplitude } = this;
      let offsetTop = this.offsetTop;
      ctx.strokeStyle = color;
      ctx.fillStyle = color;
      ctx.lineWidth = 1;
      // 绘制前清空画板
      this.ctx.clearRect(0,0,this.width,this.height);
      ctx.beginPath();
      // 波形涨满后无需进行波形绘制,直接绘制矩形填充
      if (offsetTop <= 0) {
        this.offsetTop = 0;
        ctx.rect(0, 0, this.width, this.height);
        ctx.fill();
        return
      }
      // 绘制正弦曲线
      for(let i=0;i<width;i+=0.1){
        const x = i*30;
        const y = Math.sin(i+_offset )*amplitude + offsetTop;
        ctx.lineTo(x,y);
      }
      ctx.lineTo(width, height);
      ctx.lineTo(0, height);
      ctx.closePath();
      // 描边
      ctx.stroke();
      // 填充
      ctx.fill();
    }
    animate(){
      this._offset+=this.speed;
      if(this._offset > this.width) this._offset = 0;
      this.render();
      // 动画帧调用
      window.requestAnimationFrame(this.animate.bind(this));
    }
  }

使用

  // canvas 组件容器
  const el = document.querySelector('.wave');

  const wave = new Wave(el,{
    speed: 0.07,
    amplitude: 10,
    color: 'lightblue'
  });

源码地址: https://github.com/tomatoKnightJ/Blog/blob/main/src/canvas/wave.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant