Implemented #1102: Ability to specify an animation easing, i.e. curve in a platform-independent manner.

This commit is contained in:
Rossen Hristov
2015-11-16 15:20:56 +02:00
parent 52ab4f85e3
commit c4c92efd8e
8 changed files with 92 additions and 7 deletions

View File

@ -5,6 +5,7 @@ import abs = require("ui/layouts/absolute-layout");
import animationModule = require("ui/animation"); import animationModule = require("ui/animation");
import colorModule = require("color"); import colorModule = require("color");
import model = require("./model"); import model = require("./model");
import enums = require("ui/enums");
var vm = new model.ViewModel(); var vm = new model.ViewModel();
@ -27,7 +28,7 @@ export function pageLoaded(args: observable.EventData) {
export function onSlideOut(args: observable.EventData) { export function onSlideOut(args: observable.EventData) {
console.log("onSlideOut"); console.log("onSlideOut");
var curve = page.android ? new android.view.animation.AccelerateInterpolator(1) : UIViewAnimationCurve.UIViewAnimationCurveEaseIn; var curve = enums.AnimationCurve.easeOut;
var buttonAnimations = [ var buttonAnimations = [
{ target: button1, translate: { x: -240, y: 0 }, scale: { x: 0.5, y: 0.5 }, opacity: 0, duration: vm.duration, delay: 0, iterations: vm.iterations, curve: curve }, { target: button1, translate: { x: -240, y: 0 }, scale: { x: 0.5, y: 0.5 }, opacity: 0, duration: vm.duration, delay: 0, iterations: vm.iterations, curve: curve },
@ -36,7 +37,7 @@ export function onSlideOut(args: observable.EventData) {
] ]
buttonAnimation = new animationModule.Animation(buttonAnimations, vm.playSequentially); buttonAnimation = new animationModule.Animation(buttonAnimations, vm.playSequentially);
panelAnimation = panel.createAnimation({ opacity: 0, scale: { x: 0.5, y: 0.5 }, rotate: -360, backgroundColor: new colorModule.Color("red"), duration: vm.duration, iterations: vm.iterations }); panelAnimation = panel.createAnimation({ opacity: 0, scale: { x: 0.5, y: 0.5 }, rotate: -360, backgroundColor: new colorModule.Color("red"), duration: vm.duration, iterations: vm.iterations, curve: enums.AnimationCurve.easeInOut });
buttonAnimation.play() buttonAnimation.play()
.then(() => panelAnimation.play()) .then(() => panelAnimation.play())
@ -45,9 +46,9 @@ export function onSlideOut(args: observable.EventData) {
export function onSlideIn(args: observable.EventData) { export function onSlideIn(args: observable.EventData) {
console.log("onSlideIn"); console.log("onSlideIn");
var curve = page.android ? new android.view.animation.DecelerateInterpolator(1) : UIViewAnimationCurve.UIViewAnimationCurveEaseOut; var curve = enums.AnimationCurve.easeIn;
panelAnimation = panel.createAnimation({ opacity: 1, scale: { x: 1, y: 1 }, rotate: 0, backgroundColor: new colorModule.Color("yellow"), duration: vm.duration, iterations: vm.iterations }); panelAnimation = panel.createAnimation({ opacity: 1, scale: { x: 1, y: 1 }, rotate: 0, backgroundColor: new colorModule.Color("yellow"), duration: vm.duration, iterations: vm.iterations, curve: enums.AnimationCurve.easeInOut });
var buttonAnimations = [ var buttonAnimations = [
{ target: button3, translate: { x: 0, y: 0 }, scale: { x: 1, y: 1 }, opacity: 1, duration: vm.duration, delay: 0, iterations: vm.iterations, curve: curve }, { target: button3, translate: { x: 0, y: 0 }, scale: { x: 1, y: 1 }, opacity: 1, duration: vm.duration, delay: 0, iterations: vm.iterations, curve: curve },
@ -86,7 +87,7 @@ export function onSingle(args: observable.EventData) {
duration: vm.duration, duration: vm.duration,
delay: 0, delay: 0,
iterations: vm.iterations, iterations: vm.iterations,
curve: button1.ios ? UIViewAnimationCurve.UIViewAnimationCurveEaseIn : new android.view.animation.AccelerateInterpolator(1), curve: enums.AnimationCurve.linear,
}) })
.then(() => console.log("Animation finished")) .then(() => console.log("Animation finished"))
.catch((e) => console.log(e.message)); .catch((e) => console.log(e.message));

View File

@ -5,6 +5,7 @@ import viewModule = require("ui/core/view");
import labelModule = require("ui/label"); import labelModule = require("ui/label");
import stackLayoutModule = require("ui/layouts/stack-layout"); import stackLayoutModule = require("ui/layouts/stack-layout");
import colorModule = require("color"); import colorModule = require("color");
import enums = require("ui/enums");
// <snippet module="ui/animation" title="animation"> // <snippet module="ui/animation" title="animation">
// # Animation // # Animation
@ -42,7 +43,7 @@ export var test_AnimatingProperties = function (done) {
duration: 1000, duration: 1000,
delay: 100, delay: 100,
iterations: 3, iterations: 3,
curve: label.ios ? UIViewAnimationCurve.UIViewAnimationCurveEaseIn : new android.view.animation.AccelerateInterpolator(1), curve: enums.AnimationCurve.easeIn
}) })
.then(() => { .then(() => {
////console.log("Animation finished."); ////console.log("Animation finished.");

View File

@ -61,6 +61,7 @@ export class Animation implements definition.Animation {
var i = 0; var i = 0;
var length = animationDefinitions.length; var length = animationDefinitions.length;
for (; i < length; i++) { for (; i < length; i++) {
animationDefinitions[i].curve = this._resolveAnimationCurve(animationDefinitions[i].curve);
this._propertyAnimations = this._propertyAnimations.concat(Animation._createPropertyAnimations(animationDefinitions[i])); this._propertyAnimations = this._propertyAnimations.concat(Animation._createPropertyAnimations(animationDefinitions[i]));
} }
@ -82,6 +83,10 @@ export class Animation implements definition.Animation {
this._reject(new Error("Animation cancelled.")); this._reject(new Error("Animation cancelled."));
} }
_resolveAnimationCurve(curve: any): any {
//
}
private static _createPropertyAnimations(animationDefinition: definition.AnimationDefinition): Array<PropertyAnimation> { private static _createPropertyAnimations(animationDefinition: definition.AnimationDefinition): Array<PropertyAnimation> {
if (!animationDefinition.target) { if (!animationDefinition.target) {
throw new Error("No animation target specified."); throw new Error("No animation target specified.");

View File

@ -4,6 +4,7 @@ import utils = require("utils/utils");
import color = require("color"); import color = require("color");
import trace = require("trace"); import trace = require("trace");
import types = require("utils/types"); import types = require("utils/types");
import enums = require("ui/enums");
global.moduleMerge(common, exports); global.moduleMerge(common, exports);
@ -277,6 +278,26 @@ export class Animation extends common.Animation implements definition.Animation
this._propertyResetCallbacks = this._propertyResetCallbacks.concat(propertyResetCallbacks); this._propertyResetCallbacks = this._propertyResetCallbacks.concat(propertyResetCallbacks);
} }
_resolveAnimationCurve(curve: any): any {
switch (curve) {
case enums.AnimationCurve.easeIn:
trace.write("Animation curve resolved to android.view.animation.AccelerateInterpolator(1).", trace.categories.Animation);
return new android.view.animation.AccelerateInterpolator(1);
case enums.AnimationCurve.easeOut:
trace.write("Animation curve resolved to android.view.animation.DecelerateInterpolator(1).", trace.categories.Animation);
return new android.view.animation.DecelerateInterpolator(1);
case enums.AnimationCurve.easeInOut:
trace.write("Animation curve resolved to android.view.animation.AccelerateDecelerateInterpolator().", trace.categories.Animation);
return new android.view.animation.AccelerateDecelerateInterpolator();
case enums.AnimationCurve.linear:
trace.write("Animation curve resolved to android.view.animation.LinearInterpolator().", trace.categories.Animation);
return new android.view.animation.LinearInterpolator();
default:
trace.write("Animation curve resolved to original: " + curve, trace.categories.Animation);
return curve;
}
}
private static _getAndroidRepeatCount(iterations: number): number { private static _getAndroidRepeatCount(iterations: number): number {
return (iterations === Number.POSITIVE_INFINITY) ? android.view.animation.Animation.INFINITE : iterations - 1; return (iterations === Number.POSITIVE_INFINITY) ? android.view.animation.Animation.INFINITE : iterations - 1;
} }

View File

@ -54,7 +54,8 @@
iterations?: number; iterations?: number;
/** /**
* An optional animation curve of type UIViewAnimationCurve for iOS or android.animation.TimeInterpolator for Android. * An optional animation curve. Possible values are contained in the [AnimationCurve enumeration](../enums/AnimationCurve/README.md).
* Alternatively, you can pass an instance of type UIViewAnimationCurve for iOS or android.animation.TimeInterpolator for Android.
*/ */
curve?: any; curve?: any;
} }
@ -75,5 +76,8 @@
public play: () => Promise<void>; public play: () => Promise<void>;
public cancel: () => void; public cancel: () => void;
public isPlaying: boolean; public isPlaying: boolean;
//@private
_resolveAnimationCurve(curve: any): any
//@endprivate
} }
} }

View File

@ -2,6 +2,7 @@
import common = require("./animation-common"); import common = require("./animation-common");
import viewModule = require("ui/core/view"); import viewModule = require("ui/core/view");
import trace = require("trace"); import trace = require("trace");
import enums = require("ui/enums");
global.moduleMerge(common, exports); global.moduleMerge(common, exports);
@ -143,6 +144,26 @@ export class Animation extends common.Animation implements definition.Animation
this._iOSAnimationFunction = Animation._createiOSAnimationFunction(this._mergedPropertyAnimations, 0, this._playSequentially, animationFinishedCallback); this._iOSAnimationFunction = Animation._createiOSAnimationFunction(this._mergedPropertyAnimations, 0, this._playSequentially, animationFinishedCallback);
} }
_resolveAnimationCurve(curve: any): any {
switch (curve) {
case enums.AnimationCurve.easeIn:
trace.write("Animation curve resolved to UIViewAnimationCurve.UIViewAnimationCurveEaseIn.", trace.categories.Animation);
return UIViewAnimationCurve.UIViewAnimationCurveEaseIn;
case enums.AnimationCurve.easeOut:
trace.write("Animation curve resolved to UIViewAnimationCurve.UIViewAnimationCurveEaseOut.", trace.categories.Animation);
return UIViewAnimationCurve.UIViewAnimationCurveEaseOut;
case enums.AnimationCurve.easeInOut:
trace.write("Animation curve resolved to UIViewAnimationCurve.UIViewAnimationCurveEaseInOut.", trace.categories.Animation);
return UIViewAnimationCurve.UIViewAnimationCurveEaseInOut;
case enums.AnimationCurve.linear:
trace.write("Animation curve resolved to UIViewAnimationCurve.UIViewAnimationCurveLinear.", trace.categories.Animation);
return UIViewAnimationCurve.UIViewAnimationCurveLinear;
default:
trace.write("Animation curve resolved to original: " + curve, trace.categories.Animation);
return curve;
}
}
private static _createiOSAnimationFunction(propertyAnimations: Array<common.PropertyAnimation>, index: number, playSequentially: boolean, finishedCallback: (cancelled?: boolean) => void): Function { private static _createiOSAnimationFunction(propertyAnimations: Array<common.PropertyAnimation>, index: number, playSequentially: boolean, finishedCallback: (cancelled?: boolean) => void): Function {
return (cancelled?: boolean) => { return (cancelled?: boolean) => {
if (cancelled && finishedCallback) { if (cancelled && finishedCallback) {

25
ui/enums/enums.d.ts vendored
View File

@ -492,4 +492,29 @@
*/ */
export var right: string; export var right: string;
} }
/**
* Represents an animation curve type.
*/
module AnimationCurve {
/**
* An ease-in curve causes the animation to begin slowly, and then speed up as it progresses.
*/
export var easeIn: string;
/**
* An ease-out curve causes the animation to begin quickly, and then slow down as it completes.
*/
export var easeOut: string;
/**
* An ease-in ease-out curve causes the animation to begin slowly, accelerate through the middle of its duration, and then slow again before completing.
*/
export var easeInOut: string;
/**
* A linear animation curve causes an animation to occur evenly over its duration.
*/
export var linear: string;
}
} }

View File

@ -149,3 +149,10 @@ export module BackgroundRepeat {
export var repeatY: string = "repeat-y"; export var repeatY: string = "repeat-y";
export var noRepeat: string = "no-repeat"; export var noRepeat: string = "no-repeat";
} }
export module AnimationCurve {
export var easeIn = "easeIn";
export var easeOut = "easeOut";
export var easeInOut = "easeInOut";
export var linear = "linear";
}