import 'dart:ui'; import 'package:flutter/material.dart'; /// 使用Shader实现的麦克风流动动画组件 class ShaderMicFlow extends StatefulWidget { final double size; final double amplitude; const ShaderMicFlow({ super.key, required this.size, this.amplitude = 0.0, }); @override State createState() => _ShaderMicFlowState(); } class _ShaderMicFlowState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; FragmentShader? _shader; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(seconds: 60), vsync: this, )..repeat(); _loadShader(); } Future _loadShader() async { try { final program = await FragmentProgram.fromAsset('shaders/mic_flow.frag'); setState(() { _shader = program.fragmentShader(); }); } catch (e) { debugPrint('Failed to load shader: $e'); } } @override void dispose() { _controller.dispose(); _shader?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SizedBox( width: widget.size, height: widget.size, child: AnimatedBuilder( animation: _controller, builder: (context, child) { return CustomPaint( painter: _shader != null ? _ShaderPainter( shader: _shader!, time: _controller.value * 60.0, amplitude: widget.amplitude, ) : null, size: Size.square(widget.size), ); }, ), ); } } class _ShaderPainter extends CustomPainter { final FragmentShader shader; final double time; final double amplitude; _ShaderPainter({ required this.shader, required this.time, required this.amplitude, }); @override void paint(Canvas canvas, Size size) { // 设置shader uniforms shader.setFloat(0, size.width); // u_resolution.x shader.setFloat(1, size.height); // u_resolution.y shader.setFloat(2, time); // u_time shader.setFloat(3, amplitude); // u_amp final paint = Paint()..shader = shader; canvas.drawRect(Offset.zero & size, paint); } @override bool shouldRepaint(covariant _ShaderPainter oldDelegate) { return oldDelegate.time != time || oldDelegate.amplitude != amplitude; } }