2 changed files with 162 additions and 7 deletions
@ -0,0 +1,144 @@ |
|||
import 'dart:math'; |
|||
|
|||
import 'package:flutter/material.dart'; |
|||
|
|||
class CircularFlowAnimation extends StatefulWidget { |
|||
const CircularFlowAnimation({super.key}); |
|||
|
|||
@override |
|||
State<CircularFlowAnimation> createState() => _CircularFlowAnimationState(); |
|||
} |
|||
|
|||
class _CircularFlowAnimationState extends State<CircularFlowAnimation> |
|||
with SingleTickerProviderStateMixin { |
|||
late AnimationController _controller; |
|||
|
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
_controller = AnimationController( |
|||
vsync: this, |
|||
duration: const Duration(seconds: 20), |
|||
)..repeat(); |
|||
} |
|||
|
|||
@override |
|||
void dispose() { |
|||
_controller.dispose(); |
|||
super.dispose(); |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return CustomPaint( |
|||
painter: CircularFlowPainter(_controller), |
|||
size: Size.infinite, |
|||
); |
|||
} |
|||
} |
|||
|
|||
class CircularFlowPainter extends CustomPainter { |
|||
final Animation<double> animation; |
|||
|
|||
CircularFlowPainter(this.animation) : super(repaint: animation); |
|||
|
|||
@override |
|||
void paint(Canvas canvas, Size size) { |
|||
final center = Offset(size.width / 2, size.height / 2); |
|||
const baseRadius = 150.0; |
|||
final time = animation.value * 2 * pi; |
|||
|
|||
// 绘制圆形路径 |
|||
_drawCircularPath(canvas, center, baseRadius); |
|||
|
|||
// 绘制三个围绕圆形运动的渐变云朵 |
|||
_drawOrbitingCloud( |
|||
canvas: canvas, |
|||
center: center, |
|||
time: time, |
|||
colors: [Colors.blue, Colors.purple], |
|||
orbitRadius: baseRadius, |
|||
speed: 0.5, |
|||
direction: 1, |
|||
); |
|||
|
|||
_drawOrbitingCloud( |
|||
canvas: canvas, |
|||
center: center, |
|||
time: time, |
|||
colors: [Colors.pink, Colors.orange], |
|||
orbitRadius: baseRadius * 0.8, |
|||
speed: 1.0, |
|||
direction: -1, |
|||
); |
|||
|
|||
_drawOrbitingCloud( |
|||
canvas: canvas, |
|||
center: center, |
|||
time: time, |
|||
colors: [Colors.green, Colors.yellow], |
|||
orbitRadius: baseRadius * 1.2, |
|||
speed: 0.3, |
|||
direction: 1, |
|||
); |
|||
|
|||
_drawOrbitingCloud( |
|||
canvas: canvas, |
|||
center: center, |
|||
time: time, |
|||
colors: [Colors.red, Colors.deepOrangeAccent], |
|||
orbitRadius: baseRadius * 0.5, |
|||
speed: 0.8, |
|||
direction: -1, |
|||
); |
|||
} |
|||
|
|||
void _drawCircularPath(Canvas canvas, Offset center, double radius) { |
|||
final paint = Paint() |
|||
..color = Colors.red |
|||
..style = PaintingStyle.stroke |
|||
..strokeWidth = 2 |
|||
..maskFilter = MaskFilter.blur(BlurStyle.normal, 4); |
|||
|
|||
canvas.drawCircle(center, radius, paint); |
|||
} |
|||
|
|||
void _drawOrbitingCloud({ |
|||
required Canvas canvas, |
|||
required Offset center, |
|||
required double time, |
|||
required List<Color> colors, |
|||
required double orbitRadius, |
|||
required double speed, |
|||
required int direction, |
|||
}) { |
|||
final angle = time * speed * direction; |
|||
final position = Offset( |
|||
center.dx + orbitRadius * cos(angle), |
|||
center.dy + orbitRadius * sin(angle), |
|||
); |
|||
|
|||
final gradient = RadialGradient( |
|||
colors: colors, |
|||
stops: const [0.3, 1.0], |
|||
radius: 0.6, |
|||
focal: Alignment( |
|||
0.1 + cos(angle * 2) * 0.3, |
|||
0.1 + sin(angle * 2) * 0.3, |
|||
), |
|||
); |
|||
|
|||
final paint = Paint() |
|||
..shader = gradient.createShader(Rect.fromCircle( |
|||
center: position, |
|||
radius: 100 + 30 * sin(time * 3), |
|||
)) |
|||
..maskFilter = MaskFilter.blur(BlurStyle.normal, 40) |
|||
..blendMode = BlendMode.plus; |
|||
|
|||
canvas.drawCircle(position, 80 + 20 * cos(time * 2), paint); |
|||
} |
|||
|
|||
@override |
|||
bool shouldRepaint(covariant CustomPainter oldDelegate) => true; |
|||
} |
|||
Loading…
Reference in new issue