Subscribe

Flutter 3D pan effect

✍️

Creating a 3D panning effect in Flutter

20 Aug, 2021 · 5 min read

A while ago, I found out about this super cool devcard from my fantastic colleagues at daily.dev.

I was inspired by the excellent 3D pan effect on the card and wanted to find out how to get this effect in Flutter.

The result for this article will be this super cool effect:

As the starting point, I’ll use my Flutter hello world application.

Creating the basic widget

Since our hello world app is rendering a stateless widget, we need to modify that part and make this a stateful widget.

The stateful widget allows us to re-render a new state, which we need to create the panning effect.

Modify the existing MyApp to become a stateful widget.

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

As for the state, we can create this basic state for now:

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter 3D Card'), // changed
      ),
      body: Center(
        child: Image(image: AssetImage('DailyDevTips.png')),
      ),
    );
  }
}

This will create a simple state that returns a local image to our screen.

However, we need to tell Flutter where it can render this particular image.

Adding local image assets in Flutter

To add local images in Flutter, create a local folder for it. I’ve created a assets folder at the root of my project.

Inside that, I put my image called DailyDevTips.png.

Then you need to edit your pubspec.yml file and add this asset under your flutter configuration.

flutter:
  assets:
    - assets/DailyDevTips.png

Now we can load the image using the AssetImage widget as you saw above.

Flutter local image loaded

However, this looks a bit cramped, right? What we can do is wrap the image in a fractional-sized box widget. This widget can take a fraction of the page and use that as the limit. The cool part about this is that it will adjust to all the different screens.

body: Center(
    child: FractionallySizedBox(
      widthFactor: 0.7,
      heightFactor: 0.9,
      child: Image(image: AssetImage('DailyDevTips.png')),
    ),
),

The fractions can be read as percentages meaning 70% of the width and 90% of the height.

In our case, this will result in this:

Flutter fractional sized box with image

Creating a 3D pan effect in Flutter

Now that we have our basic image setup, we can add our 3D pan effect.

The first thing we’ll need to do is add a basic offset variable in our state. We will use this offset to define the movement of the card.

Offset _offset = Offset.zero;

Then we can insert a transform widget that will allow us to modify the 3D properties.

body: Center(
    child: Transform(
      transform: Matrix4.identity()
        ..setEntry(3, 2, 0.001) // perspective
        ..rotateX(0.01 * _offset.dy) // changed
        ..rotateY(-0.01 * _offset.dx), // changed
      alignment: FractionalOffset.center,
      child: (
            // TODO
      ),
    ),
),

This will set our primary 3D object up. However, it won’t do anything and render zero on every axis.

The matrix identity is a 4-dimensional array containing four rows and four columns. If you want to read more about the concept and option, I found this article on advanced matrix 4 in Flutter super useful

To make this all work, we need to render a gesture detector as the child of this transform. This detector will update our offset and contain our image as the child.

child: GestureDetector(
    onPanUpdate: (details) => setState(() => _offset += details.delta),
    onDoubleTap: () => setState(() => _offset = Offset.zero),
    child: FractionallySizedBox(
      widthFactor: 0.7,
      heightFactor: 0.9,
      child: Image(image: AssetImage('DailyDevTips.png')),
    ),
),

As you can see, the pan update effect will re-render our state and give the offset the new modified offset values. Then we add a double-tap to reset our image to zero again. And this all wraps a child, which is the image we had before.

If we now reload our code, we can move the image around and see the cool 3D effect in action!

I hope you enjoyed this article and learned the basics of 3D effects in Flutter. I enjoyed trying this out, and my mind is already going wild with what we could do with this effect.

If you are looking for the complete code, you can find that on this GitHub branch.

Thank you for reading, and let’s connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Spread the knowledge with fellow developers on Twitter
Tweet this tip
Powered by Webmentions - Learn more

Read next 📖

Adding Auth0 to a Flutter application

22 Aug, 2021 · 14 min read

Adding Auth0 to a Flutter application

Creating dialogs in Flutter

21 Aug, 2021 · 6 min read

Creating dialogs in Flutter

Join 2099 devs and subscribe to my newsletter