3D movement animation in Flutter

Issue

I am using Transform to have a 3D movement on a card. with onPanUpdate it moves all way until it tilts completely. How can I restrict or control the movement in a way that it goes half way at most when you touch any point close to the edges.
Here is how I applied Transform:

    Transform(
                      transform: Matrix4.identity()
                        ..setEntry(3, 2, 0.001) // perspective
                        ..rotateX(0.001 * _offset.dy) // changed
                        ..rotateY(-0.001 * _offset.dx), // changed
                      alignment: FractionalOffset.center,
                      child: GestureDetector(
                        onPanUpdate: (details) => setState(() =>
                                // Offset(-0.1, -0.1) < details.delta ||
                                //         details.delta < Offset(0.1, 0.1)
                                // ?
                                _offset += details.delta
                            // : _offset = _offset
                            ),
                        child: ReusableCard(),
                      ),
                    ),

Solution

I solved the issue by using physics-simulation concept. I added onPanStart and onPanEnd to the GestureDetector and also defining a controller to listen to changes and control the movement to be smooth

class ReusableCard extends StatefulWidget {

  @override
  _ReusableCardState createState() => _ReusableCardState();
}

class _ReusableCardState extends State<ReusableCard>
    with TickerProviderStateMixin {
  AnimationController _offsetController;
  Animation<Offset> _offsetAnimation;
  Offset _offset = Offset.zero;
  static const double limitParallaxOffset = 350;

  void _runOffsetAnimation() {
    _offsetAnimation = _offsetController.drive(Tween<Offset>(
      begin: _offset,
      end: Offset.zero,
    ));
    _offsetController.reset();
    _offsetController.forward();
  }

  @override
  void initState() {
    super.initState();

    _offsetController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 300));
    _offsetController.addListener(() {
      setState(() {
        _offset = _offsetAnimation.value;
      });
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Transform(
      transform: Matrix4.identity()
        ..setEntry(3, 2, 0.001) // perspective
        ..rotateX(0.001 * _offset.dy) // changed
        ..rotateY(-0.001 * _offset.dx), // changed
      alignment: FractionalOffset.center,
      child: GestureDetector(
        onPanStart: (details) {
          _offsetController.stop();
        },
        onPanUpdate: (details) {
          setState(() {
            Offset(-limitParallaxOffset, -limitParallaxOffset) < _offset &&
                    _offset < Offset(limitParallaxOffset, limitParallaxOffset)
                ? _offset += details.delta / 2
                : _offset = Offset.zero;
          });
        },
        onPanEnd: (details) {
          _runOffsetAnimation();
        },
        child: Container(
        decoration: BoxDecoration(
          boxShadow: [
            BoxShadow(
                color: Colors.blue,
                offset: Offset(0, 20),
                blurRadius: 30.0),
            ],
          ),
         height: 100,
         width: 100,
        ),
      ),
    );
  }
}

Answered By – Zahra

Answer Checked By – Mildred Charles (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.