transition improvements

This commit is contained in:
Adam Bradley
2015-06-15 15:45:01 -05:00
parent 05fd7984f3
commit 5c72ff44c1
7 changed files with 59 additions and 65 deletions

View File

@ -1,6 +1,6 @@
import {CSS} from '../util/dom'; import {CSS, raf} from '../util/dom';
const RENDER_DELAY = 36; const RENDER_DELAY = 32;
let AnimationRegistry = {}; let AnimationRegistry = {};
/** /**
@ -17,10 +17,11 @@ let AnimationRegistry = {};
8) Run from/to animation on elements 8) Run from/to animation on elements
9) Animations finish async 9) Animations finish async
10) Set inline styles w/ the "to" effects on elements 10) Set inline styles w/ the "to" effects on elements
11) Add after classes to elements 11) Call onFinish()
12) Remove after classes from elements 12) Wait one rAF
13) Call onFinish() 13) Add after classes to elements
14) Resolve play()'s promise 14) Remove after classes from elements
15) Resolve play()'s promise
**/ **/
export class Animation { export class Animation {
@ -209,8 +210,11 @@ export class Animation {
children[i]._onFinish(); children[i]._onFinish();
} }
self._onFinish(); self._onFinish();
raf(() => {
self._onAfter();
resolve(); resolve();
}); });
});
} }
if (this._duration > RENDER_DELAY) { if (this._duration > RENDER_DELAY) {
@ -291,43 +295,48 @@ export class Animation {
_onFinish() { _onFinish() {
// after the animations have finished // after the animations have finished
const self = this; if (!this._isFinished) {
let i, j, ele; this._isFinished = true;
this.onFinish && this.onFinish();
if (!self._isFinished) { }
self._isFinished = true;
if (self.playbackRate() < 0) {
// reverse direction
for (i = 0; i < self._el.length; i++) {
ele = self._el[i];
for (j = 0; j < self._bfAdd.length; j++) {
ele.classList.remove(self._bfAdd[j]);
} }
for (j = 0; j < self._bfRmv.length; j++) { _onAfter() {
ele.classList.add(self._bfRmv[j]); // one requestAnimationFrame after onFinish happened
let i, j, ele;
for (i = 0; i < this._children.length; i++) {
this._children[i]._onAfter();
}
if (this.playbackRate() < 0) {
// reverse direction
for (i = 0; i < this._el.length; i++) {
ele = this._el[i];
for (j = 0; j < this._bfAdd.length; j++) {
ele.classList.remove(this._bfAdd[j]);
}
for (j = 0; j < this._bfRmv.length; j++) {
ele.classList.add(this._bfRmv[j]);
} }
} }
} else { } else {
// normal direction // normal direction
for (i = 0; i < self._el.length; i++) { for (i = 0; i < this._el.length; i++) {
ele = self._el[i]; ele = this._el[i];
for (j = 0; j < self._afAdd.length; j++) { for (j = 0; j < this._afAdd.length; j++) {
ele.classList.add(self._afAdd[j]); ele.classList.add(this._afAdd[j]);
} }
for (j = 0; j < self._afRmv.length; j++) { for (j = 0; j < this._afRmv.length; j++) {
ele.classList.remove(self._afRmv[j]); ele.classList.remove(this._afRmv[j]);
} }
} }
} }
self.onFinish && self.onFinish();
}
} }
pause() { pause() {

View File

@ -85,7 +85,9 @@ $content-padding: 10px !default;
opacity: 0; opacity: 0;
z-index: $z-index-click-block; z-index: $z-index-click-block;
transform: translate3d(-9999px, 0px, 0px); transform: translate3d(-9999px, 0px, 0px);
overflow: hidden;
//background: red;
//opacity: .3;
} }
.click-block-active { .click-block-active {

View File

@ -72,10 +72,8 @@ export class Navbar {
alignTitle() { alignTitle() {
// called after the navbar/title has had a moment to // called after the navbar/title has had a moment to
// finish rendering in their correct locations // finish rendering in their correct locations
const navbarEle = this._ele; const navbarEle = this._ele;
const innerTitleEle = this._innerTtEle || (this._innerTtEle = navbarEle.querySelector('.navbar-inner-title')); const titleEle = this._ttEle || (this._ttEle = navbarEle.querySelector('ion-title'));
const titleEle = this._ttEle || (this._ttEle = innerTitleEle.querySelector('ion-title'));
// don't bother if there's no title element // don't bother if there's no title element
if (!titleEle) return; if (!titleEle) return;
@ -87,9 +85,8 @@ export class Navbar {
if (titleStyle.textAlign !== 'center') return; if (titleStyle.textAlign !== 'center') return;
// get all the dimensions // get all the dimensions
const titleOffsetWidth = titleEle.offsetWidth;
const titleOffsetLeft = titleEle.offsetLeft; const titleOffsetLeft = titleEle.offsetLeft;
const titleOffsetRight = navbarEle.offsetWidth - (titleOffsetLeft + titleOffsetWidth); const titleOffsetRight = navbarEle.offsetWidth - (titleOffsetLeft + titleEle.offsetWidth);
let marginLeft = 0; let marginLeft = 0;
let marginRight = 0; let marginRight = 0;
@ -104,6 +101,7 @@ export class Navbar {
if ((marginLeft || marginRight) && margin !== this._ttMargin) { if ((marginLeft || marginRight) && margin !== this._ttMargin) {
// only do an update if it has to // only do an update if it has to
const innerTitleEle = this._innerTtEle || (this._innerTtEle = navbarEle.querySelector('.navbar-inner-title'));
innerTitleEle.style.margin = this._ttMargin = margin; innerTitleEle.style.margin = this._ttMargin = margin;
} }
} }

View File

@ -22,7 +22,7 @@ ion-navbar {
justify-content: space-between; justify-content: space-between;
order: $flex-order-toolbar-top; order: $flex-order-toolbar-top;
transform: translate3d(0px, -9999px, 0px); transform: translate3d(100%, 0px, 0px);
&.show-navbar { &.show-navbar {
transform: translate3d(0px, 0px, 0px); transform: translate3d(0px, 0px, 0px);
} }

View File

@ -122,8 +122,6 @@ export class ViewController {
opts.animate = (opts.animation !== 'none'); opts.animate = (opts.animation !== 'none');
this.transitionStart(opts);
// wait for the new item to complete setup // wait for the new item to complete setup
enteringItem.stage(() => { enteringItem.stage(() => {
@ -144,6 +142,13 @@ export class ViewController {
transAnimation.duration(0); transAnimation.duration(0);
} }
let duration = transAnimation.duration();
if (duration > 64) {
// block any clicks during the transition and provide a
// fallback to remove the clickblock if something goes wrong
ClickBlock(true, duration + 200);
}
// start the transition // start the transition
transAnimation.play().then(() => { transAnimation.play().then(() => {
@ -193,9 +198,6 @@ export class ViewController {
enteringItem.shouldCache = false; enteringItem.shouldCache = false;
enteringItem.willEnter(); enteringItem.willEnter();
// start the transition
this.transitionStart({ animate: true });
// wait for the new item to complete setup // wait for the new item to complete setup
enteringItem.stage(() => { enteringItem.stage(() => {
@ -283,13 +285,6 @@ export class ViewController {
return false; return false;
} }
transitionStart(opts) {
if (opts.animate) {
// block possible clicks during transition
ClickBlock(true, 520);
}
}
transitionComplete() { transitionComplete() {
this.items.forEach((item) => { this.items.forEach((item) => {

View File

@ -63,11 +63,11 @@ class IOSTransition extends Transition {
} else { } else {
// forward direction // forward direction
this.enteringView this.enteringView
.from(TRANSLATEX, '99%') .from(TRANSLATEX, OFF_RIGHT)
.from(OPACITY, 1); .from(OPACITY, 1);
this.enteringTitle this.enteringTitle
.from(TRANSLATEX, '97%'); .from(TRANSLATEX, OFF_RIGHT);
this.leavingView this.leavingView
.to(TRANSLATEX, OFF_LEFT) .to(TRANSLATEX, OFF_LEFT)

View File

@ -1,15 +1,9 @@
const CSS_CLICK_BLOCK = 'click-block-active'; const CSS_CLICK_BLOCK = 'click-block-active';
const DEFAULT_EXPIRE = 330; const DEFAULT_EXPIRE = 330;
let cbEle, fallbackTimerId; let cbEle, fallbackTimerId;
let isShowing = false; let isShowing = false;
function preventClick(ev) {
ev.preventDefault();
ev.stopPropagation();
}
function show(expire) { function show(expire) {
clearTimeout(fallbackTimerId); clearTimeout(fallbackTimerId);
fallbackTimerId = setTimeout(hide, expire || DEFAULT_EXPIRE); fallbackTimerId = setTimeout(hide, expire || DEFAULT_EXPIRE);
@ -23,10 +17,6 @@ function show(expire) {
cbEle = document.createElement('div'); cbEle = document.createElement('div');
cbEle.className = 'click-block ' + CSS_CLICK_BLOCK; cbEle.className = 'click-block ' + CSS_CLICK_BLOCK;
document.body.appendChild(cbEle); document.body.appendChild(cbEle);
cbEle.addEventListener('touchstart', preventClick);
cbEle.addEventListener('mousedown', preventClick);
cbEle.addEventListener('pointerdown', preventClick);
cbEle.addEventListener('MSPointerDown', preventClick);
} }
} }
} }