Reputation: 9047
How to get a persistent tick at every frame refresh time. For example in Flame game engine update
method gets called at around every 1/60
seconds and a value dt
with elapsed time is passed.
I want to implement one simple animation where a fan will rotate. I want to change its rotation speed depending on user input. My idea is that at every tick I will rotate the fan image/ container at a fixed value. As the user increases the speed I will increase the multiplier. There are few options like using the Flame engine or Flare, but they seem overkill. Also, I can use SingleTickerProviderMixin
but there are few overheads like reverse the animation when finished and forwarded it and so...
I think there will be a simple solution, which will notify me at each frame refresh time that occurs at around every 1/60 seconds, and pass me the elapsed time dt
(around 167 mS or so).
Upvotes: 4
Views: 4185
Reputation: 506
Also you can use Stream.periodic()
.
Example from the documentation:
final stream = Stream<int>.periodic(
const Duration(seconds: 1),
(count) => count * count,
).take(5);
stream.forEach(print); // Outputs event values 0,1,4,9,16 every second
Upvotes: 0
Reputation: 495
I would also make sure to implement the dispose() callback if you copy this code. You need to make sure to cancel() any running timers to prevent odd behaviors or they will become a source of memory leaks.
The timer = null; is not always needed, but there are situations where the state object will hold a reference to the timer var itself and also cause a memory leak. For example, if you capture the timer var inside the timer callback body.
Example:
@override
void dispose() {
timer?.cancel();
timer = null;
super.dispose();
}
Upvotes: 2
Reputation: 2367
A nice way to do it (without Animation widgets), is to implement a Timer with a Stream; see the example below:
import 'package:flutter/material.dart';
import "dart:async";
const frequency = Duration(milliseconds: 50);
void main() => runApp(
MaterialApp(
home: Material(
child: Center(
child: Container(
color: Colors.white,
child: MyWidget(),
),
),
),
),
);
class MyWidget extends StatefulWidget {
MyWidgetState createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
final StreamController<double> _streamer =
StreamController<double>.broadcast();
Timer timer;
double _rotation = 0.0;
@override
void initState() {
super.initState();
timer = Timer.periodic(frequency, (t) {
_rotation++;
_streamer.add(1);
});
}
@override
Widget build(BuildContext context) {
return StreamBuilder<double>(
initialData: 0,
stream: _streamer.stream,
builder: (context, snapshot) {
return Transform(
transform: Matrix4.rotationZ(_rotation),
child: Text('Hello, World!'),
);
});
}
}
Upvotes: 5