skip to Main Content

I’m trying to animate some images which should be orbited based on a circle.

example image

Here i1, i2, i3 and i4 are four image widgets which should change their position on any touch event in a clockwise way. As I’m new in flutter animation any kind of hints or explanation would be very helpful for me.

2

Answers


  1. I’m sure the Rotation Transition Widget can help you.
    Here’s a video for your reference.

    Login or Signup to reply.
  2. Thanks for your question.

    We can achieve this by using Flutter’s AnimationController and the dart:math library. I will share the sample workaround here.

    Two methods pop into my mind to achieve this, one is using custom UI and the other one is using the default Flutter framework widgets. I am going to use the Stack widget here.

    Create a StatefulWidget

    class OrbitingWidgets extends StatefulWidget {
      const OrbitingWidgets({super.key});
    
      @override
      State<OrbitingWidgets> createState() => _OrbitingWidgetsState();
    }
    
    class _OrbitingWidgetsState extends State<OrbitingWidgets>{
    
    late AnimationController _controller;
    @override
      void initState() {
        super.initState();
    
        // Create animation controller
        _controller = AnimationController(
          vsync: this,
          duration: Duration(seconds: 10), // Duration for one full rotation
        )..repeat();
    
      }
    
    
    @override
      Widget build(BuildContext context) {
        return Stack(
          children: [
            // Central dot
            Center(
              child: Container(
                width: 10,
                height: 10,
                decoration: const BoxDecoration(
                  color: Colors.red,
                  shape: BoxShape.circle,
                ),
              ),
            ),
            // Orbiting widgets will be here
          ],
        );
      }
    
     @override
     void dispose() {
       _controller.dispose();
       super.dispose();
     }
    
    }
    

    Next, create AnimatedBuilder

    Widget _buildOrbitingWidget(int index) {
        
        return AnimatedBuilder(
          animation: _controller,
          builder: (context, child) {
            double x = 0; // find the x displacement
            double y = 0; // find the y displacement
    
            return Positioned(
              left: MediaQuery.of(context).size.width / 2 + x,
              top: MediaQuery.of(context).size.height / 2 + y,
              child: Container(
                width: 20,
                height: 20,
                decoration: BoxDecoration(
                  color: Colors.blue,
                  shape: BoxShape.circle,
                ),
              ),
            );
          },
        );
      }
    

    Next find the x position and y position

        /// For finding the x and y  point of the circle's outline we are using the below equation
        final radius  = 100;
        double x = cos(angle + _controller.value * 2 * pi) * radius;
        double y = sin(angle + _controller.value * 2 * pi) * radius;
    

    Finally, we call the function in a for loop for as many children

      @override
      Widget build(BuildContext context) {
        return Stack(alignment: Alignment.center,
          children: [
            // Central dot
            Container(
              width: 10,
              height: 10,
              decoration: const BoxDecoration(
                color: Colors.red,
                shape: BoxShape.circle,
              ),
            ),
            // Orbiting widgets
            for (int i = 0; i < 10; i++) _buildOrbitingWidget(i),
          ],
        );
      }
    

    The above code is tested and working I will post a video here
    sample code demo

    You can optimize the code as you want. Also, you can implement it inside an InteractiveViewer if it is a big widget.

    You. can wrap it inside RepaintBoundary to crop the parts as you showed in the question.

    Thanks

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search