Flutter Animation - Radial Menu at 60FPS

Fireship · Advanced ·🌐 Frontend Engineering ·7y ago

Key Takeaways

The video demonstrates how to create a complex radial menu in Flutter that can translate, scale, and rotate at 60 FPS, utilizing trigonometry for animation calculations and achieving smooth performance with the Flutter animation framework and performance tools.

Full Transcript

[Music] building a butter smooth UI is extremely important in the world of native apps it only takes a small amount of jank for people to think your app sucks that's why one of my favorite things about flutter is how beautifully it renders the animations we can use the built-in profiler to see that we easily achieve 60 frames per second even for this complex rotating radio menu in today's video you'll learn all about flutter animations by building this menu from scratch if you're new here like and subscribe and you can find the full source code on fire ship IL before we get started I have a confession to make in college I failed trigonometry I vividly remember scoring zero out of 100 points on the midterm and I probably didn't even take the final and that's not good because we need to use trigonometry in this video to determine where to place the different elements on the menu if we take a closer look at this menu we actually have ten different buttons stacked on top of each other the open and close buttons stay in the middle and then they scale up and down depending on whether or not the menu is opened or closed when opened all of the outer buttons will be translated or moved to a specific bearing from the center point this is where trig comes into play because we need to calculate a specific XY coordinate based on an angle from the center but don't worry too much about that it's actually a very easy calculation and this entire demo only takes about 150 lines of code which is pretty crazy and as a final touch will also add a rotation to the entire stack of buttons so that way it rotates clockwise when opening and counterclockwise when closing to get started you'll need to have a flutter app and then I also have vector math installed and optionally fun awesome for some better icons the material then if we go into our main dart file you can see that I'm importing dart math and then I'm importing radians from vector math and it's important to do the import like this because it has some conflicting classes with flutter now we'll go down here to our material app and we'll just add a scaffold and for this demo we'll just have the menu fill up the entire screen and for that we can use a sized box and have it expand to fill out the entire viewport and then the child for that box will be our custom radial menu widget when working with animations the first thing you usually start with is a stateful widget the only thing this widget is concerned with is defining the animation controller which itself controls the duration of the animation as well as the controls to tell it to play in forward or in Reverse what it doesn't control is the actual animation properties or the UI Oh that are being animated the first thing we'll do is add a mix into this class called the single ticker provider state mix in this will put the widget and ticker mode which makes animations possible the next thing we'll do is declare our animation controller and then we'll actually define it inside of the annette lifecycle hook the most important aspect of the animation controller is the duration at the end of the video we'll stagger animations which will all be relative to the duration that we define here so in this case the total duration of the animation is 900 milliseconds we also have to pass the this context to vsync which is just a piece of boilerplate for animation controllers in order to achieve 60 frames per second this animation controller will take every 16 milliseconds I haven't commented out here but you could add a listener to this controller and then set the state every time it takes but we'll be using an animated builder in the next step which makes this part unnecessary now we'll define the build method for this widget and you'll see it returns a radial animation widget which will define next just notice how it takes the animation controller as a property to its constructor we'll be using the same controller to orchestrate multiple different animations at the same time all of the animation logic will be handled by this radial animation widget in order for it to take the animation controller as an input property we add it to the constructor here and then call super from there we'll define the build method and it will start with an animated builder an animated builder takes two main arguments the first one is just the animation controller and the second one is a function to build the UI so basically every time the animation controller ticks it will run this builder function to rebuild all your widgets we can control the state of this animation bolt in the stateless widget or in the stateful widget above because this is a menu I want to make these methods a little more clear so I'm defining my own custom @ that's called open and closed open we'll run the animation and forward and then close we'll run the animation in Reverse now we can go up to our builder function and the first thing I'm going to define is a stack because remember all the buttons are just stacked on top of each other in the children array I'll go ahead and add two floating action buttons and because we're working with a stack only the last button should be visible that means you want the button that will open the menu initially to be the last item in the stack if we open this on a device we should see our blue open menu button and if we take that out of the stack then we'll see the close button that takes care of the initial setup now let's build the first animation that toggles open and close button for that we're going to zoom out a bit and go to the top of our radial animation button and first define a property called scale that is typed to an animation of a number then we'll define scale as a tween a tween is one of those words that always makes me nervous when I see it however they're actually very simple and they just translate to in between so you give it a starting value and an ending value and it will calculate everything in between in this case we're animating the scale of an element and by giving it a starting point of 1.5 it will be one hundred and fifty percent of its normal size and then at the end of the animation it will be zero percent or invisible the next thing we need to do is bind this tween to our actual animation controller that gives it an actual duration to know how to calculate the in-between values you could just pass then the animation controller directly here but more often than not you'll use a curved animation to make your animations a little more exciting I'm using fast out slow in but there's a lot of different curves you can experiment with here the last piece of this puzzle is determining where to apply this animation in the widget tree the scale animation is only going to apply to our open and close buttons in the middle flutter has this super useful thing called a transform widget and it has a few static methods to rotate scale and translate a child widget but it can also be used for super complex perspective based 3d animations so notice here how we've wrapped our floating action button in the transform scale and then for the scale argument we're passing at the scale value from the tween animation so that means every animation tick or every 16 milliseconds it will update the scale value of this element when it's animating now we'll go ahead and wrap the other button and transform scale as well but you'll notice right now they're both using the same animation so they'll be doing the same thing at the same time we could write an entirely different animation for each button but we can also be kind of clever here and instead just subtract one from the scale value which will give us the opposite animation for the closing button always see if you can be clever first before writing a bunch of extra code that completes the first animation if we open it up on a device we should see the button scaling in and out when clicked the next challenge is to create a whole bunch of buttons that pop out of the middle when the menu is activated we'll go back up to the constructor and add another animation that's very similar to our scale animation this time we'll go ahead and call it translation we'll give it a starting value of zero and an ending you have 100 then we'll defined a curved animation and then again make sure to experiment with the different curves you have a whole bunch of different options here now we definitely don't want to hard-code a bunch of floating action buttons one by one instead I'm writing a method called build button which will take an angle as an argument which is in degrees and it will also take an optional color and icon this is the part where a little bit of trigonometry is going to help us write very concise code what we want to do is translate each individual button at a specific angle from the center point of this menu this needs to be done in radians and not degrees but degrees are a lot easier to work with if you're a human being because it's easy to reason about a circle when you think of it in 360 degrees so the first thing we'll do is convert that angle argument to radians then we'll define a transform widget and that allows us to actually pass in a transformation matrix this is really cool because you can chain together different transformations by using darts double dot notation we're not going to do this today but in theory we could also chain together a scale and a rotation if we wanted to in this demo we're only concerned about the translation but we need to calculate the translation based on the X Y value from the center point of the circle we do that by taking the current translation value and then multiplying it by the cosine of the radians and will give us the x value and then to get the Y value we just take the sign of the radians and even as they failed trigonometry student I think I understand this and that's all it takes to calculate that translation the only other thing we have to do here is add a child widget which will just be a floating action button that will take our icon and background-color arguments now we can come back up to the widget tree to our stack and just call this button for every item that we want to add to the menu we'll put the first button at zero degrees the next one at 45 the next one at 90 and so on if you open up the app you should have an effect that looks like this at this point the buttons are going in and out but there's no rotation going on yet what I want to show you is how to rotate the entire widget stack but do it in a way that's offset from the main animation timeline this is what you would call a staggered animation first we'll set up another number tween and then we'll start at 0 and rotate around the entire circle to 360 degrees we can make this staggered by going into the curved animation and then instead of providing a curve will provide an interval this will tell the animation to start executing at a certain point in the animation timeline with the first value being 0 that means the we'll start right away but the second value is 0.7 which means it will end at 70 percent into the animation itself in other words the rotation animation will happen faster than the rest of the animation timeline and now the interval itself will take the actual curve argument so that takes care of the animation now let's come down to the widget tree and then we'll wrap the entire stack in the transform rotate method now the stack will become the child of this widget and then we'll set the angle value to the rotation value the angle is also based on radians so you'll want to do that conversion there if you're looking to do one full circle with 360 degrees now open up the demo on a device and you should have the super smooth 60 frame per second animation and if you don't believe me flutter has a built-in profiler so just run flutter run flag profile and you should see that you have plenty room to spare for even more animation and UI painting I'm gonna go ahead and wrap things up there if you have any UI elements from popular mobile apps that you might want to see clone on this channel let me know in the comments and if this video helped you please like and subscribe thanks for watching and I will talk to you soon [Music]

Original Description

Animate a complex radial menu 🥞 in Flutter at can translate, scale, and rotate at 60 FPS from scratch https://fireship.io/lessons/flutter-radial-menu-staggered-animations/ - Flutter Animation https://flutter.dev/docs/development/ui/animations - Flutter Performance https://flutter.dev/docs/testing/ui-performance #flutter #animation #butter
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from Fireship · Fireship · 0 of 60

← Previous Next →
1 Angular 4 Development and Production Environments with Firebase
Angular 4 Development and Production Environments with Firebase
Fireship
2 OAuth with Angular and Firebase Tutorial
OAuth with Angular and Firebase Tutorial
Fireship
3 Anonymous Authentication with Angular and Firebase - Lazy Registration
Anonymous Authentication with Angular and Firebase - Lazy Registration
Fireship
4 Angular Router Guards for Firebase Users
Angular Router Guards for Firebase Users
Fireship
5 Angular Firebase CRUD App with NoSQL Database Tutorial
Angular Firebase CRUD App with NoSQL Database Tutorial
Fireship
6 Upload Files from Angular to Firebase Storage
Upload Files from Angular to Firebase Storage
Fireship
7 How to Deploy an Angular App to Firebase Hosting
How to Deploy an Angular App to Firebase Hosting
Fireship
8 Sharing Data between Components in Angular
Sharing Data between Components in Angular
Fireship
9 Loading Spinners for Asynchronous Firebase Data
Loading Spinners for Asynchronous Firebase Data
Fireship
10 Angular 4 Transactional Email with Google Firebase Cloud Functions
Angular 4 Transactional Email with Google Firebase Cloud Functions
Fireship
11 Firebase Database Rules Tutorial
Firebase Database Rules Tutorial
Fireship
12 Autocomplete Search with Angular4 and Firebase
Autocomplete Search with Angular4 and Firebase
Fireship
13 Reddit Inspired Upvoting System with Angular and Firebase NoSQL
Reddit Inspired Upvoting System with Angular and Firebase NoSQL
Fireship
14 Angular Drag-and-Drop File Uploads to Firebase Storage
Angular Drag-and-Drop File Uploads to Firebase Storage
Fireship
15 Text Translation with Firebase Cloud Functions onWrite and Angular 4
Text Translation with Firebase Cloud Functions onWrite and Angular 4
Fireship
16 Custom Usernames with Firebase Authentication
Custom Usernames with Firebase Authentication
Fireship
17 Twitter-Inspired Follow Unfollow Feature with Firebase and Angular 4
Twitter-Inspired Follow Unfollow Feature with Firebase and Angular 4
Fireship
18 Simple Pagination with Firebase and Angular 4
Simple Pagination with Firebase and Angular 4
Fireship
19 How to Connect Firebase Users to their Data - 3 Methods
How to Connect Firebase Users to their Data - 3 Methods
Fireship
20 Add Toast Message Notifications to your Angular App
Add Toast Message Notifications to your Angular App
Fireship
21 Facebook-Inspired Reactions System with Angular and Firebase
Facebook-Inspired Reactions System with Angular and Firebase
Fireship
22 Learn NgModule in Angular with Examples
Learn NgModule in Angular with Examples
Fireship
23 Lazy Loading Components in Angular 4
Lazy Loading Components in Angular 4
Fireship
24 Stripe Checkout Payments with Angular and Firebase - Part 1
Stripe Checkout Payments with Angular and Firebase - Part 1
Fireship
25 Process Stripe Payments with Firebase Cloud Functions - Part 2
Process Stripe Payments with Firebase Cloud Functions - Part 2
Fireship
26 Selling Digital Content in Angular with Stripe Payments - Part 3
Selling Digital Content in Angular with Stripe Payments - Part 3
Fireship
27 Angular 4 Full Text Search with Algolia - Part 1
Angular 4 Full Text Search with Algolia - Part 1
Fireship
28 Algolia with Firebase Cloud Functions - Part 2
Algolia with Firebase Cloud Functions - Part 2
Fireship
29 Firebase Phone Authentication in Angular 4
Firebase Phone Authentication in Angular 4
Fireship
30 Top 7 RxJS Concepts for Angular Developers
Top 7 RxJS Concepts for Angular Developers
Fireship
31 Learn Angular Animations with 5 Examples
Learn Angular Animations with 5 Examples
Fireship
32 Advanced Firebase Data Filtering (Multi-Property)
Advanced Firebase Data Filtering (Multi-Property)
Fireship
33 Realtime Maps with Mapbox + Firebase + Angular
Realtime Maps with Mapbox + Firebase + Angular
Fireship
34 Angular Reactive Forms with Firebase Database Backend
Angular Reactive Forms with Firebase Database Backend
Fireship
35 Send Push Notifications in Angular with Firebase Cloud Messaging
Send Push Notifications in Angular with Firebase Cloud Messaging
Fireship
36 Top 7 Ways to Debug Angular 4 Apps
Top 7 Ways to Debug Angular 4 Apps
Fireship
37 Infinite Scroll with Angular and Firebase
Infinite Scroll with Angular and Firebase
Fireship
38 Use TypeScript with Firebase Cloud Functions
Use TypeScript with Firebase Cloud Functions
Fireship
39 Realtime Graphs and Charts with Plotly and Firebase
Realtime Graphs and Charts with Plotly and Firebase
Fireship
40 Role-Based User Permissions in Firebase
Role-Based User Permissions in Firebase
Fireship
41 User Presence System in Realtime - Online, Offline, Away
User Presence System in Realtime - Online, Offline, Away
Fireship
42 Location-based Queries with GeoFire and Angular Google Maps
Location-based Queries with GeoFire and Angular Google Maps
Fireship
43 Angular ngrx Redux Quick Start Tutorial
Angular ngrx Redux Quick Start Tutorial
Fireship
44 Angular Ngrx Effects with Firebase Database
Angular Ngrx Effects with Firebase Database
Fireship
45 Progressive Web Apps with Angular
Progressive Web Apps with Angular
Fireship
46 Angular Ngrx with Firebase Google OAuth User Authentication
Angular Ngrx with Firebase Google OAuth User Authentication
Fireship
47 RxJS Quick Start with Practical Examples
RxJS Quick Start with Practical Examples
Fireship
48 Send SMS Text Messages with Twilio and Firebase
Send SMS Text Messages with Twilio and Firebase
Fireship
49 Firebase Database Performance Profiling
Firebase Database Performance Profiling
Fireship
50 Native Desktop Apps with Angular and Electron
Native Desktop Apps with Angular and Electron
Fireship
51 Subscription Payments with Stripe, Angular, and Firebase
Subscription Payments with Stripe, Angular, and Firebase
Fireship
52 Firestore with AngularFire5 Quick Start Tutorial
Firestore with AngularFire5 Quick Start Tutorial
Fireship
53 Angular HTTP Client Quick Start Tutorial
Angular HTTP Client Quick Start Tutorial
Fireship
54 Google Sign-In with Firestore Custom User Data
Google Sign-In with Firestore Custom User Data
Fireship
55 Star Review System from Scratch with Firestore + Angular
Star Review System from Scratch with Firestore + Angular
Fireship
56 Angular Chatbot with Dialogflow (API.ai)
Angular Chatbot with Dialogflow (API.ai)
Fireship
57 Learn @ngrx/entity and Feature Modules
Learn @ngrx/entity and Feature Modules
Fireship
58 Infinite Scroll Pagination with Firestore
Infinite Scroll Pagination with Firestore
Fireship
59 Faster Firestore via Data Aggregation
Faster Firestore via Data Aggregation
Fireship
60 Contentful - CMS for Angular Progressive Web Apps
Contentful - CMS for Angular Progressive Web Apps
Fireship

This video teaches how to create a complex radial menu in Flutter that can translate, scale, and rotate at 60 FPS, covering key concepts such as trigonometry, animation controllers, and performance optimization. By following this tutorial, developers can learn how to design and implement custom UI widgets and achieve smooth animation performance in their Flutter apps.

Key Takeaways
  1. Add a scaffold to the main dart file
  2. Import dart math and radians from vector math
  3. Define the animation controller and its duration
  4. Pass the context to vsync
  5. Use an animated builder to orchestrate animations
  6. Define build method for RadialAnimation widget
  7. Add animation controller to RadialAnimation widget constructor
  8. Use Transform widget to apply scale animation to FABs
  9. Bind tween animation to animation controller with duration
  10. Wrap two buttons with transform scale
💡 To achieve smooth animation performance in Flutter, it's essential to utilize the Flutter animation framework and performance tools, such as the Flutter profiler, to optimize app performance and ensure that animations run at 60 FPS.

Related Reads

📰
Inside the Wayfair Frontend SDE-2 Interview: A Complete Breakdown
Learn how to prepare for a Frontend SDE-2 interview at Wayfair, including online assessments, machine coding, and system design.
Medium · Programming
📰
I Spent Two Years Maintaining a React SPA. HTMX Rebuilt It in a Week
Learn how HTMX rebuilt a React SPA in a week, replacing 2 years of maintenance work, and discover the benefits of this alternative approach
Medium · Programming
📰
The 5 Levels of Front End Engineering (And Where Most Developers Get Stuck)
Learn the 5 levels of front end engineering to improve your skills and avoid getting stuck in a career rut
Medium · Programming
📰
Browser-Based PDF Editing with Vue 3 and pdf-lib
Learn to build a browser-based PDF editor using Vue 3 and pdf-lib, enabling users to edit PDFs directly in the browser
Dev.to · sunshey
Up next
How to Use Semrush Keyword Magic Tool with ChatGPT to Make Money
Grow with Will - SEO, Sales & Entrepreneurship
Watch →