0812
This commit is contained in:
113
lib/widgets/voice_animation.dart
Normal file
113
lib/widgets/voice_animation.dart
Normal file
@@ -0,0 +1,113 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class VoiceWaveAnimation extends StatefulWidget {
|
||||
const VoiceWaveAnimation({super.key});
|
||||
|
||||
@override
|
||||
State<VoiceWaveAnimation> createState() => _VoiceWaveAnimationState();
|
||||
}
|
||||
|
||||
class _VoiceWaveAnimationState extends State<VoiceWaveAnimation> with TickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// 创建一个持续动画控制器
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 1500),
|
||||
vsync: this,
|
||||
)..repeat();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (context, child) {
|
||||
return SizedBox(
|
||||
width: 160,
|
||||
height: 30,
|
||||
child: CustomPaint(
|
||||
painter: SineWavePainter(
|
||||
animation: _controller,
|
||||
count: 2, // 波浪数量
|
||||
color: Colors.white,
|
||||
amplitudeFactor: 0.5, // 波幅因子
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SineWavePainter extends CustomPainter {
|
||||
final Animation<double> animation;
|
||||
final int count; // 波浪数量
|
||||
final Color color;
|
||||
final double amplitudeFactor; // 波幅因子
|
||||
|
||||
SineWavePainter({
|
||||
required this.animation,
|
||||
this.count = 2,
|
||||
required this.color,
|
||||
this.amplitudeFactor = 1.0,
|
||||
});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final Paint paint = Paint()
|
||||
..color = color.withValues(alpha: 0.7)
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 2.0;
|
||||
|
||||
final Paint paint2 = Paint()
|
||||
..color = color.withValues(alpha: 0.3)
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 2.0;
|
||||
|
||||
final double width = size.width;
|
||||
final double height = size.height;
|
||||
final double centerY = height / 2;
|
||||
|
||||
// 绘制第一个波浪
|
||||
final path = Path();
|
||||
final path2 = Path();
|
||||
|
||||
// 创建两条不同相位的波形,一条主要一条次要
|
||||
path.moveTo(0, centerY);
|
||||
path2.moveTo(0, centerY);
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
// 主波形
|
||||
final double x = i.toDouble();
|
||||
final double normalizedX = (x / width) * count * 2 * pi;
|
||||
final double offset = 2 * pi * animation.value;
|
||||
|
||||
// 使用随机振幅变化模拟声音波动
|
||||
final double randomAmplitude = (sin(normalizedX + offset) + 1) / 2 * amplitudeFactor;
|
||||
path.lineTo(x, centerY - randomAmplitude * 10);
|
||||
|
||||
// 次波形,相位滞后
|
||||
final double randomAmplitude2 = (sin(normalizedX + offset + pi / 6) + 1) / 2 * amplitudeFactor;
|
||||
path2.lineTo(x, centerY - randomAmplitude2 * 5);
|
||||
}
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
canvas.drawPath(path2, paint2);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user