The first effect

The Draggable component is used for drag effects and the CurvedAnimation is used for composite animations

In the source

Use the GifImage plugin to control the time of GIF animation.

Flutter_gifimage: ^ 1.0.1Copy the code

use

DraggableAnimation(Duration: 5, landTime: 0.3, landDuration: 0.04, hover: Container(Width: 58, height: 84, child: GifImage( controller: GifController(vsync: this).. repeat(min: 0, max: 5, period: Duration(milliseconds: 500)), image: AssetImage("images/await.gif"), ), ), drag: Container( width: 54, height: 107, child: Image.asset("images/drag.gif"), ), fall: Container( width: 65, height: 108, child: Image.asset("images/fall.gif"), ), run: Container( width: 66, height: 120, child: GifImage( controller: GifController(vsync: this).. repeat(min: 0, max: 3, period: Duration(milliseconds: 300)), image: AssetImage("images/run.gif"), ), ), land: Container( width: 68, height: 90, child: GifImage( controller: GifController(vsync: this).. repeat(min: 0, max: 2, period: Duration(milliseconds: 200)), image: AssetImage("images/land.gif"), ), ), ),Copy the code

Realize the source

class DraggableAnimation extends StatefulWidget { final Widget hover; final Widget drag; final Widget fall; final Widget land; final Widget run; final int duration; final double landTime; final double landDuration; Const DraggableAnimation({Key Key, this.drag, // hover, // fall, // fall, this.land, Duration = 5, // Total duration of animation this.landTime = 0.3, // start time of animation this.landDuration = 0.1, }) : super(key: key); @override State<StatefulWidget> createState() { return DraggableAnimationState(); } } enum AnimationState { drag, fall, land, run } class DraggableAnimationState extends State<DraggableAnimation> with SingleTickerProviderStateMixin { AnimationState _state; bool _isAnimation = false; double _startLeft = 0; double _startBottom = 0; Size _containerSize = Size.zero; GlobalKey _keyContainer = GlobalKey(debugLabel: 'key_onTAINer '); GlobalKey _keyDragContainer = GlobalKey(debugLabel: 'key_drag_ontainer'); Map<AnimationState, Widget> _contentMap = Map(); AnimationController _animationController; Animation _dropAnimation; Animation _runAnimation; @override void initState() { super.initState(); _contentMap = { AnimationState.drag: widget.drag, AnimationState.fall: widget.fall, AnimationState.land: widget.land, AnimationState.run: widget.run, }; _animationController = AnimationController(duration: Duration(seconds: widget.duration), vsync: this) .. addListener(() { setState(() { _isAnimation = _animationController.isAnimating; if (_animationController.value <= widget.landTime) { _state = AnimationState.fall; } else if (_animationController.value >= widget.landTime + widget.landDuration) { _state = AnimationState.run; } else { _state = AnimationState.land; }}); }); } @override Widget build(BuildContext context) { return SafeArea( child: Stack( key: _keyContainer, children: <Widget>[ Positioned( child: Visibility( child: _draggableWidget(), visible: !_isAnimation, ), right: 0, top: 120, ), Positioned( left: _runAnimation?.value ?? 0, bottom: _dropAnimation?.value ?? 0, child: Visibility( visible: _isAnimation, child: _contentMap[_state] ?? Container(), ), ) ], ), ); } Widget _draggableWidget() { return Draggable( child: widget.hover ?? Container(), onDragStarted: () { if (_state ! = AnimationState.drag) { setState(() { _state = AnimationState.drag; }); } }, onDraggableCanceled: (Velocity velocity, Offset offset) { RenderBox renderContainer = _keyContainer.currentContext.findRenderObject(); _containerSize = renderContainer.size; var containerPosition = renderContainer.localToGlobal(Offset.zero); final RenderBox renderBoxRed = _keyDragContainer.currentContext.findRenderObject(); var position = renderBoxRed.localToGlobal(Offset.zero); var size = renderBoxRed.size; _startLeft = position.dx; _startBottom = _containerSize.height - position.dy - size.height + containerPosition.dy; if (_containerSize.width - _startLeft < 2 * size.width) { return; } _startAnimation(); }, childWhenDragging: Container(), feedback: Container( child: widget.drag ?? Container(), key: _keyDragContainer, ), ); } void _startAnimation() {_dropAnimation = Tween<double>(begin: _startBottom, end: 0). Animate (CurvedAnimation(parent: _animationController, Curve: Interval(0.0, widget.landTime, curve: Curves.easeInCubic), )); _runAnimation = Tween<double>(begin: _startLeft, end: _containerSize.width).animate(CurvedAnimation( parent: _animationController, Curve: Interval(Widget.landTime + Widget.landDuration, 1.0, Curve: Curves. EaseOut),); _animationController.reset(); _animationController.forward(); }}Copy the code