flutter如何实现歌词逐字渲染效果

在Flutter中如何实现类似音乐播放器的歌词逐字渲染效果?目前我尝试用RichText分段显示,但无法做到平滑的字与字之间的过渡动画。请问有没有成熟的方案或第三方库可以实现:

  1. 根据时间轴精确控制每个字的颜色渐变
  2. 支持卡拉OK式的逐字高亮效果
  3. 能同步音频播放进度实时更新渲染? 最好能提供核心代码片段或实现思路。
2 回复

使用CustomPaint自定义绘制,逐字解析歌词时间轴。通过AnimationController控制进度,在paint方法中根据时间戳计算当前应高亮的字符位置,使用TextPainter分段绘制不同颜色的文字即可实现逐字高亮效果。

更多关于flutter如何实现歌词逐字渲染效果的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现歌词逐字渲染效果,可以通过以下步骤实现:

核心思路

使用CustomPaint自定义绘制,结合动画控制器控制歌词逐字显示进度。

实现步骤

  1. 歌词数据准备 将歌词解析为包含每个字符和时间戳的列表。

  2. 自定义绘制组件 使用CustomPaint绘制歌词文本,根据当前播放进度计算已显示字符数。

  3. 动画控制 使用AnimationController同步播放进度,触发重绘。

示例代码

class LyricPainter extends CustomPainter {
  final String lyric;
  final double progress; // 0.0 ~ 1.0
  final TextStyle normalStyle;
  final TextStyle highlightStyle;

  LyricPainter({
    required this.lyric,
    required this.progress,
    required this.normalStyle,
    required this.highlightStyle,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final textPainter = TextPainter(
      textDirection: TextDirection.ltr,
    );

    double offsetX = 0;
    final totalChars = lyric.length;
    final highlightedChars = (totalChars * progress).round();

    for (int i = 0; i < totalChars; i++) {
      final char = lyric[i];
      final style = i < highlightedChars ? highlightStyle : normalStyle;
      
      textPainter.text = TextSpan(text: char, style: style);
      textPainter.layout();
      
      textPainter.paint(canvas, Offset(offsetX, 0));
      offsetX += textPainter.width;
    }
  }

  @override
  bool shouldRepaint(LyricPainter oldDelegate) {
    return lyric != oldDelegate.lyric || progress != oldDelegate.progress;
  }
}

// 使用示例
class LyricWidget extends StatefulWidget {
  @override
  _LyricWidgetState createState() => _LyricWidgetState();
}

class _LyricWidgetState extends State<LyricWidget> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  double _progress = 0.0;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 5), // 歌词总时长
      vsync: this,
    )..addListener(() {
        setState(() {
          _progress = _controller.value;
        });
      });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        CustomPaint(
          painter: LyricPainter(
            lyric: "这是示例歌词",
            progress: _progress,
            normalStyle: TextStyle(color: Colors.grey, fontSize: 20),
            highlightStyle: TextStyle(color: Colors.blue, fontSize: 20),
          ),
        ),
        Slider(
          value: _progress,
          onChanged: (value) {
            setState(() {
              _progress = value;
              _controller.value = value;
            });
          },
        ),
      ],
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

优化建议

  1. 性能优化:对于长文本,考虑使用TextSpan一次性绘制
  2. 时间轴同步:集成实际音频播放器的时间戳
  3. 布局处理:添加自动换行和居中显示逻辑
  4. 缓存机制:预计算字符位置减少实时计算

扩展功能

  • 添加字体缩放动画
  • 实现卡拉OK式的颜色填充效果
  • 支持多行歌词同步显示

通过调整progress数值即可控制歌词逐字渲染的进度,配合音频播放器即可实现完整的歌词同步效果。

回到顶部