Skip to content
This repository has been archived by the owner on Feb 2, 2019. It is now read-only.

Commit

Permalink
feat(util): add Animate class for css and typescript based animations
Browse files Browse the repository at this point in the history
 - implement an enter/leave set of functions similar to angular 1.x for applying/removing CSS classes with animations on them given their existing durations.
 - implement a setStyles/animateStyles set of functions for controlling the transition of styles over a given duration. This is similar to the described coming NG2 Animate usage (https://www.youtube.com/watch?v=izp5N2eeogg)
  • Loading branch information
justindujardin committed Dec 19, 2015
1 parent d6653f7 commit 99a4abc
Showing 1 changed file with 132 additions and 0 deletions.
132 changes: 132 additions & 0 deletions ng2-material/core/util/animate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import {DOM} from 'angular2/src/platform/dom/dom_adapter';

/**
* Provide an API for animating elements with CSS transitions
*/
export class Animate {

/**
* Look up the transition event name for the browser type and cache it.
*/
static TRANSITION_EVENT: string = Animate.whichTransitionEvent();

static enter(el: HTMLElement, cssClass: string): Promise<void> {
DOM.removeClass(el, cssClass);
return new Promise<void>((resolve)=> {
var duration = Animate.getTransitionDuration(el, true);
var callTimeout = setTimeout(() => done(), duration);
var done = () => {
clearTimeout(callTimeout);
removeListener();
resolve();
};
let removeListener = DOM.onAndCancel(el, Animate.TRANSITION_EVENT, done);
DOM.addClass(el, cssClass);
});
}

static leave(el: HTMLElement, cssClass: string): Promise<void> {
return new Promise<void>((resolve)=> {
var duration = Animate.getTransitionDuration(el, true);
var callTimeout = setTimeout(() => done(), duration);

var done = () => {
clearTimeout(callTimeout);
removeListener();
resolve();
};
let removeListener = DOM.onAndCancel(el, Animate.TRANSITION_EVENT, done);
DOM.removeClass(el, cssClass);
});
}

/**
* Get the duration of any transitions being applied to the given element.
*
* Based on: https://gist.github.com/snorpey/5323028
* @param element The element to query
* @param includeDelay Include any specified transition-delay value.
* @returns {number}
*/
static getTransitionDuration(element: HTMLElement, includeDelay: boolean = false) {
var prefixes = ['moz', 'webkit', 'ms', 'o', 'khtml'];
var style: any = window.getComputedStyle(element);
for (let i = 0; i < prefixes.length; i++) {
let duration = style['-' + prefixes[i] + '-transition-duration'];
if (!duration) {
continue;
}
duration = ( duration.indexOf('ms') > -1 ) ? parseFloat(duration) : parseFloat(duration) * 1000;
if (includeDelay) {
var delay = style['-' + prefixes[i] + '-transition-delay'];
if (typeof delay !== 'undefined') {
duration += ( delay.indexOf('ms') > -1 ) ? parseFloat(delay) : parseFloat(delay) * 1000;
}
}
return duration;
}
return -1;
}

static setTransitionDuration(element: HTMLElement, delayMs: number) {
DOM.setStyle(element, 'transition-duration', `${delayMs}ms`);
}

/* From Modernizr */
static whichTransitionEvent(): string {
var t: string;
var el: any = document.createElement('fakeelement');
var transitions: {[prefix:string]:string} = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};

for (t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
}

static animateStyles(element: HTMLElement, styles: {[style:string]:string|number}, durationMs: number): Promise<void> {
let saveDuration = Animate.getTransitionDuration(element);
Animate.setTransitionDuration(element, durationMs);
return new Promise<void>((animResolve, animReject) => {
let callTimeout = setTimeout(() => done(), durationMs);

let done = () => {
clearTimeout(callTimeout);
removeListener();
if (saveDuration !== -1) {
Animate.setTransitionDuration(element, saveDuration);
}
animResolve();
};
let removeListener = DOM.onAndCancel(element, Animate.TRANSITION_EVENT, done);
Object.keys(styles).forEach((key: string) => {
DOM.setStyle(element, key, `${styles[key]}`);
});

});
}

/**
* Set CSS styles immediately by turning off transition duration and restoring it afterward
*/
static setStyles(element: HTMLElement, styles: {[style:string]:string|number}): Promise<void> {
let saveDuration = Animate.getTransitionDuration(element);
Animate.setTransitionDuration(element, 0);
return new Promise<void>((resolve, reject) => {
Object.keys(styles).forEach((key: string) => {
DOM.setStyle(element, key, `${styles[key]}`);
});
if (saveDuration !== -1) {
Animate.setTransitionDuration(element, saveDuration);
}
resolve();
});
}

}

0 comments on commit 99a4abc

Please sign in to comment.