feat(animate): adds basic support for CSS animations on enter and leave
Closes #3876
This commit is contained in:
@ -86,6 +86,8 @@ import {APP_COMPONENT_REF_PROMISE, APP_COMPONENT} from './application_tokens';
|
||||
import {wtfInit} from './profile/wtf_init';
|
||||
import {EXCEPTION_BINDING} from './platform_bindings';
|
||||
import {ApplicationRef} from './application_ref';
|
||||
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
|
||||
import {BrowserDetails} from 'angular2/src/animate/browser_details';
|
||||
|
||||
var _rootInjector: Injector;
|
||||
|
||||
@ -161,6 +163,8 @@ function _injectorBindings(appComponentType): Array<Type | Binding | any[]> {
|
||||
Testability,
|
||||
AnchorBasedAppRootUrl,
|
||||
bind(AppRootUrl).toAlias(AnchorBasedAppRootUrl),
|
||||
BrowserDetails,
|
||||
AnimationBuilder,
|
||||
FORM_BINDINGS
|
||||
];
|
||||
}
|
||||
|
@ -451,6 +451,8 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
return element.dataset[name];
|
||||
}
|
||||
|
||||
getComputedStyle(elem) => elem.getComputedStyle();
|
||||
|
||||
// TODO(tbosch): move this into a separate environment class once we have it
|
||||
setGlobalVar(String path, value) {
|
||||
var parts = path.split('.');
|
||||
@ -465,6 +467,14 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
}
|
||||
obj[parts.removeAt(0)] = value;
|
||||
}
|
||||
|
||||
requestAnimationFrame(callback) {
|
||||
return window.requestAnimationFrame(callback);
|
||||
}
|
||||
|
||||
cancelAnimationFrame(id) {
|
||||
window.cancelAnimationFrame(id);
|
||||
}
|
||||
}
|
||||
|
||||
var baseElement = null;
|
||||
|
@ -317,8 +317,11 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
this.setAttribute(element, 'data-' + name, value);
|
||||
}
|
||||
getData(element, name: string): string { return this.getAttribute(element, 'data-' + name); }
|
||||
getComputedStyle(element): any { return getComputedStyle(element); }
|
||||
// TODO(tbosch): move this into a separate environment class once we have it
|
||||
setGlobalVar(path: string, value: any) { setValueOnPath(global, path, value); }
|
||||
requestAnimationFrame(callback): number { return window.requestAnimationFrame(callback); }
|
||||
cancelAnimationFrame(id: number) { window.cancelAnimationFrame(id); }
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,6 +133,9 @@ export class DomAdapter {
|
||||
resetBaseElement(): void { throw _abstract(); }
|
||||
getUserAgent(): string { throw _abstract(); }
|
||||
setData(element, name: string, value: string) { throw _abstract(); }
|
||||
getComputedStyle(element): any { throw _abstract(); }
|
||||
getData(element, name: string): string { throw _abstract(); }
|
||||
setGlobalVar(name: string, value: any) { throw _abstract(); }
|
||||
requestAnimationFrame(callback): number { throw _abstract(); }
|
||||
cancelAnimationFrame(id) { throw _abstract(); }
|
||||
}
|
||||
|
@ -412,6 +412,10 @@ class Html5LibDomAdapter implements DomAdapter {
|
||||
this.setAttribute(element, 'data-${name}', value);
|
||||
}
|
||||
|
||||
getComputedStyle(element) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
String getData(Element element, String name) {
|
||||
return this.getAttribute(element, 'data-${name}');
|
||||
}
|
||||
@ -420,4 +424,11 @@ class Html5LibDomAdapter implements DomAdapter {
|
||||
setGlobalVar(String name, value) {
|
||||
// noop on the server
|
||||
}
|
||||
|
||||
requestAnimationFrame(callback) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
cancelAnimationFrame(id) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
}
|
||||
|
@ -539,9 +539,12 @@ export class Parse5DomAdapter extends DomAdapter {
|
||||
getLocation(): Location { throw 'not implemented'; }
|
||||
getUserAgent(): string { return "Fake user agent"; }
|
||||
getData(el, name: string): string { return this.getAttribute(el, 'data-' + name); }
|
||||
getComputedStyle(el): any { throw 'not implemented'; }
|
||||
setData(el, name: string, value: string) { this.setAttribute(el, 'data-' + name, value); }
|
||||
// TODO(tbosch): move this into a separate environment class once we have it
|
||||
setGlobalVar(path: string, value: any) { setValueOnPath(global, path, value); }
|
||||
requestAnimationFrame(callback): number { return setTimeout(callback, 0); }
|
||||
cancelAnimationFrame(id: number) { clearTimeout(id); }
|
||||
}
|
||||
|
||||
// TODO: build a proper list, this one is all the keys of a HTMLInputElement
|
||||
|
@ -19,4 +19,6 @@ class Math {
|
||||
static num ceil(num a) => a.ceil();
|
||||
|
||||
static num sqrt(num x) => math.sqrt(x);
|
||||
|
||||
static num round(num x) => x.round();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {Inject, Injectable, OpaqueToken} from 'angular2/src/core/di';
|
||||
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
|
||||
import {isPresent, isBlank, RegExpWrapper, CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||
import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions';
|
||||
|
||||
@ -42,7 +43,7 @@ export class DomRenderer extends Renderer {
|
||||
* @private
|
||||
*/
|
||||
constructor(private _eventManager: EventManager,
|
||||
private _domSharedStylesHost: DomSharedStylesHost,
|
||||
private _domSharedStylesHost: DomSharedStylesHost, private _animate: AnimationBuilder,
|
||||
private _templateCloner: TemplateCloner, @Inject(DOCUMENT) document) {
|
||||
super();
|
||||
this._document = document;
|
||||
@ -94,7 +95,51 @@ export class DomRenderer extends Renderer {
|
||||
var previousFragmentNodes = resolveInternalDomFragment(previousFragmentRef);
|
||||
if (previousFragmentNodes.length > 0) {
|
||||
var sibling = previousFragmentNodes[previousFragmentNodes.length - 1];
|
||||
moveNodesAfterSibling(sibling, resolveInternalDomFragment(fragmentRef));
|
||||
let nodes = resolveInternalDomFragment(fragmentRef);
|
||||
moveNodesAfterSibling(sibling, nodes);
|
||||
this.animateNodesEnter(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through all nodes being added to the DOM and animates them if necessary
|
||||
* @param nodes
|
||||
*/
|
||||
animateNodesEnter(nodes: Node[]) {
|
||||
for (let i = 0; i < nodes.length; i++) this.animateNodeEnter(nodes[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs animations if necessary
|
||||
* @param node
|
||||
*/
|
||||
animateNodeEnter(node: Node) {
|
||||
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
|
||||
DOM.addClass(node, 'ng-enter');
|
||||
this._animate.css()
|
||||
.addAnimationClass('ng-enter-active')
|
||||
.start(<HTMLElement>node)
|
||||
.onComplete(() => { DOM.removeClass(node, 'ng-enter'); });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If animations are necessary, performs animations then removes the element; otherwise, it just
|
||||
* removes the element.
|
||||
* @param node
|
||||
*/
|
||||
animateNodeLeave(node: Node) {
|
||||
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
|
||||
DOM.addClass(node, 'ng-leave');
|
||||
this._animate.css()
|
||||
.addAnimationClass('ng-leave-active')
|
||||
.start(<HTMLElement>node)
|
||||
.onComplete(() => {
|
||||
DOM.removeClass(node, 'ng-leave');
|
||||
DOM.remove(node);
|
||||
});
|
||||
} else {
|
||||
DOM.remove(node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +149,9 @@ export class DomRenderer extends Renderer {
|
||||
}
|
||||
var parentView = resolveInternalDomView(elementRef.renderView);
|
||||
var element = parentView.boundElements[elementRef.renderBoundElementIndex];
|
||||
moveNodesAfterSibling(element, resolveInternalDomFragment(fragmentRef));
|
||||
var nodes = resolveInternalDomFragment(fragmentRef);
|
||||
moveNodesAfterSibling(element, nodes);
|
||||
this.animateNodesEnter(nodes);
|
||||
}
|
||||
|
||||
_detachFragmentScope = wtfCreateScope('DomRenderer#detachFragment()');
|
||||
@ -112,7 +159,7 @@ export class DomRenderer extends Renderer {
|
||||
var s = this._detachFragmentScope();
|
||||
var fragmentNodes = resolveInternalDomFragment(fragmentRef);
|
||||
for (var i = 0; i < fragmentNodes.length; i++) {
|
||||
DOM.remove(fragmentNodes[i]);
|
||||
this.animateNodeLeave(fragmentNodes[i]);
|
||||
}
|
||||
wtfLeave(s);
|
||||
}
|
||||
|
Reference in New Issue
Block a user