This article explains 3 cool 3D animation effects.

Here’s what you want to achieve:

The 3D effect of Flutter is realized by the Transform component, there is no Transform effect implementation:

class TransformDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('3 d transform Demo'),
      ),
      body: Container(
        alignment: Alignment.center,
        color: Colors.white,
        child: Text('3 d transform Demo'),),); }}Copy the code

Add sliding event listening via the GestureDetector component:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('3 d transform Demo'),
    ),
    body: GestureDetector(
      onPanUpdate: (details) {
        print('$details');
      },
      child: Container(
        alignment: Alignment.center,
        color: Colors.white,
        child: Text('3 d transform Demo'),),),); }Copy the code

Add Transform to component into rotation:

@override
Widget build(BuildContext context) {
  returnTransform( transform: Matrix4.identity() .. setEntry(3.2.0.001)
        ..rotateX(pi/6)
        ..rotateY(pi/6),
      alignment: Alignment.center,
      child: Scaffold(
        appBar: AppBar(
          title: Text('3 d transform Demo'),
        ),
        body: GestureDetector(
          onPanUpdate: (details) {
          },
          child: Container(
            alignment: Alignment.center,
            color: Colors.white,
            child: Text('3 d transform Demo'),),),)); }Copy the code

Associate sliding offset with rotation:

class TransformDemo extends StatefulWidget {
  @override
  _TransformDemoState createState() => _TransformDemoState();
}

class _TransformDemoState extends State<TransformDemo> {
  double _rotateX = . 0;
  double _rotateY = . 0;

  @override
  Widget build(BuildContext context) {
    returnTransform( transform: Matrix4.identity() .. rotateX(_rotateX) .. rotateY(_rotateY), alignment: Alignment.center, child: Scaffold( appBar: AppBar( title: Text('3 d transform Demo'),
          ),
          body: GestureDetector(
            onPanUpdate: (details) {
              setState(() {
                _rotateX += details.delta.dy * .01;
                _rotateY += details.delta.dx * -.01;
              });
            },
            child: Container(
              alignment: Alignment.center,
              color: Colors.white,
              child: Text('3 d transform Demo'),),),)); }}Copy the code

Basically, 3D effect has been achieved, but the effect is rather stiff, especially when rotating vertically, the width of the far point and the near point on the screen is the same.

Add near large and far small effects:

Transform( transform: Matrix4.identity() .. setEntry(3.2.0.001).. rotateX(_rotateX) .. rotateY(_rotateY), ...Copy the code

Effect of books

The above effect is similar to the effect of turning a book.

Principle of implementation:

The left and right sides of the picture are cut into two parts, and the two pictures are divided into four new components, as shown below: 1, 2, 3 and 4

Code implementation:

_child1 = ClipRect(
  child: Align(
    alignment: Alignment.centerLeft,
    widthFactor: 0.5,
    child: child1,
  ),
);
_child2 = ClipRect(
  child: Align(
    alignment: Alignment.centerRight,
    widthFactor: 0.5,
    child: child1,
  ),
);

_child3 = ClipRect(
  child: Align(
    alignment: Alignment.centerLeft,
    widthFactor: 0.5,
    child: child2,
  ),
);

_child4 = ClipRect(
  child: Align(
    alignment: Alignment.centerRight,
    widthFactor: 0.5,
    child: child2,
  ),
);
Copy the code

Put the first picture on top of the second picture, first rotate component 2 from 0 to 90 degrees, and then rotate component 3 from -90 to 0 degrees, the code implementation:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Stack(
      children: [
        _child1,
        Transform(
          alignment: Alignment.centerRight,
          transform: Matrix4.identity()
            ..setEntry(3.2.0.001)
            ..rotateY(_animation1.value),
          child: _child3,
        ),
      ],
    ),
    Container(
      width: 3,
      color: Colors.white,
    ),
    Stack(
      children: [
        _child4,
        Transform(
          alignment: Alignment.centerLeft,
          transform: Matrix4.identity()
            ..setEntry(3.2.0.001)
            ..rotateY(_animation.value),
          child: _child2,
        )
      ],
    )
  ],
)
Copy the code

Animation controller Settings:

@override
void initState() {
  init();
  _controller =
      AnimationController(vsync: this, duration: Duration(seconds: 5))
        ..addListener(() {
          setState(() {});
        });
  _animation = Tween(begin: . 0, end: pi / 2)
      .animate(CurvedAnimation(parent: _controller, curve: Interval(. 0.. 5)));
  _animation1 = Tween(begin: -pi / 2, end: 0.0).animate(
      CurvedAnimation(parent: _controller, curve: Interval(. 5.1.0)));
  _controller.forward();
  super.initState();
}
Copy the code

Child1 and child2 are two kinds of images, with the codes as follows:

_FlipUpDemoState(
    Container(
      width: 300,
      height: 400,
      child: Image.asset(
        'assets/images/b.jpg',
        fit: BoxFit.cover,
      ),
    ),
    Container(
      width: 300,
      height: 400,
      child: Image.asset(
        'assets/images/c.jpeg',
        fit: BoxFit.cover,
      ),
    ))
Copy the code

The resulting effect is the beginning of the book flipping effect.

Above is the left and right page turning effect, the same as the up and down page turning effect:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    body: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Stack(
          children: [
            _upperChild1,
            Transform(
              alignment: Alignment.bottomCenter,
              transform: Matrix4.identity()
                ..setEntry(3.2.0.003)
                ..rotateX(_animation1.value),
              child: _upperChild2,
            ),
          ],
        ),
        SizedBox(
          height: 2,
        ),
        Stack(
          children: [
            _lowerChild2,
            Transform(
              alignment: Alignment.topCenter,
              transform: Matrix4.identity()
                ..setEntry(3.2.0.003)
                ..rotateX(_animation.value),
              child: _lowerChild1,
            )
          ],
        )
      ],
    ),
  );
}
Copy the code

communication

Old Meng Flutter blog address (330 controls usage) : laomengit.com