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

Scroll to Top during transition (not before or after) #605

Open
ChristopherJohnson25 opened this issue May 23, 2018 · 8 comments
Open

Scroll to Top during transition (not before or after) #605

ChristopherJohnson25 opened this issue May 23, 2018 · 8 comments

Comments

@ChristopherJohnson25
Copy link

ChristopherJohnson25 commented May 23, 2018

I'm trying to have my app scroll to top on every transition (traditional website style) and am having trouble doing this with liquid-outlet. Has anyone encountered this issue and found a solution (either with just liquid-outlet or pairing with another ember addon?). My usage of liquid-fire relies on this functionality and I cannot seem to find a work around anywhere. Thank You!!

@ChristopherJohnson25 ChristopherJohnson25 changed the title Scroll to Top during Scroll to Top during transition (not before or after) May 23, 2018
@chrism
Copy link
Contributor

chrism commented May 23, 2018

So, I'm not sure if this is the 'approved' method but I can explain what I did in my app to do this.

The transition I was using was a simple fade so I created a new transition based on that code which also included scrolling (as required).

This is the final code for the transition

transitions/between-screens.js

import {
  isAnimating,
  finish,
  timeSpent,
  animate,
  stop,
  Promise
} from "liquid-fire";
export default function betweenScreens(opts={}) {
  let firstStep;
  let outOpts = opts;
  let fadingElement = findFadingElement(this);

  if (fadingElement) {
    // We still have some older version that is in the process of
    // fading out, so out first step is waiting for it to finish.
    firstStep = finish(fadingElement, 'fade-out');
  } else {
    if (isAnimating(this.oldElement, 'fade-in')) {
      // if the previous view is partially faded in, scale its
      // fade-out duration appropriately.
      outOpts = { duration: timeSpent(this.oldElement, 'fade-in') };
    }
    stop(this.oldElement);
    firstStep = animate(this.oldElement, {opacity: 0}, outOpts, 'fade-out');
  }
  return firstStep.then(() => {
    return needsToScroll().then(() => {
      return animate(this.newElement, {opacity: [(opts.maxOpacity || 1), 0]}, opts, 'fade-in');
    });
  });
}

function needsToScroll() {
  let currentScroll = $('html').scrollTop();
  if (currentScroll > 1) {
    return window.$.Velocity($('html'), 'scroll', {duration: 500, offset: 0});
  } else {
    return Promise.resolve();
  }
}

function findFadingElement(context) {
  for (let i = 0; i < context.older.length; i++) {
    let entry = context.older[i];
    if (isAnimating(entry.element, 'fade-out')) {
      return entry.element;
    }
  }
  if (isAnimating(context.oldElement, 'fade-out')) {
    return context.oldElement;
  }
}

You can see that there is a method to check if the scroll is needed (I did this to avoid an extra unnecessary delay for screens already at the top).

For my use case I wanted the scroll to happen first, not at the same time—but I think you could just adapt the promise chain into a Promise.all to get them occurring at the same time.

@ChristopherJohnson25
Copy link
Author

@chrism looks good, could I see your file structure, not sure how to implement this to try. Thanks!

@chrism
Copy link
Contributor

chrism commented May 23, 2018

Sure, there should be a transitions folder in the root of you app folder, which then gets automatically picked up (though you might need to restart your server).

For naming I think you need to name the file the same as the transition name you give it (hyphened) and make sure the default function export is the same too.

After that you should just be able to use it like the pre-rolled transtions, like this.

transitions.js

export default function() {
  this.transition(
    this.toRoute([
      'your-route',
      'another-route'
    ]),
    this.use('betweenScreens')
  )
}

I think custom transitions are documented here if this isn't clear:
https://ember-animation.github.io/liquid-fire/transitions/defining

@ChristopherJohnson25
Copy link
Author

Great, thanks! This works. Still dealing with that pesky jump before transition. Thoughts on that?

@chrism
Copy link
Contributor

chrism commented May 23, 2018

Sorry, not sure what you mean by the pesky jump... I guess I don't encounter that issue because I scroll first?

@ChristopherJohnson25
Copy link
Author

It seems that anytime I try to transition from something below the fold liquid-outlet jumps up the page a bit, then transitions to top. I've encountered this issue with custom scroll to top workarounds, your workaround, and the ember-router-scroll add on.

@chrism
Copy link
Contributor

chrism commented May 23, 2018

Hmm — could that be an unrelated margin collapsing issue?

I seem to remember having something like that happen once... you could try removing all vertical margins in the content and see whether there is still that jump?

@ChristopherJohnson25
Copy link
Author

Good point, will try that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants