千家信息网

Flutter怎么绘制曲线,折线图及波浪动效

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,这篇文章主要介绍了Flutter怎么绘制曲线,折线图及波浪动效,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。简介之前用 Flutter
千家信息网最后更新 2026年11月04日Flutter怎么绘制曲线,折线图及波浪动效

这篇文章主要介绍了Flutter怎么绘制曲线,折线图及波浪动效,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

简介

之前用 Flutter 的 Canvas 画点有趣的图形我们介绍了使用 CustomPaint 绘制自定义形状,可以看到有了图形的平面绘制数学计算方法,我们可以画出所需的形状。本篇我们来介绍线条类图形的绘制,并且结合 Animation 实现了常见的波浪动效。通过本篇,你可以了解到:

  • 正弦曲线的绘制

  • 利用两条正弦曲线加上 Animation 实现波浪动效

  • 曲线的一般绘制方法

  • 折线图绘制

下面是最终实现的效果图,接下来我们一项一项介绍。

正弦曲线绘制

对于正弦曲线,公式定义如下:y=Asin(2ut+θ)对于在屏幕绘制,由于屏幕的点都是离散的,因此实际就是对正弦曲线进行采样,只要采样间隔足够密集,画出来的效果肉眼上很难区分是离散点之间通过连线完成绘制的。因此,绘制正弦曲线其实就是将正弦曲线的点依次连起来就好了。下面是绘制的实现代码,waveHeight是正弦曲线的振幅,这里我们一个屏幕宽度绘制一个周期,因此使用的是 2 * pi * i / size.width。

Path path = Path();path.moveTo(0, center.height);for (double i = 1; i < size.width; i += 1) {  path.lineTo(    i,    center.height +        waveHeight * sin(2 * pi * i / size.width + startAngle * pi * 4),  );}canvas.drawPath(path, paint);

波浪动效

观察波浪动效,实际上是两条正弦曲线,由于移动的速度不一样,给人的感觉是向前涌动一样。控制曲线的移动实际上可以在动画过程中控制正弦曲线的起始角度,即公式中的θ变量来实现。我们的动画控制变量 Animation的变化范围是0到1,为了保证动画重复角度的连贯性,保持起始角度在一个动画周期结束后保持一致即可,也就是动画周期结束时要为2π的整数倍,这里我们一个设置了一条正弦取消的周期为4π,另一条是6π。起始角度的周期角度越大,给人感觉的移动速度会越快。下面是两条正弦曲线的绘制代码,这里的startAngle就是 Animation对象在动画过程中的值。这里需要注意一下,由于每次startAngle都会刷新,因此在 CustomPainter 的子类中,需要将 shouldRepaint 返回 true 以支持重绘,如果这个值返回是 false 的话就不会重新绘制。

  void paint(Canvas canvas, Size size) {  var center = Size(size.width / 2, waveHeight * 2);  var paint1 = Paint()..color = Color(0xFF20B0FE);  paint1.strokeWidth = 1.0;  paint1.style = PaintingStyle.stroke;  var paint2 = Paint()..color = Color(0x8020C0E5);  paint2.strokeWidth = 1.0;  paint2.style = PaintingStyle.stroke;  Path path2 = Path();  path2.moveTo(0, center.height);  Path path3 = Path();  path3.moveTo(0, center.height + waveHeight);  for (double i = 1; i < size.width; i += 1) {    path2.lineTo(      i,      center.height +          waveHeight * sin(2 * pi * i / size.width + startAngle * pi * 4),    );    path3.lineTo(      i,      center.height +          waveHeight * sin(2 * pi * i / size.width + startAngle * 6 * pi),    );  }  canvas.drawPath(path2, paint1);  canvas.drawPath(path3, paint2);}

完整代码已经上传至:自定义绘图代码,目录在 basic_paint 目录下的 curves_paint.dart 中。

曲线绘制

有了正弦曲线的绘制知识,其他曲线其实也是一个道理,我们通过数学表达式,通过横坐标计算纵坐标的值,然后形成一系列采样点,再用 Path 对象依次连接这些点就可以实现各类曲线的绘制了。下面是对数曲线的绘制示例代码。

var center = Size(size.width / 2, size.height / 2);var paint = Paint()..color = Color(0xFF2080E5); //2080E5paint.strokeWidth = 1.0;paint.style = PaintingStyle.stroke;Path path = Path();path.moveTo(0, center.height);for (double i = 1; i <= size.width; i += 1) {  path.lineTo(    i - 1,    center.height - 20.0 * log(i),  );}canvas.drawPath(path, paint);

绘制效果如下图。

折线图

折线图在实际开发中会比较常见了,通常会有坐标轴,然后将这个点通过线段连起来,并需要标注点的位置。绘制的原理和曲线是一样的,只是因为折线图的间隔比较大而已。而标注点我们可以通过在折线上绘制圆圈或正方形来实现,我们封装了两个类,一个绘制折线,一个绘制坐标轴。坐标轴的绘制目前实现比较简单,就是由外面传入横轴起止点和纵轴起止点,将横轴和纵轴绘制出来并加上了箭头指示。

// 折线绘制class LineChartPainter extends CustomPainter {  final List> points;  LineChartPainter({Key? key, required this.points}) : super();  @override  void paint(Canvas canvas, Size size) {    var paint = Paint()..color = Color(0xFF2080E5); //2080E5    paint.strokeWidth = 2.0;    paint.style = PaintingStyle.stroke;    var pointPaint = Paint()..color = Color(0xFF20FF65); //2080E5    pointPaint.strokeWidth = 1.0;    pointPaint.style = PaintingStyle.stroke;    Path path = Path();    path.moveTo(points[0].x, points[0].y);    for (var point in points) {      path.lineTo(point.x, point.y);      canvas.drawCircle(Offset(point.x, point.y), 4.0, pointPaint);    }    canvas.drawPath(path, paint);  }  @override  bool shouldRepaint(covariant CustomPainter oldDelegate) {    return false;  }}// 坐标轴绘制class AxisPainter extends CustomPainter {  final Point horizontalStartPoint, horizontalEndPoint;  final Point verticalStartPoint, verticalEndPoint;  AxisPainter({    Key? key,    required this.horizontalStartPoint,    required this.horizontalEndPoint,    required this.verticalStartPoint,    required this.verticalEndPoint,  }) : super();  @override  void paint(Canvas canvas, Size size) {    var paint = Paint()..color = Color(0xFF909090);    paint.strokeWidth = 2.0;    paint.style = PaintingStyle.stroke;    Path horizontalPath = Path();    horizontalPath.moveTo(horizontalStartPoint.x, horizontalStartPoint.y);    horizontalPath.lineTo(horizontalEndPoint.x - 1, horizontalEndPoint.y);    canvas.drawPath(horizontalPath, paint);    Path verticalPath = Path();    verticalPath.moveTo(verticalStartPoint.x, verticalStartPoint.y);    verticalPath.lineTo(verticalEndPoint.x, verticalEndPoint.y + 1);    canvas.drawPath(verticalPath, paint);    paint.style = PaintingStyle.fill;    paint.strokeWidth = 2.0;    final double arrowLength = 12.0;    // 画箭头    Path horizontalArrow = Path();    horizontalArrow.moveTo(horizontalEndPoint.x, horizontalEndPoint.y);    horizontalArrow.lineTo(horizontalEndPoint.x - arrowLength,        horizontalEndPoint.y - arrowLength / 2);    horizontalArrow.lineTo(horizontalEndPoint.x - arrowLength,        horizontalEndPoint.y + arrowLength / 2);    horizontalArrow.close();    canvas.drawPath(horizontalArrow, paint);    // 画箭头    Path verticalArrow = Path();    verticalArrow.moveTo(verticalEndPoint.x, verticalEndPoint.y);    verticalArrow.lineTo(        verticalEndPoint.x - arrowLength / 2, verticalEndPoint.y + arrowLength);    verticalArrow.lineTo(        verticalEndPoint.x + arrowLength / 2, verticalEndPoint.y + arrowLength);    verticalArrow.close();    canvas.drawPath(verticalArrow, paint);  }  @override  bool shouldRepaint(covariant CustomPainter oldDelegate) {    return false;  }}

最终实现的折线图绘制效果如下。

其他说明

对于 CustomPaint 的绘制区域,这里特别说明一下。如果 CustomPaint 是组件树的根节点的话,那么绘制区域是整个屏幕。但是如果CustomPaint 有子元素(即 child 参数不为空),那么会将绘制区域尺寸限制为子元素的大小。本篇的示例中使用了一个列表将三个绘制方式放在了一个页面,为了限制每个绘图的尺寸,都指定了一个 Container作为了 CustomPaint 的子元素,通过这种方式可以指定绘制区域大小,以及设置背景色(例如波浪动效的背景就是使用了 Container 实现了渐变效果)。

感谢你能够认真阅读完这篇文章,希望小编分享的"Flutter怎么绘制曲线,折线图及波浪动效"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

曲线 正弦 正弦曲线 波浪 线图 动画 代码 周期 效果 区域 坐标 坐标轴 实际 就是 屏幕 篇文章 角度 元素 图形 折线 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广东猪兼强互联网科技有限公司 哈尔滨大商圈互联网科技有限公司 江苏根荣互联网科技 互联网巨头科技公司 北京互联网科技 互联网 卓越科技 艾特科技互联网 互联网金融科技创新 镁科技互联网资讯平台 湖南洣水互联网科技有限公司扣款 团飞科技与伯堂互联网服务平台 阿里互联网科技公司 苏州五指互联网络科技有限 千方科技属于互联网企业吗 互联网科技商业 恒生互联网科技指数跳水 互联网金融科技元年 平安好医生打造互联网科技医疗 恒生互联网科技趋势 武汉亿视互联网科技有限公司 广东万易互联网科技有限公司惠州分公司 互联网科技小贷 天津摩尔互联网科技 华中科技有哪些互联网大佬 互联网为啥属于高科技 花神(南京)互联网科技有限公司 滨湖区互联网智能科技产品有哪些 中国互联网公司的科技投入 安徽零酒互联网科技有限公司 互联网企业和网络科技有限公司
0