MatrixTransition

通过矩阵变换实现平滑过渡动画效果的组件

MatrixTransition是Flutter中的一个动画组件,用于通过矩阵变换(如平移、旋转、缩放)实现平滑的过渡动画效果。它基于Matrix4对象,允许开发者自定义复杂的2D或3D变换动画,适用于需要动态调整组件位置、大小或旋转 角度的场景。其核心逻辑是通过Animation<Matrix4>驱动矩阵插值,在动画过程中实时更新子组件的变换效果。

使用场景

  • 动态图标变换: 如图标从列表项平滑移动到详情页标题位置。
  • 卡片展开/折叠: 通过缩放矩阵实现卡片的展开动画。
  • 3D翻转效果: 结合旋转矩阵创建卡片正反面翻转的交互。
  • 游戏元素动画: 如角色移动时的平移和旋转组合变换。

示例

基础平移动画

import 'package:flutter/material.dart';

class BasicTranslationExample extends StatefulWidget {
  
  _BasicTranslationExampleState createState() => _BasicTranslationExampleState();
}

class _BasicTranslationExampleState extends State<BasicTranslationExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Matrix4> _animation;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true); // 循环反向播放

    // 创建从原点平移至 (100,100) 的矩阵动画
    _animation = Matrix4Tween(
      begin: Matrix4.identity(),
      end: Matrix4.identity()..translate(100.0, 100.0),
    ).animate(_controller);
  }

  
  Widget build(BuildContext context) {
    return MatrixTransition(
      animation: _animation,
      child: Container(
        width: 50,
        height: 50,
        color: Colors.blue,
        child: Icon(Icons.star, color: Colors.white),
      ),
    );
  }

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

交互式缩放旋转

class InteractiveExample extends StatefulWidget {
  
  _InteractiveExampleState createState() => _InteractiveExampleState();
}

class _InteractiveExampleState extends State<InteractiveExample> {
  double _scale = 1.0;
  double _rotate = 0.0;

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Slider(
          value: _scale,
          min: 0.5,
          max: 2.0,
          onChanged: (value) => setState(() => _scale = value),
        ),
        Slider(
          value: _rotate,
          min: 0,
          max: 6.28, // 2π弧度(360度)
          onChanged: (value) => setState(() => _rotate = value),
        ),
        MatrixTransition(
          animation: AlwaysStoppedAnimation<Matrix4>(
            Matrix4.identity()
              ..scale(_scale, _scale) // 缩放
              ..rotateZ(_rotate),     // 绕Z轴旋转
          ),
          child: Container(
            width: 100,
            height: 100,
            color: Colors.green,
            alignment: Alignment.center,
            child: Text('交互控制', style: TextStyle(color: Colors.white)),
          ),
        ),
      ],
    );
  }
}

主题适配的3D翻转

class ThemeFlipExample extends StatefulWidget {
  
  _ThemeFlipExampleState createState() => _ThemeFlipExampleState();
}

class _ThemeFlipExampleState extends State<ThemeFlipExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
  }

  void _flipCard() {
    if (_controller.status == AnimationStatus.completed) {
      _controller.reverse();
    } else {
      _controller.forward();
    }
  }

  
  Widget build(BuildContext context) {
    final matrixAnim = Matrix4Tween(
      begin: Matrix4.identity(),
      end: Matrix4.identity()..rotateY(3.14), // 绕Y轴旋转180度(π弧度)
    ).animate(_controller);

    return GestureDetector(
      onTap: _flipCard,
      child: MatrixTransition(
        animation: matrixAnim,
        child: Container(
          width: 150,
          height: 200,
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.primary,
            borderRadius: BorderRadius.circular(12),
          ),
          alignment: Alignment.center,
          child: Text(
            '点击翻转',
            style: TextStyle(
              color: Theme.of(context).colorScheme.onPrimary,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }

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

注意点

常见问题与解决方案

  • 性能瓶颈: 复杂矩阵变换(如透视投影)可能引发渲染性能下降。建议:
  • 对静态变换使用Transform组件而非MatrixTransition
  • 避免在动画中频繁更新矩阵(如每秒60次以上),可通过AnimationController控制帧率。
  • 子组件溢出: 变换后子组件可能超出父容器范围。解决方案:
  • ClipRect包裹MatrixTransition限制显示区域。
  • 矩阵顺序敏感: 矩阵操作(如先平移后旋转vs先旋转后平移)结果不同。务必确认操作顺序符合设计意图。

优化技巧

  • 使用Matrix4.identity()作为初始值,逐步叠加变换操作。
  • 通过Matrix4Tween插值生成动画矩阵,确保平滑过渡。
  • dispose时及时释放AnimationController防止内存泄漏。

最佳实践

  • 优先使用Transform组件实现简单静态变换,MatrixTransition专用于动态动画。
  • 测试动画在低端设备上的流畅度,必要时降低动画复杂度或时长。
  • 结合CurvedAnimation为矩阵变换添加缓动效果(如Curves.easeInOut)。

构造函数

MatrixTransition({
  Key? key,
  required Animation<Matrix4> animation,
  Widget? child,
})

属性

属性名属性类型说明
animationAnimation<Matrix4>核心属性:控制矩阵变换的动画对象,其值变化驱动组件更新。
childWidget?可选子组件,接受矩阵变换效果。若为 null,则渲染空组件。

关键属性解析

  • animation:

    • 必须为Animation<Matrix4>类型,通常通过Matrix4Tween生成。
    • 矩阵值变化时自动触发重绘,无需手动更新状态。
    • 支持与AnimationControllerCurvedAnimation结合控制动画行为。
  • child:

    • 变换仅应用于直接子组件,嵌套子组件会继承当前变换状态。
    • 若动画期间需切换子组件(如翻转后显示不同内容),建议将状态管理移至父组件。