Flutter CustomPaint 绘制声音波动曲线(二)

11,625 阅读3分钟

voicewave.gif

前言

上节介绍了 Flutter CustomPaint 绘制声音波动曲线(一)

振幅相同曲线的波动实现,这一节我们介绍下效果图所示曲线的实现原理以及代码实现过程

  首先要对需求有着确切的分析后,明确需求的大概实现思路,那么需求就已经实现了一半 

分析

  1.明确动画是不是有规律的?

  • 确定是一个 振幅有规律递增递减的正弦函数,如果无规律则无法实现   2.曲线的函数表达式是什么?
  • 正弦函数的表达式 y=A sin(ωx+φ), 振幅有规律递增递减的正弦函数是什么?,需要明确函数表达式

思路

    1. 通过确定曲线函数表达式,绘制递增递减的静态曲线

    2. 通过改变静态曲线的函数某些参数,实现曲线的波动 

工欲善其事,必先利其器

  推荐个工具,不仅更直观函数的图像表达,还可以设置参数调试动画效果

曲线的表达式

可惜数学都留在了校园,但曲线的形状感觉在哪里见到过,感觉像是信号与系统里的载波信号,经过上述工具的推算,最终表达式其实是两个正弦函数的乘积

  •   f(x) =  A * sin(b * x) * sin(c * x)  

曲线的绘制

 void paint(Canvas canvas, Size size) {
    // 获取采样点
    initPoints();
    // 画笔
    Paint paint = Paint()
      ..color = Colors.red
      ..strokeWidth = 2
      ..style = PaintingStyle.stroke;
    // 路径
    Path path = Path();
    canvas.translate(0, size.height / 2);
    // 通过点确定曲线路径
    for (var i = 1; i < xAliax.length - 1; i++) {
      double x1 = xAliax[i];
      double y1 = funcSquaredSinx(x1);
      double x2 = (xAliax[i] + xAliax[i + 1]) / 2;
      double y2 = (y1 + funcSquaredSinx(xAliax[i + 1])) / 2;
      path.quadraticBezierTo(x1, y1, x2, y2);
    }
    // 画布绘制
    canvas.drawPath(path, paint);
  }
   //曲线函数表达式
   double funcSquaredSinx(double x) {
    double p = 30 * sin(3 * pi * x / 400) * sin(x * pi / 400);
    return p;
  }
  • 采样点 [x1,x2,x3,....] 经过funcSquaredSinx 计算出y值
  • 通过path.quadraticBezierTo(x1, y1, x2, y2) 采样点相连接,最终绘制出曲线

 

曲线波动效果

  首先需要思考一个问题,我们如何让曲线实现波动效果?振幅相同曲线通过canvas移动 实现曲线波动,在这里肯定不适应

  • 我们是采样点链接绘制路径,只有改变采样点的y值,需要从函数funcSquaredSinx入手

  正弦函数 y=A sin(ωx+φ) 的平移 是由φ决定, 所以只需要控制funcSquaredSinxsin(3 * pi * x / 400 + φ)φ 便可以可以平移曲线。用工具演示如下  

曲线波动的代码实现

  只需要我们传入 Animation *repaint 更改函数表达式


   Tween(begin: 0.0, end: 1.0).animate(_controller)
   //曲线函数表达式
   double funcSquaredSinx(double x) {
    double p = 
    30 * sin(3 * pi * x / 400 - 100 * repaint.value) * sin(x * pi / 400);
    return p;
  }
  • 动画不断重绘,采样点的y值不断改变,路径不断改变,每一帧的路径渐变,产生动画
  • Canvas 可以绘制多条曲线,三条曲线初始相位不同和振幅不同,自定义每条线的粗细和颜色,便产生了首图的效果

三条曲线并加入渐进色  

总结

优点

  • 任意曲线动效都能实现
  •  支持渐变色

缺点

  • 不断重绘path,相对canvas移动更消耗性能 但在接受范围之内

两种曲线的绘制方式

  1. 固定点的位置,固定路径绘制,移动画板canvas

  2. 刷新点的位置,不断重绘路径,生成动画

公式总结:

image.png

未经作者授权,禁止转载