flutter_animate
flutter_animate copied to clipboard
Animate only if the widgets are inside the ViewPort or visible portion of the screen [Web]
I have multiple distinct widgets inside a column and every widget has some animation effects, upon the user reaching the respective widget by scrolling they will animate which I want, but before that, if they are hidden from the user's view part means not inside the viewport, then they will not animate.
But here the issue is they all are animating at once after the website loads.
Reference - https://www.stryve.online/
@gskinner any input, please?
Sorry, I'm not totally clear on which are you asking for?
- It animates as soon as it is instantiated.
- It animates when it scrolls into view.
@gskinner All the animations are instantiated at once after the website loads, so when I reach the animation attached widgets by scrolling down, nothing happens as those have already been instantiated in the website's initial load.
Yes it should be fine to animate only once it is visible. The first items list animate. The second, out of screen, doesn't.
class Page8 extends StatelessWidget {
List<Widget> items = List.generate(
3,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 100,
height: 100,
color: Colors.amber,
child: Text('Item $index'),
),
));
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(children: [
Row(
children: [...items]
.animate(interval: 600.ms)
.fadeIn(duration: 900.ms, delay: 300.ms)
.shimmer(blendMode: BlendMode.srcOver, color: Colors.white12)
.move(
begin: Offset(MediaQuery.of(context).size.width, 0),
curve: Curves.easeOutQuad),
),
const SizedBox(
height: 900,
),
// Don't animate when it become visible
Row(
children: [...items]
.animate(interval: 600.ms)
.fadeIn(duration: 900.ms, delay: 300.ms)
.shimmer(blendMode: BlendMode.srcOver, color: Colors.white12)
.move(
begin: Offset(MediaQuery.of(context).size.width, 0),
curve: Curves.easeOutQuad),
),
]));
}
}
It might be possible to create an Adapter that would handle this. I'm not sure that's the best choice, since adapters are intended to control the animation position directly, whereas this would just be playing/pausing. Sketch:
foo.animate(
// names TBD
// debounce = time to delay before playing
// threshold = how much needs to be onscreen?
adapter: OnScreenAdapter(debounce: 500.ms, threshold: 1.0)
).fadeIn()
Another option would be a simple helper class that wraps the child, and starts a controller when the item becomes visible on screen. This would likely be messier though, as it would require creating the controller externally, with all the baggage that involves (state, disposal, etc).
A final approach could be to have a helper method that can be called from (or passed to) onInit, that would manage it for you. Sketch:
// getOnScreenWatcher would return a function that accepts the controller from onInit
// pauses the animation, and sets everything up.
foo.animate(onInit: getOnScreenWatcher(debounce: 500.ms, etc)).fadeIn()
I'll add looking at these options to my backlog, but feel free to take a stab at a PR.
i dint understood could you please explain how to acheive this behaviour