Flutter示例代码:波浪形圆形进度条
渲染
实现步骤
绘制进度条
- 先绘制波浪
void drawWave(Canvas canvas, Offset center, double radius, double waveOffsetPercent, Paint paint) { double waveOffset = -(waveOffsetPercent * radius * 2); //对画布进行圆形裁剪 canvas.save(); Path clipPath = Path() ..addOval(Rect.fromCircle(center: center, radius: radius)); canvas.clipPath(clipPath); //表示出上图所示的point(上图中p)以及controlPoint(上图中c) double waveProgressHeightY = (1 - percent) * radius * 2; Offset point1 = Offset(waveOffset, waveProgressHeightY); Offset point2 = Offset(waveOffset + radius, waveProgressHeightY); Offset point3 = Offset(waveOffset + radius * 2, waveProgressHeightY); Offset point4 = Offset(waveOffset + radius * 3, waveProgressHeightY); Offset point5 = Offset(waveOffset + radius * 4, waveProgressHeightY); Offset point6 = Offset(point5.dx, radius * 2 + halfWaveHeight); Offset point7 = Offset(point1.dx, radius * 2 + halfWaveHeight); Offset controlPoint1 = Offset(waveOffset + radius * 0.5, waveProgressHeightY - halfWaveHeight); Offset controlPoint2 = Offset(waveOffset + radius * 1.5, waveProgressHeightY + halfWaveHeight); Offset controlPoint3 = Offset(waveOffset + radius * 2.5, waveProgressHeightY - halfWaveHeight); Offset controlPoint4 = Offset(waveOffset + radius * 3.5, waveProgressHeightY + halfWaveHeight); //完成path的链接 Path wavePath = Path() ..moveTo(point1.dx, point1.dy) ..quadraticBezierTo( controlPoint1.dx, controlPoint1.dy, point2.dx, point2.dy) ..quadraticBezierTo( controlPoint2.dx, controlPoint2.dy, point3.dx, point3.dy) ..quadraticBezierTo( controlPoint3.dx, controlPoint3.dy, point4.dx, point4.dy) ..quadraticBezierTo( controlPoint4.dx, controlPoint4.dy, point5.dx, point5.dy) ..lineTo(point6.dx, point6.dy) ..lineTo(point7.dx, point7.dy) ..close(); //完成绘制 canvas.drawPath(wavePath, paint); canvas.restore(); } 复制代码
- 按照第一步绘制波浪,方法同步骤 去掉颜色和偏移用第一波
- 的值画出圆形的过程内容。这一步注意,绘制进度时必须旋转画布。具体绘制内容如下
void drawCircleProgress( Canvas canvas, Offset center, double radius, Size size) { //画进度条圆框背景 canvas.drawCircle(center, radius, circleProgressBGPaint); //保存画布状态 canvas.save(); //逆时针旋转画布90度 canvas.rotate(degreeToRadian(-90)); canvas.translate( -(size.height + size.width) / 2, -(size.height - size.width) / 2); //画进度条圆框进度 canvas.drawArc( Rect.fromCircle(center: center, radius: radius), degreeToRadian(0), degreeToRadian(percent * 360), false, circleProgressPaint); //恢复画布状态 canvas.restore(); } 复制代码
绘制工作基本差不多完成了
让波浪在动
使用动画改变波浪的偏移值,重复动画。两个波浪的位移速度设置为不一致,让波浪显得更加协调
void initState() {
super.initState();
waveAnimation = AnimationController(
vsync: this,
duration: widget.waveAnimationDuration,
);
waveAnimation.addListener(waveAnimationListener);
lightWaveAnimation = AnimationController(
vsync: this,
duration: widget.lightWaveAnimationDuration,
);
//在lightWaveAnimationListener中获取波浪最新的偏移值,刷新状态
lightWaveAnimation.addListener(lightWaveAnimationListener);
waveAnimation.repeat();
lightWaveAnimation.repeat();
}
复制代码
波浪运动的效果做完之后,基本是一样的,但是有一个明显的问题,就是进度之后设置后,进度条中的波浪立即上升,看起来很不协调,因此,我们需要在进度变化时为进度条添加动画效果。
让波浪慢慢地上升和下降
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this, duration: widget.progressAnimatedDuration);
controller.addStatusListener((status) {
//当动画结束时重置动画
if (status == AnimationStatus.completed) {
progressAnimation.removeListener(handleProgressChange);
controller.reset();
}
});
}
@override
Widget build(BuildContext context) {
//当进度发生改变时,开始动画
if (currentValue != widget.value && !controller.isAnimating) {
progressAnimation =
controller.drive(IntTween(begin: currentValue, end: widget.value));
progressAnimation.addListener(handleProgressChange);
controller.forward();
}
...
}
复制代码
如果进度发生变化,我们使用动画将进度更改为给定的进度。这保证了当进度发生变化时,波浪不会立即上升。
作者:kevin燮
链接:https://juejin.im/post/5d008a4c518825668a3745ed
来源:掘金♶作者版权所有。商业转载请联系作者获得许可。非商业转载请注明来源。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。