Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animate only if the widgets are inside the ViewPort or visible portion of the screen [Web] #106

Open
TechSatya opened this issue Sep 15, 2023 · 7 comments
Labels
info needed Further information is required

Comments

@TechSatya
Copy link

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/

@arithmic-satya
Copy link

@gskinner any input, please?

@gskinner
Copy link
Owner

Sorry, I'm not totally clear on which are you asking for?

  1. It animates as soon as it is instantiated.
  2. It animates when it scrolls into view.

@gskinner gskinner added the info needed Further information is required label Nov 20, 2023
@arithmic-satya
Copy link

@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.

@ljoly83
Copy link

ljoly83 commented Dec 8, 2023

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),
      ),
    ]));
  }
}

@gskinner
Copy link
Owner

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.

@itanvation
Copy link

i dint understood could you please explain how to acheive this behaviour

@aji17766
Copy link

aji17766 commented Jan 1, 2025

did you find any solution? @TechSatya

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
info needed Further information is required
Projects
None yet
Development

No branches or pull requests

6 participants