You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
3.4 KiB
144 lines
3.4 KiB
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;
|
|
}
|
|
|