googlearchive / core-animated-pages

Animated transitions between pages
https://www.polymer-project.org/docs/elements/core-elements.html#core-animated-pages
32 stars 37 forks source link

core-animated-page: call src.offsetTop after selection is made (so transition works using [active]). #52

Closed danbeam closed 9 years ago

danbeam commented 9 years ago

This allows developers to write code like:

.my-prepare-class [active] {
  /* start transition */
}
.my-go-class [active] {
  /* activate transition */
}

Currently the hack to force layout (src.offsetTop;) is applied AFTER the selection is applied, so transitions coalesce (and don't work) when [active] is used.

/cc @jklein24 @khorimoto

googlebot commented 9 years ago

Thanks for your pull request.

It looks like this may be your first contribution to a Google open source project, in which case you'll need to sign a Contributor License Agreement (CLA) at https://cla.developers.google.com/.

If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address. Check the information on your CLA or see this help article on setting the email on your git commits.

Once you've done that, please reply here to let us know. If you signed the CLA as a corporation, please let us know the company's name.

danbeam commented 9 years ago

Signed the CLA 3 days ago. /cc @ebidel

googlebot commented 9 years ago

CLAs look good, thanks!

morethanreal commented 9 years ago

It's intentional that we force layout before changing the selection, because the transitions included with this element (all extended from core-transition-pages) trigger the transition by adding activeClass and toggling "core-selected". That allows the same transition to run in both directions, ie. from unselected to selected, and vice versa.

Would this model work for your transitions?

danbeam commented 9 years ago

@morethanreal I'm not entirely sure what you mean, but are you implying we should we just kick offsetTop before and after the selection is applied?

khorimoto-zz commented 9 years ago

@morethanreal The problem being fixed by this CL is that the active attribute and core-selected class are not given a chance to be applied before the core-animated-pages' active class is applied.

Consider the following selectors:

:host(.scope-class) ::content > [active] {
  -webkit-transition: all 1s linear;
  background-color: black;
}

:host(.active-class.scope-class) ::content > [active] {
  background-color: white;
}

We would expect the following: 1) The host has the scope-class class applied, and the active page has the active attribute applied. 2) The first selector above draws the active page with a black background. 3) The host has the active-class class applied. 4) The second selector above causes the active page to transition its background from black to white.

However, because we do not force a layout between steps 2 and 3 above, both of the selectors are set in the same turn, and only one ends up applying. This results in no transition at all. An extra side effect (in addition to the UI showing the wrong thing) is that this means no transitionend event is fired, so the <core-animated-pages> does not officially finish its page transition until the 5-second timeout period.

So, we need to force a layout between steps 2 and 3. Do you think it makes sense to touch src.offsetTop in its current place AND in the place which this pull request dictates?

morethanreal commented 9 years ago

The element requires that you style the before and after states based on the selection state, ie. core-selected or active, instead of active-class and scope-class. active-class means "the transition is currently running", and "scope-class" means "the transition is being set up/is running".

This is important because the current transitions can run in reverse when you switch pages back and forth. In the above example, you would get a black to white transition when a page becomes active, but you don't get white to black when the page becomes inactive.

To transition from A to B:

  1. A is displayed, B is display:none.
  2. core-animated-pages displays A and B.
  3. scope-class gets applied. Generally this sets up A and B to the "from" state based on the selection status.
  4. Force layout to render A and B to the "from" state.
  5. Apply selection and active-class to trigger the transition.

Can you write the transition like this (similar to the included transitions, like slide-down)?

/* the before state of inactive->active is black */
:host(.scope-class) ::content > :not([active]) {
  background-color: black;
}

/* the after state of inactive->active is white */
:host(.scope-class) ::content > [active] {
  background-color: white;
}

/* apply transition attribute to start the transition */
:host(.active-class.scope-class) ::content > * {
  transition: all 1s linear;
}

I think the included transitions would not work if you layout between applying the selection and setting active-class, because the layout would draw the white background and there's nothing to transition to when you set active-class.

Is this okay for your use case? If not, I would like to understand it better so I can make better suggestions.

danbeam commented 9 years ago

we accomplished what we needed by inverting some of our logic (e.g. :not([active])). thanks for your help solving the problem.