'How to implement Uniformly Accelerated Motion Formula into Flutter Animation
I tried to create a Flutter Web App that can simulate Uniformly Accelerated Motion. So, I create a circle as the simulation object and some buttons. When the user press the most right button and the most left button, it will change the value of x
and y
in Alignment()
so the circle will change its position. Then, for the double arrow button, if you press it, it should "launch" the circle to the right and to the left, back and forth, until _velocity
is equal to zero.
So I managed to create the method for the most right and the most left button, but I don't know how to create the method for the double arrow button. Here is what I've been doing:
CircleAvatar(
backgroundColor: Colors.grey[300],
child: IconButton(
color: Colors.black,
onPressed: () => {
Timer.periodic(Duration(milliseconds: _duration),
(timer) {
if (isRight) {
setState(_addXValue);
if (_xValue > 1) {
isRight = false;
}
} else {
setState(_reduceXValue);
if (_xValue < -1) {
isRight = true;
}
}
_duration++;
})
},
icon: const Icon(Icons.keyboard_double_arrow_right),
),
),
My idea was to create a Timer
function so it will change the circle position in a duration of time. I used Timer
because I thought I can update the duration at run-time so it will apply like Uniformly Accelerated Motion, which is the animation will start fast at the beginning and it will become slower as the time goes by until _velocity
is zero. So, for now I use a constant duration for the Timer
.
Here is my full source code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
double _xValue = 0.0;
double _yValue = 1.0;
double _degree = 0;
int _velocity = 300;
bool isRight = true;
int? _duration;
void _addXValue() {
if (_velocity > 0 && _duration != null) {
_velocity -= 1;
_xValue += 0.1;
_degree += 15;
_duration = _duration! + 1;
}
}
void _reduceXValue() {
if (_velocity > 0 && _duration != null) {
_velocity -= 1;
_xValue -= 0.1;
_degree -= 15;
_duration = _duration! + 1;
}
}
void _handleBallMovement(int _duration) {
Timer.periodic(Duration(milliseconds: _duration), (timer) {
if (isRight) {
setState(_addXValue);
if (_xValue > 1) {
isRight = false;
}
} else {
setState(_reduceXValue);
if (_xValue < -1) {
isRight = true;
}
}
});
}
@override
void initState() {
_duration = _velocity > 0
? ((_velocity / (_velocity * 0.01)) - (_velocity * 0.1) + 10).floor()
: 0;
super.initState();
}
@override
Widget build(BuildContext context) {
// int _duration = _velocity > 0
// ? ((_velocity / (_velocity * 0.01)) - (_velocity * 0.1) + 10).floor()
// : 0;
var ball = Padding(
padding: const EdgeInsets.symmetric(horizontal: 32.0),
child: AnimatedAlign(
duration: const Duration(milliseconds: 100),
alignment: Alignment(_xValue, _yValue),
child: Transform.rotate(
angle: _degree * math.pi / 180,
child: Container(
width: 100,
height: 100,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
child: const Center(
child: Text(
'BOLA INI BOI',
style: TextStyle(
fontSize: 8.0,
color: Colors.white,
),
),
),
),
),
),
);
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 800,
height: 600,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
),
),
child: ball,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
backgroundColor: Colors.grey[300],
child: IconButton(
color: Colors.black,
onPressed: () => setState(_reduceXValue),
icon: const Icon(Icons.arrow_left),
),
),
CircleAvatar(
backgroundColor: Colors.grey[300],
child: IconButton(
color: Colors.black,
onPressed: () => {},
icon: const Icon(Icons.keyboard_double_arrow_left),
),
),
Text("velocity: ${_velocity.toString()}"),
SizedBox(width: 30),
Text('xValue: ${_xValue.toString()}'),
SizedBox(width: 30),
Text('duration: $_duration'),
CircleAvatar(
backgroundColor: Colors.grey[300],
child: IconButton(
color: Colors.black,
onPressed: () => {
_handleBallMovement(_duration!)
// Timer.periodic(Duration(milliseconds: _duration),
// (timer) {
// if (isRight) {
// setState(_addXValue);
// if (_xValue > 1) {
// isRight = false;
// }
// _duration += 50;
// } else {
// setState(_reduceXValue);
// if (_xValue < -1) {
// isRight = true;
// }
// _duration += 50;
// }
// })
},
icon: const Icon(Icons.keyboard_double_arrow_right),
),
),
CircleAvatar(
backgroundColor: Colors.grey[300],
child: IconButton(
color: Colors.black,
onPressed: () => setState(_addXValue),
icon: const Icon(Icons.arrow_right),
),
),
],
)
],
),
),
);
}
}
Sorry for my bad english.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|