ember-animation/liquid-fire

Scroll to Top during transition (not before or after)

Opened this issue · 8 comments

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!!

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.

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

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

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

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

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.

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?

Good point, will try that.