How To Create A Cylindrical Animation in Flutter

Before moving forward let’s see what are we building in this tutorial.

Such a cool animation, isn’t it.

Now let’s dive deep into the project.

Firstly let me talk about pre-requistes

Prerequisite

  • Basic knowledge of flutter
  • Desire to learn something new…..xD

Create A Cylindrical Animation with [ FULL CODE ]

STEP 1.

Create a Stateful Widget named – cylindrical_animation.dart

import 'package:flutter/material.dart';

class CylindricalAnimation extends StatefulWidget {
  @override
  _CylindricalAnimationState createState() => _CylindricalAnimationState();
}

class _CylindricalAnimationState extends State<CylindricalAnimation> {
  @override
  Widget build(BuildContext context) {
    return Scaffold();
  }
}

STEP 2.

Create another widget in the same class but this time it would be a Stateless Widget

class VerticalText extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

Step 3.

Paste the code below in VerticalText Widget, I will explain you in a minute

class VerticalText extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return RotatedBox(
        quarterTurns: 3,
        child: Text("FLUTTER",
          style: TextStyle(
              fontSize: 100,
              fontWeight: FontWeight.bold,
              color: Colors.white
          ),)
    );
  }
}

Explanation:

We created a Text Widget with the text we want to animate and wrapped it inside of an RotatedBox Widget.

To know more about RotatedBox Widget Watch this Video.

Also Read About: How To Use Retrofit Tutorial in Kotlin

Step 4.

Paste the code below in CylindricalAnimation Widget

class CylindricalAnimation extends StatefulWidget {
  @override
  _CylindricalAnimationState createState() => _CylindricalAnimationState();
}

class _CylindricalAnimationState extends State<CylindricalAnimation> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Color(0xff1b1c1e), // adding backgroud color
        body : VerticalText() // the widget we created now
    );
  }
}

You could see an output on screen like this.

How to create a cylindrical animation in flutter 1
Output 1.

Step 5.

Paste the code below in CylindricalAnimation Widget, I will explain you in a minute

class CylindricalAnimation extends StatefulWidget {
  @override
  _CylindricalAnimationState createState() => _CylindricalAnimationState();
}

class _CylindricalAnimationState extends State<CylindricalAnimation> {

  // Number of text we want in cylinder
  int numberOfVal = 6;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Color(0xff1b1c1e),
        body : Center(
          child: SizedBox.expand(
            child: Stack(
              alignment: Alignment.center,
              children: [
                ...List.generate(numberOfVal, (index){
                  return VerticalText();
                })
              ],
            ),
          ),
        )
    );
  }
}

Explanation

  1. Firstly we created a variable named numberOfVal – this is number of text widget we want to animate.
  2. Then we created a list of VerticalText Widget and put it inside the stack widget

So in the image below there are 5 more VerticalText Widget under this.

How to create a cylindrical animation in flutter 2
How To Create A Cylindrical Animation in Flutter 4

Step 6.

Wrap the Vertical Text Widget Inside Transform Widget with the following values

class CylindricalAnimation extends StatefulWidget {
  @override
  _CylindricalAnimationState createState() => _CylindricalAnimationState();
}

class _CylindricalAnimationState extends State<CylindricalAnimation> {

  // Number of text we want in cylinder
  int numberOfVal = 6;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Color(0xff1b1c1e),
        body : Center(
          child: SizedBox.expand(
            child: Stack(
              alignment: Alignment.center,
              children: [
                ...List.generate(numberOfVal, (index){
                  return Transform(
                      alignment: Alignment.center,
                      transform: Matrix4.identity()
                        ..setEntry(3, 2, 0.001) // This is for perception
                        ..rotateY(0) // This is the value we will animate
                        ..translate(-120.0),
                      child: VerticalText()
                  );
                })
              ],
            ),
          ),
        )
    );
  }
}

Here we used Matrix4.identity() function because it gives us whole controll over translate, rotate and scale transformation.

Along with this it gives us control over perception. If you want to know more about perception please let me know in the comments or you can view an article here.

setEntry(2,3,0.001) – This reduces lengths when the object goes farther away and increases them when they come nearer.

rotateY(0) – This is used to rotate the text along the Y axis, this is where the animation magic happens.

translate(-120.0) – This translate the text to the left side on x-axis by 120.0 px. You can play with this value.

How to create a cylindrical animation in flutter 3
How To Create A Cylindrical Animation in Flutter 5

Step 7.

Now let’s add an animation controller to the code, so firstly add SingleTickerProviderStateMixin to the stateful widget then initialising the controller in the widget initState(). also don’t forget to dispose the controller.

Note: Make sure you do a hot reload because we are adding code to initstate.

class _CylindricalAnimationState extends State<CylindricalAnimation> with SingleTickerProviderStateMixin {

  // Number of text we want in cylinder
  int numberOfVal = 6;

  //This is the animation controller
  AnimationController? _controller;

  @override
  void initState() {
    super.initState();
    // I chose duration to be 4 seconds you can play with it.
    //also making the animation repeat
    _controller = AnimationController(vsync: this,duration: Duration(seconds: 4))..repeat();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Color(0xff1b1c1e),
        body : Center(
          child: SizedBox.expand(
            child: Stack(
              alignment: Alignment.center,
              children: [
                ...List.generate(numberOfVal, (index){
                  return AnimatedBuilder(
                      animation: _controller!,
                      builder: (context, snapshot) {
                        return Transform(
                            alignment: Alignment.center,
                            transform: Matrix4.identity()
                              ..setEntry(3, 2, 0.001)
                              ..rotateY(0)
                              ..translate(-120.0),
                            child: VerticalText()
                        );
                      }
                  );
                })
              ],
            ),
          ),
        )
    );
  }
}

Step 8.

This is the final step and the step where magic happens…….

 @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Color(0xff1b1c1e),
        body : Center(
          child: SizedBox.expand(
            child: Stack(
              alignment: Alignment.center,
              children: [
                ...List.generate(numberOfVal, (index){
                  return AnimatedBuilder(
                      animation: _controller!,
                      builder: (context, snapshot) {
                        final animationValue = _controller!.value * (2 * pi / numberOfVal);
                        var rotation = (2 * pi * index/numberOfVal) + animationValue;

                        return Transform(
                            alignment: Alignment.center,
                            transform: Matrix4.identity()
                              ..setEntry(3, 2, 0.001)
                              ..rotateY(rotation)
                              ..translate(-120.0),
                            child: VerticalText()
                        );
                      }
                  );
                })
              ],
            ),
          ),
        )
    );
  }

NOTE: There is a detailed explanation of this code after the output so must read it to know how this is working.

Explanation:

Firstly focus on this line.

final animationValue = _controller!.value * (2 * pi / numberOfVal);

With the help of SingleTickerProviderStateMixin we are getting a new controller value at any instace of time.

Now – Circumference of a circle is 2*pi and we are dividing circumference of a circle in 6 equal parts because numberOfVal = 6.

Now the second line says

var rotation = (2 * pi * index/numberOfVal) + animationValue;

We are multiplying the circumference of a circle by the index of text in the list.

For Eg. – the rotaion of 1st VerticalText Widget would be = circumference of circle * 1/6.

Simillarly for 2nd Widget would be = circumference of circle * 2/6. and so on.

And by adding the animation value from the above code we get the rotation of the Vertical Text Widget.

Bounus Explaination:

You can see in the video above how the 6 VerticalText Widget are animating in a cylindrical path but you know “appearances can be deceptive“. If you see just one VerticalText Widget you will come to know that they are just rotating around a fixed Y-axis. See the video Below

To get Full source code you can visit this – Github Repo

If you like the article please star the repo also please follow me XD

Hot Topics

Related Articles