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

如何将senkuro.com网站的过渡动画迁移到Flutter中?

如何将senkuro.com的过渡动画迁移到Flutter

第一步:拆解目标动画的核心细节

要复刻动画,先精准分析senkuro.com上的过渡效果,你需要明确:

  • 触发场景:是页面跳转、组件状态切换还是元素交互时的过渡?
  • 动画属性变化:比如元素的透明度(opacity)、位移(translate)、缩放(scale)、旋转(rotate)这些维度的变化组合
  • 动画节奏:持续时长(比如300ms/500ms)、速度曲线(比如先快后慢、先慢后快,或者自定义的缓动曲线)
  • 层级关系:动画过程中元素的层级变化、是否有遮罩层联动

第二步:用Flutter的自定义动画能力实现

Flutter的动画系统足够灵活,完全可以复刻绝大多数Web端过渡效果,以下是核心实现方式:

1. 自定义页面级过渡(页面跳转场景)

如果是页面切换的过渡,放弃Material默认的PageRoute,用PageRouteBuilder完全自定义:

class CustomPageTransition extends PageRouteBuilder {
  final Widget page;

  CustomPageTransition({required this.page})
      : super(
          pageBuilder: (context, animation, secondaryAnimation) => page,
          transitionDuration: const Duration(milliseconds: 400), // 匹配原动画时长
          transitionsBuilder: (context, animation, secondaryAnimation, child) {
            // 这里组合动画:比如淡入+从右侧滑入
            final fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
              CurvedAnimation(parent: animation, curve: Curves.easeInOut),
            );
            final slideAnimation = Tween<Offset>(
              begin: const Offset(1.0, 0.0),
              end: Offset.zero,
            ).animate(
              CurvedAnimation(parent: animation, curve: Curves.decelerate),
            );

            return FadeTransition(
              opacity: fadeAnimation,
              child: SlideTransition(
                position: slideAnimation,
                child: child,
              ),
            );
          },
        );
}

// 使用方式
Navigator.push(context, CustomPageTransition(page: TargetPage()));

2. 局部元素过渡(组件状态切换场景)

如果是单个组件的状态变化过渡,用AnimatedBuilder或AnimatedWidget来控制:

class CustomElementTransition extends StatefulWidget {
  const CustomElementTransition({super.key});

  @override
  State<CustomElementTransition> createState() => _CustomElementTransitionState();
}

class _CustomElementTransitionState extends State<CustomElementTransition> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _scaleAnimation;
  late Animation<double> _opacityAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 300),
      vsync: this,
    );
    _scaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeOutBack),
    );
    _opacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller);
  }

  void triggerAnimation() {
    _controller.forward(from: 0.0);
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Opacity(
          opacity: _opacityAnimation.value,
          child: Transform.scale(
            scale: _scaleAnimation.value,
            child: child,
          ),
        );
      },
      child: GestureDetector(
        onTap: triggerAnimation,
        child: const Icon(Icons.star, size: 48),
      ),
    );
  }
}

3. 匹配自定义动画曲线

如果原动画的曲线不是Flutter内置的Curves,可以自定义Curve类来复刻:

class CustomEaseCurve extends Curve {
  @override
  double transform(double t) {
    // 根据原动画的曲线参数调整,比如用贝塞尔曲线公式
    return t * t * (3.0 - 2.0 * t); // 示例:自定义缓入缓出
  }
}

// 使用时替换CurvedAnimation的curve参数
CurvedAnimation(parent: animation, curve: CustomEaseCurve())

第三步:调试与对齐

  • 用Flutter DevTools的Animation Inspector查看动画的属性变化,对比原动画的时序
  • 逐步调整Duration、Tween的起始值、Curve参数,直到视觉效果与目标一致
  • 如果涉及复杂的层级遮罩,可以用Stack配合AnimatedOpacity或ClipPath实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 11:27:25