You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现SVG动画按钮:点击触发动画播放方案咨询

Flutter SVG动画按钮实现方案

步骤1:添加依赖

在pubspec.yaml中引入支持SVG动画的包,并声明资源路径:

dependencies:
  flutter:
    sdk: flutter
  flutter_svg: ^2.0.9 # 可替换为最新版本

assets:
  - assets/images/icons/
  - assets/animations/

步骤2:修改代码实现点击触发动画

替换原有的静态图片逻辑,引入动画控制器并绑定SVG播放:

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State createState() => _Home();
}

class _Home extends State<HomeScreen> with SingleTickerProviderStateMixin {
  Color background_color = Colors.red;
  final String _staticBamboo = 'assets/images/icons/OngQue.png';
  final String _animatedBamboo = 'assets/animations/OngQue.svg';
  
  late AnimationController _animationController;
  bool _isAnimating = false;

  @override
  void initState() {
    super.initState();
    // 初始化动画控制器,时长匹配你的SVG动画实际长度
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 1),
    );
  }

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

  void _playAnimation() {
    setState(() => _isAnimating = true);
    _animationController.forward().then((_) {
      // 动画结束后重置控制器,恢复静态图
      _animationController.reset();
      setState(() => _isAnimating = false);
    });
  }

  @override
  Widget build(BuildContext context) {
    final double bambooSize = MediaQuery.of(context).size.width * 0.9;

    return Container(
      color: background_color,
      child: Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          Flexible(
            child: GestureDetector(
              onTap: _playAnimation,
              child: _isAnimating
                  ? SvgPicture.asset(
                      _animatedBamboo,
                      width: bambooSize,
                      height: bambooSize,
                      allowDrawingOutsideViewBox: true,
                      // SVG加载时显示静态图作为占位
                      placeholderBuilder: (_) => Image.asset(
                        _staticBamboo,
                        width: bambooSize,
                        height: bambooSize,
                      ),
                      controller: _animationController,
                    )
                  : Image.asset(
                      _staticBamboo,
                      width: bambooSize,
                      height: bambooSize,
                    ),
            ),
          ),
          const SizedBox(height: 20),
        ],
      ),
    );
  }
}

关键说明

  • 使用flutter_svg包加载SVG动画:原生Image组件不支持SVG动画播放,该包支持SMIL格式的SVG动画。
  • 动画控制器管理播放状态:点击时触发动画向前播放,结束后重置控制器并切换回静态图,保证每次点击都能完整播放一次动画。
  • 用GestureDetector替代IconButton:更灵活控制点击区域,避免尺寸适配问题。

注意事项

  • 确保你的SVG动画是SMIL格式:CSS驱动的SVG动画无法被flutter_svg识别,需要提前转换为SMIL。
  • 同步动画时长:AnimationController的duration要和SVG动画的实际时长一致,避免播放不同步。
  • 资源路径正确:pubspec.yaml中必须声明SVG所在的assets目录,否则会出现加载失败。

内容的提问来源于stack exchange,提问作者ManDo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:01:04