La simulación física en Flutter es una manera hermosa de animar los componentes de la aplicación flutter para que se vea más realista e interactivo. Estos se pueden usar para crear una variedad de animaciones, como objetos que caen debido a la gravedad, o hacer que un contenedor parezca estar unido a un resorte. En este artículo, exploraremos lo mismo mediante la creación de una aplicación simple.
Siga los pasos a continuación para crear una simulación física simple en un widget:
- Desarrollar un controlador de animación.
- Usa gestos para el movimiento.
- Muestre la animación.
- Utilice la velocidad para simular el movimiento de salto.
Vamos a discutirlos en detalle:
Desarrollo de un controlador de animación:
Para crear el controlador de animación, cree un StatefulWidget llamado DraggableCard como se muestra a continuación:
Dart
import 'package:flutter/material.dart'; main() { runApp(MaterialApp(home: PhysicsCardDragDemo())); } class PhysicsCardDragDemo extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: DraggableCard( child: FlutterLogo( size: 128, ), ), ); } } class DraggableCard extends StatefulWidget { final Widget child; DraggableCard({this.child}); @override _DraggableCardState createState() => _DraggableCardState(); } class _DraggableCardState extends State<DraggableCard> { @override void initState() { super.initState(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Align( child: Card( child: widget.child, ), ); } }
Uso de gestos para el movimiento:
Aquí haremos que el widget se mueva cuando se arrastre en cualquier dirección. El movimiento se puede mapear usando un GestureDetector que maneja onPanEnd , onPanUpdate y onPanDown como se muestra a continuación:
Dart
@override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; return GestureDetector( onPanDown: (details) {}, onPanUpdate: (details) { setState(() { _dragAlignment += Alignment( details.delta.dx / (size.width / 2), details.delta.dy / (size.height / 2), ); }); }, onPanEnd: (details) {}, child: Align( alignment: _dragAlignment, child: Card( child: widget.child, ), ), ); }
Mostrar animación:
Use el campo Animation<Alignment> y el método _runAnimation para producir un efecto similar a un resorte como se muestra a continuación para mostrar la Animación:
Dart
Animation<Alignment> _animation; void _runAnimation() { _animation = _controller.drive( AlignmentTween( begin: _dragAlignment, end: Alignment.center, ), ); _controller.reset(); _controller.forward(); }
Ahora, siempre que el controlador de animación produzca un valor, actualice el campo _dragAlignment como se muestra a continuación:
Dart
@override void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: Duration(seconds: 1)); _controller.addListener(() { setState(() { _dragAlignment = _animation.value; }); }); }
Ahora, use el campo _dragAlignment para alinear el widget como se muestra a continuación:
Dart
child: Align( alignment: _dragAlignment, child: Card( child: widget.child, ), ),
Finalmente administre la Animación usando GestureDetector de la siguiente manera:
Dart
onPanDown: (details) { _controller.stop(); }, onPanUpdate: (details) { setState(() { _dragAlignment += Alignment( details.delta.dx / (size.width / 2), details.delta.dy / (size.height / 2), ); }); }, onPanEnd: (details) { _runAnimation(); },
Usando la velocidad para simular el movimiento de salto:
Primero, importe el paquete Physics como se muestra a continuación:
import 'package:flutter/physics.dart';
Ahora use el método animateWith() de AnimationController para crear un efecto similar a un resorte como se muestra a continuación:
Dart
void _runAnimation(Offset pixelsPerSecond, Size size) { _animation = _controller.drive( AlignmentTween( begin: _dragAlignment, end: Alignment.center, ), ); final unitsPerSecondX = pixelsPerSecond.dx / size.width; final unitsPerSecondY = pixelsPerSecond.dy / size.height; final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY); final unitVelocity = unitsPerSecond.distance; const spring = SpringDescription( mass: 30, stiffness: 1, damping: 1, ); final simulation = SpringSimulation(spring, 0, 1, -unitVelocity); _controller.animateWith(simulation); }
Finalmente, haga una llamada al método _runAnimation() con velocidad y tamaño como parámetro, como se muestra a continuación:
Dart
onPanEnd: (details) { _runAnimation(details.velocity.pixelsPerSecond, size); },
Código fuente completo:
Dart
import 'package:flutter/material.dart'; import 'package:flutter/physics.dart'; main() { runApp(MaterialApp(home: PhysicsCardDragDemo())); } class PhysicsCardDragDemo extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('GeeksForGeeks'), backgroundColor: Colors.green, ), body: DraggableCard( child: Container( width: 140, height: 140, decoration: BoxDecoration( color: Colors.green ), ) ), ); } } class DraggableCard extends StatefulWidget { final Widget child; DraggableCard({this.child}); @override _DraggableCardState createState() => _DraggableCardState(); } class _DraggableCardState extends State<DraggableCard> with SingleTickerProviderStateMixin { AnimationController _controller; Alignment _dragAlignment = Alignment.center; Animation<Alignment> _animation; void _runAnimation(Offset pixelsPerSecond, Size size) { _animation = _controller.drive( AlignmentTween( begin: _dragAlignment, end: Alignment.center, ), ); // evaluating velocity final unitsPerSecondX = pixelsPerSecond.dx / size.width; final unitsPerSecondY = pixelsPerSecond.dy / size.height; final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY); final unitVelocity = unitsPerSecond.distance; const spring = SpringDescription( mass: 30, stiffness: 1, damping: 1, ); final simulation = SpringSimulation(spring, 0, 1, -unitVelocity); _controller.animateWith(simulation); } @override void initState() { super.initState(); _controller = AnimationController(vsync: this); _controller.addListener(() { setState(() { _dragAlignment = _animation.value; }); }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; return GestureDetector( onPanDown: (details) { _controller.stop(); }, onPanUpdate: (details) { setState(() { _dragAlignment += Alignment( details.delta.dx / (size.width / 2), details.delta.dy / (size.height / 2), ); }); }, onPanEnd: (details) { _runAnimation(details.velocity.pixelsPerSecond, size); }, child: Align( alignment: _dragAlignment, child: Card( child: widget.child, ), ), ); } }
Producción:
Publicación traducida automáticamente
Artículo escrito por ddeevviissaavviittaa y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA