Make 3D flip animation in Flutter

Learn Flutter from UI challenges

As a continuation of my first article, I am going to take a new challenge. This one will be a bit more complex than the previous (the shimmer). I call it a flip animation:

It’s good enough for a challenge, isn’t it? Yep, we are going to play with an animation running a likely 3-D effect.

How it works

At a first glance, the idea is simple: we have a stack of panels, each is broken into 2 halves, each half can rotate around X-axis and reveal a next one.

How to do it in code? I am going to divide it into 2 tasks:

  • Cut a panel into 2 halves
  • Rotate a half of panel around X-axis

So how does Flutter support us? Looking into Flutter document, I found two Widgets fit for our tasks: ClipRect and Transform.

Implementation

  • Cut a panel into 2 halves:

ClipRect widget has a clipper parameter to define the size and location of the clip rect but its document also suggests another way to use ClipRect, by combining it with an Align:

class FlipWidget extends StatelessWidget {
  Widget child;

  FlipWidget({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        ClipRect(
            child: Align(
          alignment: Alignment.topCenter,
          heightFactor: 0.5,
          child: child,
        )),
        Padding(
          padding: EdgeInsets.only(top: 2.0),
        ),
        ClipRect(
            child: Align(
          alignment: Alignment.bottomCenter,
          heightFactor: 0.5,
          child: child,
        )),
      ],
    );
  }
}

Try it out:

That’s it. Additionally, the child lets us freely design the content of our animation (a text, an image, no matter).

  • Rotate a half of panel around X-axis:

Transform widget has a transform parameter of type Matrix4 to define the kind of transform applied and Matrix4 exposes a factory constructor called rotationX(), it looks like what we need, let try it for the upper half of panel:

@override
Widget build(BuildContext context) {
   return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Transform(
          transform: Matrix4.rotationX(pi / 4),
          alignment: Alignment.bottomCenter,
          child: ClipRect(
              child: Align(
            alignment: Alignment.topCenter,
            heightFactor: 0.5,
            child: child,
          )),
        ),
        ...
      ],
    );
  }

 

Try it out:

What!!!! It looks like a scale effect, doesn’t it?

What’s wrong? Answer this question is the hardest point of this challenge. I turn to Flutter document, example codes, articles… and end up with this one. It points out that changing value at row 3 and column 2 of Matrix4 will change its perspective and bring up 3-D effect into our transformation:

...
Transform(
  transform: Matrix4.identity()..setEntry(3, 2, 0.006)..rotateX(pi / 4),
  alignment: Alignment.bottomCenter,
  child: ClipRect(
      child: Align(
    alignment: Alignment.topCenter,
    heightFactor: 0.5,
    child: child,
  )),
),
...

Try it out:

Cool. But what about the magic number of 0.006? To be honest, I don’t know how to calculate it exactly, just try some values and pick one I feel good.

The rest is to add animation for our widget. It needs a bit tricky here. In fact, each panel has content on both sides (front and back) but it’s silly to make it in code because there’s only one side visible at a moment. I assume we are going to create an animation that panels flip upward, so our animation turns out to be two phases (sequentially), the first is to flip the lower half upward to make the animation of revealing the lower half of a next panel while hiding the lower half of current panel, the second is to flip the upper half in the same direction to reveal the upper half of the next while hiding the upper half of the current:

The implementation code of this animation is quite long, it’s not a good idea to embed it here. You can find it in the link I put at the bottom of this article. Here’s our final result:

Awesome. We have just finished another UI challenge with Flutter. The more you practice, the better you become. I will keep looking new challenges, solve it with Flutter and share the results with you. Thanks for reading.

P/S: There’s something wrong in the perspective transform (causes the transformed image skewed), I use a very small value instead of zero for rotateX() to temporarily get around this matter.

Full source code: https://gist.github.com/hnvn/f1094fb4f6902078516cba78de9c868e

I’ve published my code as a package called flip_panel

Source: https://medium.com/flutter-community/make-3d-flip-animation-in-flutter-16c006bb3798

Written by

Medium member since Mar 2018

Mobile developer * Android * iOS * Flutter

Flutter Community

Flutter Community

Articles and Stories from the Flutter Community

Scroll al inicio

Si continuas utilizando este sitio aceptas el uso de cookies. más información

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar