112 lines
2.8 KiB
Dart
112 lines
2.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_animate/flutter_animate.dart';
|
|
|
|
enum AnimationTrigger {
|
|
onPageLoad,
|
|
onActionTrigger,
|
|
}
|
|
|
|
class AnimationInfo {
|
|
AnimationInfo({
|
|
required this.trigger,
|
|
required this.effectsBuilder,
|
|
this.loop = false,
|
|
this.reverse = false,
|
|
this.applyInitialState = true,
|
|
});
|
|
final AnimationTrigger trigger;
|
|
final List<Effect> Function()? effectsBuilder;
|
|
final bool applyInitialState;
|
|
final bool loop;
|
|
final bool reverse;
|
|
late AnimationController controller;
|
|
|
|
List<Effect>? _effects;
|
|
List<Effect> get effects => _effects ??= effectsBuilder!();
|
|
|
|
void maybeUpdateEffects(List<Effect>? updatedEffects) {
|
|
if (updatedEffects != null) {
|
|
_effects = updatedEffects;
|
|
}
|
|
}
|
|
}
|
|
|
|
void createAnimation(AnimationInfo animation, TickerProvider vsync) {
|
|
final newController = AnimationController(vsync: vsync);
|
|
animation.controller = newController;
|
|
}
|
|
|
|
void setupAnimations(Iterable<AnimationInfo> animations, TickerProvider vsync) {
|
|
for (var animation in animations) {
|
|
createAnimation(animation, vsync);
|
|
}
|
|
}
|
|
|
|
extension AnimatedWidgetExtension on Widget {
|
|
Widget animateOnPageLoad(
|
|
AnimationInfo animationInfo, {
|
|
List<Effect>? effects,
|
|
}) {
|
|
animationInfo.maybeUpdateEffects(effects);
|
|
return Animate(
|
|
effects: animationInfo.effects,
|
|
child: this,
|
|
onPlay: (controller) => animationInfo.loop
|
|
? controller.repeat(reverse: animationInfo.reverse)
|
|
: null,
|
|
onComplete: (controller) => !animationInfo.loop && animationInfo.reverse
|
|
? controller.reverse()
|
|
: null,
|
|
);
|
|
}
|
|
|
|
Widget animateOnActionTrigger(
|
|
AnimationInfo animationInfo, {
|
|
List<Effect>? effects,
|
|
bool hasBeenTriggered = false,
|
|
}) {
|
|
animationInfo.maybeUpdateEffects(effects);
|
|
return hasBeenTriggered || animationInfo.applyInitialState
|
|
? Animate(
|
|
controller: animationInfo.controller,
|
|
autoPlay: false,
|
|
effects: animationInfo.effects,
|
|
child: this)
|
|
: this;
|
|
}
|
|
}
|
|
|
|
class TiltEffect extends Effect<Offset> {
|
|
const TiltEffect({
|
|
super.delay,
|
|
super.duration,
|
|
super.curve,
|
|
Offset? begin,
|
|
Offset? end,
|
|
}) : super(
|
|
begin: begin ?? const Offset(0.0, 0.0),
|
|
end: end ?? const Offset(0.0, 0.0),
|
|
);
|
|
|
|
@override
|
|
Widget build(
|
|
BuildContext context,
|
|
Widget child,
|
|
AnimationController controller,
|
|
EffectEntry entry,
|
|
) {
|
|
Animation<Offset> animation = buildAnimation(controller, entry);
|
|
return getOptimizedBuilder<Offset>(
|
|
animation: animation,
|
|
builder: (_, __) => Transform(
|
|
transform: Matrix4.identity()
|
|
..setEntry(3, 2, 0.001)
|
|
..rotateX(animation.value.dx)
|
|
..rotateY(animation.value.dy),
|
|
alignment: Alignment.center,
|
|
child: child,
|
|
),
|
|
);
|
|
}
|
|
}
|