import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_shaders/flutter_shaders.dart'; class VoiceMicFlow extends StatefulWidget { const VoiceMicFlow({super.key, this.size = 280, this.amp = 0.0}); final double size; final double amp; // 音量振幅 0.0-1.0 @override State createState() => _VoiceMicFlowState(); } class _VoiceMicFlowState extends State with SingleTickerProviderStateMixin { late final AnimationController _ctl; @override void initState() { super.initState(); _ctl = AnimationController( duration: const Duration(seconds: 100), // 100秒的长周期 vsync: this, )..repeat(); } @override void dispose() { _ctl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ClipOval( child: ShaderBuilder( assetKey: 'shaders/mic_flow.frag', (context, shader, child) { return AnimatedBuilder( animation: _ctl, builder: (_, __) { // 将0.0-1.0的动画值映射到更大的时间范围 final time = _ctl.value * 100.0; shader ..setFloat(0, widget.size) // u_resolution.x ..setFloat(1, widget.size) // u_resolution.y ..setFloat(2, time) // u_time ..setFloat(3, widget.amp); // u_amp (音量振幅) return CustomPaint( size: Size.square(widget.size), painter: _ShaderPainter(shader), ); }, ); }, // 着色器编译时的占位符 child: Container( width: widget.size, height: widget.size, decoration: const BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF1565C0), // 深蓝 Color(0xFFE3F2FD), // 浅蓝 ], ), ), ), ), ); } } class _ShaderPainter extends CustomPainter { _ShaderPainter(this.shader); final FragmentShader shader; @override void paint(Canvas canvas, Size size) { final paint = Paint()..shader = shader; canvas.drawRect(Offset.zero & size, paint); } @override bool shouldRepaint(covariant _ShaderPainter oldDelegate) => true; }