欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > Flutter动画—雷达扫描效果

Flutter动画—雷达扫描效果

2025/5/11 19:28:47 来源:https://blog.csdn.net/nonagontech/article/details/142091799  浏览:    关键词:Flutter动画—雷达扫描效果

前言

我们现在要用Flutter做一个雷达扫描的动画,如下图所示

需求分析

  • 需要在画布上画出三个同心圆和一个十字
  • 创建一个固定角度的圆弧
  • 圆弧做渐变色
  • 让圆弧动起来
  • 封装组件,将圆弧角度、圆弧颜色、几个同心圆与十字颜色

实现步骤

1.创建一3个同心圆与十字

class RingPainter extends CustomPainter {RingPainter();final double angle = 0;final Color radarViewColor = Colors.pink; //雷达扫描指针的颜色final int circleCount = 3; //雷达扫描添加瞄准的环数,暂时注销了final Paint _paint = Paint()..style = PaintingStyle.fill;@overridevoid paint(Canvas canvas, Size size) {var radius = min(size.width / 2, size.height / 2);Paint _bgPaint = Paint()..color = radarViewColor..strokeWidth = 1..style = PaintingStyle.stroke;//十字架部分canvas.drawLine(Offset(size.width / 2, size.height / 2 - radius),Offset(size.width / 2, size.height / 2 + radius),_bgPaint,);canvas.drawLine(Offset(size.width / 2 - radius, size.height / 2),Offset(size.width / 2 + radius, size.height / 2),_bgPaint,);//同心圆部分for (var i = 1; i <= circleCount; ++i) {canvas.drawCircle(Offset(size.width / 2, size.height / 2),radius * i / circleCount, _bgPaint);}canvas.save();canvas.restore();}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}class TextLiany extends StatefulWidget {const TextLiany({super.key});@overrideState<TextLiany> createState() => _TextLianyState();
}class _TextLianyState extends State<TextLiany> {@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Container(width: 300,height: 300,// child: RadarView(),child: CustomPaint(painter: RingPainter(),)),),);}
}

2.修改RingPainter类,画出一个90°圆弧,并且旋转30°

class RingPainter extends CustomPainter {RingPainter();final double angle = pi / 180 * 10;final Color radarViewColor = Colors.pink; //雷达扫描指针的颜色final int circleCount = 3; //雷达扫描添加瞄准的环数,暂时注销了final Paint _paint = Paint()..style = PaintingStyle.fill;@overridevoid paint(Canvas canvas, Size size) {var radius = min(size.width / 2, size.height / 2);Paint _bgPaint = Paint()..color = radarViewColor..strokeWidth = 1..style = PaintingStyle.stroke;//十字架部分canvas.drawLine(Offset(size.width / 2, size.height / 2 - radius),Offset(size.width / 2, size.height / 2 + radius),_bgPaint,);canvas.drawLine(Offset(size.width / 2 - radius, size.height / 2),Offset(size.width / 2 + radius, size.height / 2),_bgPaint,);//同心圆部分for (var i = 1; i <= circleCount; ++i) {canvas.drawCircle(Offset(size.width / 2, size.height / 2),radius * i / circleCount, _bgPaint);}canvas.save();double r = sqrt(pow(size.width, 2) + pow(size.height, 2));double startAngle = atan(size.height / size.width);Point p0 = Point(r * cos(startAngle), r * sin(startAngle));Point px = Point(r * cos(angle + startAngle), r * sin(angle + startAngle));canvas.translate((p0.x - px.x) / 2, (p0.y - px.y) / 2);canvas.rotate(angle);canvas.drawArc(Rect.fromCircle(center: Offset(size.width / 2, size.height / 2), radius: radius),0,pi / 180 * 90,true,_paint);canvas.restore();}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}

3.给圆弧设置渐变色,只需要给_paint添加渐变色即可

_paint.shader = ui.Gradient.sweep(Offset(size.width / 2, size.height / 2),[radarViewColor.withOpacity(.01), radarViewColor.withOpacity(.5)],[.0, 1.0],TileMode.clamp,.0,pi / 180 * 30);
class RingPainter extends CustomPainter {RingPainter();final double angle = pi / 180 * 10;final Color radarViewColor = Colors.pink; //雷达扫描指针的颜色final int circleCount = 3; //雷达扫描添加瞄准的环数,暂时注销了final Paint _paint = Paint()..style = PaintingStyle.fill;@overridevoid paint(Canvas canvas, Size size) {var radius = min(size.width / 2, size.height / 2);Paint _bgPaint = Paint()..color = radarViewColor..strokeWidth = 1..style = PaintingStyle.stroke;//十字架部分canvas.drawLine(Offset(size.width / 2, size.height / 2 - radius),Offset(size.width / 2, size.height / 2 + radius),_bgPaint,);canvas.drawLine(Offset(size.width / 2 - radius, size.height / 2),Offset(size.width / 2 + radius, size.height / 2),_bgPaint,);//同心圆部分for (var i = 1; i <= circleCount; ++i) {canvas.drawCircle(Offset(size.width / 2, size.height / 2),radius * i / circleCount, _bgPaint);}_paint.shader = ui.Gradient.sweep(Offset(size.width / 2, size.height / 2),[radarViewColor.withOpacity(.01), radarViewColor.withOpacity(.5)],[.0, 1.0],TileMode.clamp,.0,pi / 180 * 30);canvas.save();double r = sqrt(pow(size.width, 2) + pow(size.height, 2));double startAngle = atan(size.height / size.width);Point p0 = Point(r * cos(startAngle), r * sin(startAngle));Point px = Point(r * cos(angle + startAngle), r * sin(angle + startAngle));canvas.translate((p0.x - px.x) / 2, (p0.y - px.y) / 2);canvas.rotate(angle);canvas.drawArc(Rect.fromCircle(center: Offset(size.width / 2, size.height / 2), radius: radius),0,pi / 180 * 90,true,_paint);canvas.restore();}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}

4.创建动画,然后将旋转角度的angle从固定值转换成动画数值即可

class RingPainter extends CustomPainter {RingPainter({this.angle = pi / 180 * 10});final double angle;final Color radarViewColor = Colors.pink; //雷达扫描指针的颜色final int circleCount = 3; //雷达扫描添加瞄准的环数,暂时注销了final Paint _paint = Paint()..style = PaintingStyle.fill;@overridevoid paint(Canvas canvas, Size size) {var radius = min(size.width / 2, size.height / 2);Paint _bgPaint = Paint()..color = radarViewColor..strokeWidth = 1..style = PaintingStyle.stroke;//十字架部分canvas.drawLine(Offset(size.width / 2, size.height / 2 - radius),Offset(size.width / 2, size.height / 2 + radius),_bgPaint,);canvas.drawLine(Offset(size.width / 2 - radius, size.height / 2),Offset(size.width / 2 + radius, size.height / 2),_bgPaint,);//同心圆部分for (var i = 1; i <= circleCount; ++i) {canvas.drawCircle(Offset(size.width / 2, size.height / 2),radius * i / circleCount, _bgPaint);}_paint.shader = ui.Gradient.sweep(Offset(size.width / 2, size.height / 2),[radarViewColor.withOpacity(.01), radarViewColor.withOpacity(.5)],[.0, 1.0],TileMode.clamp,.0,pi / 180 * 30);canvas.save();double r = sqrt(pow(size.width, 2) + pow(size.height, 2));double startAngle = atan(size.height / size.width);Point p0 = Point(r * cos(startAngle), r * sin(startAngle));Point px = Point(r * cos(angle + startAngle), r * sin(angle + startAngle));canvas.translate((p0.x - px.x) / 2, (p0.y - px.y) / 2);canvas.rotate(angle);canvas.drawArc(Rect.fromCircle(center: Offset(size.width / 2, size.height / 2), radius: radius),0,pi / 180 * 90,true,_paint);canvas.restore();}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}class _TextLianyState extends State<TextLiany>with SingleTickerProviderStateMixin {late AnimationController _controller;late Animation<double> _animation;@overridevoid initState() {_controller =AnimationController(vsync: this, duration: const Duration(seconds: 3));_animation = Tween(begin: .0, end: pi * 2).animate(_controller);_controller.repeat();super.initState();}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Container(width: 300,height: 300,// child: RadarView(),child: AnimatedBuilder(animation: _animation,builder: (context, child) {return CustomPaint(painter: RingPainter(angle: _animation.value),);},)),),);}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词