mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Merge pull request #1521 from NativeScript/raikov/animation-custom-timing
Added custom animation curve support and spring animation
This commit is contained in:
@@ -27,6 +27,21 @@ export interface PropertyAnimation {
|
||||
curve?: any;
|
||||
}
|
||||
|
||||
export class CubicBezierAnimationCurve implements definition.CubicBezierAnimationCurve {
|
||||
|
||||
public x1: number;
|
||||
public y1: number;
|
||||
public x2: number;
|
||||
public y2: number;
|
||||
|
||||
constructor(x1: number, y1: number, x2: number, y2: number) {
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
}
|
||||
}
|
||||
|
||||
export class Animation implements definition.Animation {
|
||||
public _propertyAnimations: Array<PropertyAnimation>;
|
||||
public _playSequentially: boolean;
|
||||
@@ -98,7 +113,7 @@ export class Animation implements definition.Animation {
|
||||
}
|
||||
|
||||
var propertyAnimations = new Array<PropertyAnimation>();
|
||||
|
||||
|
||||
// opacity
|
||||
if (animationDefinition.opacity !== undefined) {
|
||||
propertyAnimations.push({
|
||||
|
||||
@@ -26,7 +26,7 @@ propertyKeys[common.Properties.translate] = Symbol(keyPrefix + common.Properties
|
||||
export class Animation extends common.Animation implements definition.Animation {
|
||||
private _animatorListener: android.animation.Animator.AnimatorListener;
|
||||
private _nativeAnimatorsArray: any;
|
||||
private _animatorSet: android.animation.AnimatorSet;
|
||||
private _animatorSet: android.animation.AnimatorSet;
|
||||
private _animators: Array<android.animation.Animator>;
|
||||
private _propertyUpdateCallbacks: Array<Function>;
|
||||
private _propertyResetCallbacks: Array<Function>;
|
||||
@@ -102,7 +102,7 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
// It has been cancelled
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var i = 0;
|
||||
var length = this._propertyUpdateCallbacks.length;
|
||||
for (; i < length; i++) {
|
||||
@@ -145,7 +145,7 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
var density = utils.layout.getDisplayDensity();
|
||||
var xyObjectAnimators: any;
|
||||
var animatorSet: android.animation.AnimatorSet;
|
||||
|
||||
|
||||
var key = propertyKeys[propertyAnimation.property];
|
||||
if (key) {
|
||||
propertyAnimation.target[key] = propertyAnimation;
|
||||
@@ -158,7 +158,7 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (propertyAnimation.property) {
|
||||
|
||||
case common.Properties.opacity:
|
||||
@@ -270,7 +270,7 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
var i = 0;
|
||||
var length = animators.length;
|
||||
for (; i < length; i++) {
|
||||
|
||||
|
||||
// Duration
|
||||
if (propertyAnimation.duration !== undefined) {
|
||||
animators[i].setDuration(propertyAnimation.duration);
|
||||
@@ -281,7 +281,7 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
animators[i].setStartDelay(propertyAnimation.delay);
|
||||
}
|
||||
|
||||
// Repeat Count
|
||||
// Repeat Count
|
||||
if (propertyAnimation.iterations !== undefined && animators[i] instanceof android.animation.ValueAnimator) {
|
||||
(<android.animation.ValueAnimator>animators[i]).setRepeatCount(Animation._getAndroidRepeatCount(propertyAnimation.iterations));
|
||||
}
|
||||
@@ -307,6 +307,7 @@ var easeIn = new android.view.animation.AccelerateInterpolator(1);
|
||||
var easeOut = new android.view.animation.DecelerateInterpolator(1);
|
||||
var easeInOut = new android.view.animation.AccelerateDecelerateInterpolator();
|
||||
var linear = new android.view.animation.LinearInterpolator();
|
||||
var bounce = new android.view.animation.BounceInterpolator();
|
||||
export function _resolveAnimationCurve(curve: any): any {
|
||||
switch (curve) {
|
||||
case enums.AnimationCurve.easeIn:
|
||||
@@ -321,8 +322,16 @@ export function _resolveAnimationCurve(curve: any): any {
|
||||
case enums.AnimationCurve.linear:
|
||||
trace.write("Animation curve resolved to android.view.animation.LinearInterpolator().", trace.categories.Animation);
|
||||
return linear;
|
||||
case enums.AnimationCurve.spring:
|
||||
trace.write("Animation curve resolved to android.view.animation.BounceInterpolator().", trace.categories.Animation);
|
||||
return bounce;
|
||||
default:
|
||||
trace.write("Animation curve resolved to original: " + curve, trace.categories.Animation);
|
||||
if (curve instanceof common.CubicBezierAnimationCurve) {
|
||||
var animationCurve = <common.CubicBezierAnimationCurve>curve;
|
||||
var interpolator = (<any>android).support.v4.view.animation.PathInterpolatorCompat.create(animationCurve.x1, animationCurve.y1, animationCurve.x2, animationCurve.y2);
|
||||
return interpolator;
|
||||
}
|
||||
return curve;
|
||||
}
|
||||
}
|
||||
|
||||
28
ui/animation/animation.d.ts
vendored
28
ui/animation/animation.d.ts
vendored
@@ -7,10 +7,10 @@
|
||||
*/
|
||||
export interface AnimationDefinition {
|
||||
/**
|
||||
* The view whose property is to be animated.
|
||||
* The view whose property is to be animated.
|
||||
*/
|
||||
target?: viewModule.View;
|
||||
|
||||
|
||||
/**
|
||||
* Animates the opacity of the view. Value should be a number between 0.0 and 1.0
|
||||
*/
|
||||
@@ -35,24 +35,24 @@
|
||||
* Animates the rotate affine transform of the view. Value should be a number specifying the rotation amount in degrees.
|
||||
*/
|
||||
rotate?: number;
|
||||
|
||||
|
||||
/**
|
||||
* The length of the animation in milliseconds. The default duration is 300 milliseconds.
|
||||
*/
|
||||
duration?: number;
|
||||
|
||||
/**
|
||||
* The amount of time, in milliseconds, to delay starting the animation.
|
||||
* The amount of time, in milliseconds, to delay starting the animation.
|
||||
*/
|
||||
delay?: number;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies how many times the animation should be played. Default is 1.
|
||||
* iOS animations support fractional iterations, i.e. 1.5.
|
||||
* To repeat an animation infinitely, use Number.POSITIVE_INFINITY
|
||||
*/
|
||||
iterations?: number;
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -60,6 +60,20 @@
|
||||
curve?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a custom animation timing curve by using the cubic-bezier function.
|
||||
* Possible values are numeric values from 0 to 1
|
||||
*/
|
||||
export class CubicBezierAnimationCurve {
|
||||
|
||||
public x1: number;
|
||||
public y1: number;
|
||||
public x2: number;
|
||||
public y2: number;
|
||||
|
||||
constructor(x1: number, y1: number, x2: number, y2: number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a pair of values (horizontal and vertical) for translate and scale animations.
|
||||
*/
|
||||
@@ -81,4 +95,4 @@
|
||||
//@private
|
||||
export function _resolveAnimationCurve(curve: any): any;
|
||||
//@endprivate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,18 @@ var _skip = "_skip";
|
||||
|
||||
var FLT_MAX = 340282346638528859811704183484516925440.000000;
|
||||
|
||||
declare var CASpringAnimation:any;
|
||||
|
||||
class AnimationInfo
|
||||
{
|
||||
public propertyNameToAnimate: string;
|
||||
public fromValue: any;
|
||||
public toValue: any;
|
||||
public duration: number;
|
||||
public repeatCount: number;
|
||||
public delay: number;
|
||||
}
|
||||
|
||||
class AnimationDelegateImpl extends NSObject {
|
||||
|
||||
public nextAnimation: Function;
|
||||
@@ -55,21 +67,18 @@ class AnimationDelegateImpl extends NSObject {
|
||||
}
|
||||
|
||||
(<any>this._propertyAnimation.target)._resumePresentationLayerUpdates();
|
||||
|
||||
}
|
||||
|
||||
public animationDidStopFinished(anim: CAAnimation, flag: boolean): void {
|
||||
public animationDidStopFinished(anim: CAAnimation, finished: boolean): void {
|
||||
if (this._finishedCallback) {
|
||||
var cancelled = !flag;
|
||||
// This could either be the master finishedCallback or an nextAnimationCallback depending on the playSequentially argument values.
|
||||
this._finishedCallback(cancelled);
|
||||
this._finishedCallback(!finished);
|
||||
}
|
||||
if (!flag) {
|
||||
if (!finished) {
|
||||
if ((<any>this._propertyAnimation)._propertyResetCallback) {
|
||||
(<any>this._propertyAnimation)._propertyResetCallback((<any>this._propertyAnimation)._originalValue);
|
||||
}
|
||||
}
|
||||
if (flag && this.nextAnimation) {
|
||||
if (finished && this.nextAnimation) {
|
||||
this.nextAnimation();
|
||||
}
|
||||
}
|
||||
@@ -83,10 +92,8 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
|
||||
public play(): Promise<void> {
|
||||
var animationFinishedPromise = super.play();
|
||||
|
||||
this._finishedAnimations = 0;
|
||||
this._cancelledAnimations = 0;
|
||||
|
||||
this._iOSAnimationFunction();
|
||||
return animationFinishedPromise;
|
||||
}
|
||||
@@ -139,151 +146,265 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
}
|
||||
};
|
||||
|
||||
this._iOSAnimationFunction = Animation._createiOSAnimationFunction(this._mergedPropertyAnimations, 0, this._playSequentially, animationFinishedCallback, this);
|
||||
this._iOSAnimationFunction = Animation._createiOSAnimationFunction(this._mergedPropertyAnimations, 0, this._playSequentially, animationFinishedCallback);
|
||||
}
|
||||
|
||||
private static _createiOSAnimationFunction(propertyAnimations: Array<common.PropertyAnimation>, index: number, playSequentially: boolean, finishedCallback: (cancelled?: boolean) => void, that:Animation): Function {
|
||||
private static _createiOSAnimationFunction(propertyAnimations: Array<common.PropertyAnimation>, index: number, playSequentially: boolean, finishedCallback: (cancelled?: boolean) => void): Function {
|
||||
return (cancelled?: boolean) => {
|
||||
|
||||
if (cancelled && finishedCallback) {
|
||||
trace.write("Animation " + (index - 1).toString() + " was cancelled. Will skip the rest of animations and call finishedCallback(true).", trace.categories.Animation);
|
||||
finishedCallback(cancelled);
|
||||
return;
|
||||
}
|
||||
|
||||
var animation = propertyAnimations[index];
|
||||
var nativeView = <UIView>animation.target._nativeView;
|
||||
var propertyNameToAnimate = animation.property;
|
||||
var value = animation.value;
|
||||
var originalValue;
|
||||
var presentationLayer = nativeView.layer.presentationLayer();
|
||||
var tempRotate = animation.target.rotate * Math.PI / 180;
|
||||
var abs
|
||||
var args = Animation._getNativeAnimationArguments(animation);
|
||||
|
||||
switch (animation.property) {
|
||||
case common.Properties.backgroundColor:
|
||||
(<any>animation)._originalValue = animation.target.backgroundColor;
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.backgroundColor = value };
|
||||
if (presentationLayer != null) {
|
||||
originalValue = presentationLayer.backgroundColor;
|
||||
}
|
||||
else {
|
||||
originalValue = nativeView.layer.backgroundColor;
|
||||
}
|
||||
value = value.CGColor;
|
||||
break;
|
||||
case common.Properties.opacity:
|
||||
(<any>animation)._originalValue = animation.target.opacity;
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.opacity = value };
|
||||
if (presentationLayer != null) {
|
||||
originalValue = presentationLayer.opacity;
|
||||
}
|
||||
else {
|
||||
originalValue = nativeView.layer.opacity;
|
||||
}
|
||||
break;
|
||||
case common.Properties.rotate:
|
||||
(<any>animation)._originalValue = animation.target.rotate;
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.rotate = value };
|
||||
propertyNameToAnimate = "transform.rotation";
|
||||
if (presentationLayer != null) {
|
||||
originalValue = presentationLayer.valueForKeyPath("transform.rotation");
|
||||
}
|
||||
else {
|
||||
originalValue = nativeView.layer.valueForKeyPath("transform.rotation");
|
||||
}
|
||||
value = value * Math.PI / 180;
|
||||
abs = fabs(originalValue - value);
|
||||
if (abs < 0.001 && originalValue !== tempRotate) {
|
||||
originalValue = tempRotate;
|
||||
}
|
||||
break;
|
||||
case common.Properties.translate:
|
||||
(<any>animation)._originalValue = { x:animation.target.translateX, y:animation.target.translateY };
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.translateX = value.x; animation.target.translateY = value.y; };
|
||||
propertyNameToAnimate = "transform"
|
||||
if (presentationLayer != null) {
|
||||
originalValue = NSValue.valueWithCATransform3D(presentationLayer.transform);
|
||||
}
|
||||
else {
|
||||
originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform);
|
||||
}
|
||||
value = NSValue.valueWithCATransform3D(CATransform3DTranslate(nativeView.layer.transform, value.x, value.y, 0));
|
||||
break;
|
||||
case common.Properties.scale:
|
||||
(<any>animation)._originalValue = { x:animation.target.scaleX, y:animation.target.scaleY };
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.scaleX = value.x; animation.target.scaleY = value.y; };
|
||||
propertyNameToAnimate = "transform"
|
||||
if (presentationLayer != null) {
|
||||
originalValue = NSValue.valueWithCATransform3D(presentationLayer.transform);
|
||||
}
|
||||
else {
|
||||
originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform);
|
||||
}
|
||||
value = NSValue.valueWithCATransform3D(CATransform3DScale(nativeView.layer.transform, value.x, value.y, 1));
|
||||
break;
|
||||
case _transform:
|
||||
if (presentationLayer != null) {
|
||||
originalValue = NSValue.valueWithCATransform3D(presentationLayer.transform);
|
||||
}
|
||||
else {
|
||||
originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform);
|
||||
}
|
||||
(<any>animation)._originalValue = { xs:animation.target.scaleX, ys:animation.target.scaleY,
|
||||
xt:animation.target.translateX, yt:animation.target.translateY };
|
||||
(<any>animation)._propertyResetCallback = (value) => {
|
||||
animation.target.translateX = value.xt;
|
||||
animation.target.translateY = value.yt;
|
||||
animation.target.scaleX = value.xs;
|
||||
animation.target.scaleY = value.ys;
|
||||
};
|
||||
propertyNameToAnimate = "transform"
|
||||
value = NSValue.valueWithCATransform3D(Animation._createNativeAffineTransform(animation));
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot animate " + animation.property);
|
||||
}
|
||||
|
||||
var nativeAnimation = CABasicAnimation.animationWithKeyPath(propertyNameToAnimate);
|
||||
nativeAnimation.fromValue = originalValue;
|
||||
nativeAnimation.toValue = value;
|
||||
if (animation.duration !== undefined) {
|
||||
nativeAnimation.duration = animation.duration / 1000.0;
|
||||
if (animation.curve === enums.AnimationCurve.spring) {
|
||||
Animation._createNativeSpringAnimation(propertyAnimations, index, playSequentially, args, animation, finishedCallback);
|
||||
}
|
||||
else {
|
||||
nativeAnimation.duration = 0.3;
|
||||
};
|
||||
if (animation.delay !== undefined) {
|
||||
nativeAnimation.beginTime = CACurrentMediaTime() + (animation.delay / 1000.0);
|
||||
Animation._createNativeAnimation(propertyAnimations, index, playSequentially, args, animation, finishedCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (animation.iterations !== undefined) {
|
||||
if (animation.iterations === Number.POSITIVE_INFINITY) {
|
||||
nativeAnimation.repeatCount = FLT_MAX;
|
||||
}
|
||||
else {
|
||||
nativeAnimation.repeatCount = animation.iterations - 1;
|
||||
}
|
||||
}
|
||||
if (animation.curve !== undefined) {
|
||||
trace.write("The animation curve is " + animation.curve, trace.categories.Animation);
|
||||
nativeAnimation.timingFunction = animation.curve;
|
||||
}
|
||||
private static _getNativeAnimationArguments(animation: common.PropertyAnimation): AnimationInfo {
|
||||
|
||||
var animationDelegate: AnimationDelegateImpl = AnimationDelegateImpl.initWithFinishedCallback(finishedCallback, animation);
|
||||
nativeAnimation.setValueForKey(animationDelegate, "delegate");
|
||||
var nativeView = <UIView>animation.target._nativeView;
|
||||
var presentationLayer = nativeView.layer.presentationLayer();
|
||||
var propertyNameToAnimate = animation.property;
|
||||
var value = animation.value;
|
||||
var originalValue;
|
||||
|
||||
nativeView.layer.addAnimationForKey(nativeAnimation, propertyNameToAnimate);
|
||||
var tempRotate = animation.target.rotate * Math.PI / 180;
|
||||
var abs
|
||||
|
||||
var callback = undefined;
|
||||
if (index+1 < propertyAnimations.length) {
|
||||
callback = Animation._createiOSAnimationFunction(propertyAnimations, index+1, playSequentially, finishedCallback, that);
|
||||
if (!playSequentially) {
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
animationDelegate.nextAnimation = callback;
|
||||
}
|
||||
switch (animation.property) {
|
||||
case common.Properties.backgroundColor:
|
||||
(<any>animation)._originalValue = animation.target.backgroundColor;
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.backgroundColor = value };
|
||||
if (presentationLayer != null) {
|
||||
originalValue = presentationLayer.backgroundColor;
|
||||
}
|
||||
else {
|
||||
originalValue = nativeView.layer.backgroundColor;
|
||||
}
|
||||
if (nativeView instanceof UILabel) {
|
||||
originalValue = nativeView.layer.backgroundColor;
|
||||
nativeView.setValueForKey(UIColor.clearColor(), "backgroundColor");
|
||||
}
|
||||
value = value.CGColor;
|
||||
break;
|
||||
case common.Properties.opacity:
|
||||
(<any>animation)._originalValue = animation.target.opacity;
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.opacity = value };
|
||||
if (presentationLayer != null) {
|
||||
originalValue = presentationLayer.opacity;
|
||||
}
|
||||
else {
|
||||
originalValue = nativeView.layer.opacity;
|
||||
}
|
||||
break;
|
||||
case common.Properties.rotate:
|
||||
(<any>animation)._originalValue = animation.target.rotate;
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.rotate = value };
|
||||
propertyNameToAnimate = "transform.rotation";
|
||||
if (presentationLayer != null) {
|
||||
originalValue = presentationLayer.valueForKeyPath("transform.rotation");
|
||||
}
|
||||
else {
|
||||
originalValue = nativeView.layer.valueForKeyPath("transform.rotation");
|
||||
}
|
||||
value = value * Math.PI / 180;
|
||||
abs = fabs(originalValue - value);
|
||||
if (abs < 0.001 && originalValue !== tempRotate) {
|
||||
originalValue = tempRotate;
|
||||
}
|
||||
break;
|
||||
case common.Properties.translate:
|
||||
(<any>animation)._originalValue = { x:animation.target.translateX, y:animation.target.translateY };
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.translateX = value.x; animation.target.translateY = value.y; };
|
||||
propertyNameToAnimate = "transform"
|
||||
if (presentationLayer != null) {
|
||||
originalValue = NSValue.valueWithCATransform3D(presentationLayer.transform);
|
||||
}
|
||||
else {
|
||||
originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform);
|
||||
}
|
||||
value = NSValue.valueWithCATransform3D(CATransform3DTranslate(nativeView.layer.transform, value.x, value.y, 0));
|
||||
break;
|
||||
case common.Properties.scale:
|
||||
(<any>animation)._originalValue = { x:animation.target.scaleX, y:animation.target.scaleY };
|
||||
(<any>animation)._propertyResetCallback = (value) => { animation.target.scaleX = value.x; animation.target.scaleY = value.y; };
|
||||
propertyNameToAnimate = "transform"
|
||||
if (presentationLayer != null) {
|
||||
originalValue = NSValue.valueWithCATransform3D(presentationLayer.transform);
|
||||
}
|
||||
else {
|
||||
originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform);
|
||||
}
|
||||
value = NSValue.valueWithCATransform3D(CATransform3DScale(nativeView.layer.transform, value.x, value.y, 1));
|
||||
break;
|
||||
case _transform:
|
||||
if (presentationLayer != null) {
|
||||
originalValue = NSValue.valueWithCATransform3D(presentationLayer.transform);
|
||||
}
|
||||
else {
|
||||
originalValue = NSValue.valueWithCATransform3D(nativeView.layer.transform);
|
||||
}
|
||||
(<any>animation)._originalValue = { xs:animation.target.scaleX, ys:animation.target.scaleY,
|
||||
xt:animation.target.translateX, yt:animation.target.translateY };
|
||||
(<any>animation)._propertyResetCallback = (value) => {
|
||||
animation.target.translateX = value.xt;
|
||||
animation.target.translateY = value.yt;
|
||||
animation.target.scaleX = value.xs;
|
||||
animation.target.scaleY = value.ys;
|
||||
};
|
||||
propertyNameToAnimate = "transform"
|
||||
value = NSValue.valueWithCATransform3D(Animation._createNativeAffineTransform(animation));
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot animate " + animation.property);
|
||||
}
|
||||
|
||||
var duration = 0.3;
|
||||
if (animation.duration !== undefined) {
|
||||
duration = animation.duration / 1000.0;
|
||||
}
|
||||
|
||||
var delay = undefined;
|
||||
if (animation.delay) {
|
||||
delay = animation.delay / 1000.0;
|
||||
}
|
||||
|
||||
var repeatCount = undefined;
|
||||
if (animation.iterations !== undefined) {
|
||||
if (animation.iterations === Number.POSITIVE_INFINITY) {
|
||||
repeatCount = FLT_MAX;
|
||||
}
|
||||
else {
|
||||
repeatCount = animation.iterations - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
propertyNameToAnimate: propertyNameToAnimate,
|
||||
fromValue: originalValue,
|
||||
toValue: value,
|
||||
duration: duration,
|
||||
repeatCount: repeatCount,
|
||||
delay: delay
|
||||
};
|
||||
}
|
||||
|
||||
private static _createNativeAnimation(propertyAnimations: Array<common.PropertyAnimation>, index: number, playSequentially: boolean, args: AnimationInfo, animation: common.PropertyAnimation, finishedCallback: (cancelled?: boolean) => void) {
|
||||
|
||||
var nativeView = <UIView>animation.target._nativeView;
|
||||
var nativeAnimation = CABasicAnimation.animationWithKeyPath(args.propertyNameToAnimate);
|
||||
nativeAnimation.fromValue = args.fromValue;
|
||||
nativeAnimation.toValue = args.toValue;
|
||||
nativeAnimation.duration = args.duration;
|
||||
if (args.repeatCount !== undefined) {
|
||||
nativeAnimation.repeatCount = args.repeatCount;
|
||||
}
|
||||
if (args.delay !== undefined) {
|
||||
nativeAnimation.beginTime = CACurrentMediaTime() + args.delay;
|
||||
}
|
||||
if (animation.curve !== undefined) {
|
||||
nativeAnimation.timingFunction = animation.curve;
|
||||
}
|
||||
|
||||
var animationDelegate = AnimationDelegateImpl.initWithFinishedCallback(finishedCallback, animation);
|
||||
nativeAnimation.setValueForKey(animationDelegate, "delegate");
|
||||
|
||||
nativeView.layer.addAnimationForKey(nativeAnimation, args.propertyNameToAnimate);
|
||||
|
||||
var callback = undefined;
|
||||
if (index+1 < propertyAnimations.length) {
|
||||
callback = Animation._createiOSAnimationFunction(propertyAnimations, index+1, playSequentially, finishedCallback);
|
||||
if (!playSequentially) {
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
animationDelegate.nextAnimation = callback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static _createNativeSpringAnimation(propertyAnimations: Array<common.PropertyAnimation>, index: number, playSequentially: boolean, args: AnimationInfo, animation: common.PropertyAnimation, finishedCallback: (cancelled?: boolean) => void) {
|
||||
|
||||
var nativeView = <UIView>animation.target._nativeView;
|
||||
|
||||
var callback = undefined;
|
||||
var nextAnimation;
|
||||
if (index + 1 < propertyAnimations.length) {
|
||||
callback = Animation._createiOSAnimationFunction(propertyAnimations, index + 1, playSequentially, finishedCallback);
|
||||
if (!playSequentially) {
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
nextAnimation = callback;
|
||||
}
|
||||
}
|
||||
|
||||
var delay = 0;
|
||||
if (args.delay) {
|
||||
delay = args.delay;
|
||||
}
|
||||
|
||||
UIView.animateWithDurationDelayUsingSpringWithDampingInitialSpringVelocityOptionsAnimationsCompletion(args.duration, delay, 0.2, 0,
|
||||
UIViewKeyframeAnimationOptions.UIViewKeyframeAnimationOptionCalculationModeLinear,
|
||||
() => {
|
||||
if (args.repeatCount !== undefined) {
|
||||
UIView.setAnimationRepeatCount(args.repeatCount);
|
||||
}
|
||||
|
||||
switch (animation.property) {
|
||||
case common.Properties.backgroundColor:
|
||||
animation.target.backgroundColor = args.toValue;
|
||||
break;
|
||||
case common.Properties.opacity:
|
||||
animation.target.opacity = args.toValue;
|
||||
break;
|
||||
case common.Properties.rotate:
|
||||
nativeView.layer.setValueForKey(args.toValue, args.propertyNameToAnimate);
|
||||
break;
|
||||
case _transform:
|
||||
(<any>animation)._originalValue = nativeView.layer.transform;
|
||||
nativeView.layer.setValueForKey(args.toValue, args.propertyNameToAnimate);
|
||||
(<any>animation)._propertyResetCallback = function (value) {
|
||||
nativeView.layer.transform = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}, function (finished:boolean) {
|
||||
if (finished) {
|
||||
if (animation.property === _transform) {
|
||||
if (animation.value[common.Properties.translate] !== undefined) {
|
||||
animation.target.translateX = animation.value[common.Properties.translate].x;
|
||||
animation.target.translateY = animation.value[common.Properties.translate].y;
|
||||
}
|
||||
if (animation.value[common.Properties.scale] !== undefined) {
|
||||
animation.target.scaleX = animation.value[common.Properties.scale].x;
|
||||
animation.target.scaleY = animation.value[common.Properties.scale].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((<any>animation)._propertyResetCallback) {
|
||||
(<any>animation)._propertyResetCallback((<any>animation)._originalValue);
|
||||
}
|
||||
}
|
||||
if (finishedCallback) {
|
||||
var cancelled = !finished;
|
||||
finishedCallback(cancelled);
|
||||
}
|
||||
if (finished && nextAnimation) {
|
||||
nextAnimation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static _createNativeAffineTransform(animation: common.PropertyAnimation): CATransform3D {
|
||||
@@ -353,8 +474,10 @@ export class Animation extends common.Animation implements definition.Animation
|
||||
value: {},
|
||||
duration: propertyAnimations[i].duration,
|
||||
delay: propertyAnimations[i].delay,
|
||||
iterations: propertyAnimations[i].iterations
|
||||
iterations: propertyAnimations[i].iterations,
|
||||
curve: propertyAnimations[i].curve
|
||||
};
|
||||
trace.write("Curve: " + propertyAnimations[i].curve, trace.categories.Animation);
|
||||
newTransformAnimation.value[propertyAnimations[i].property] = propertyAnimations[i].value;
|
||||
trace.write("Created new transform animation: " + common.Animation._getAnimationInfo(newTransformAnimation), trace.categories.Animation);
|
||||
|
||||
@@ -388,7 +511,16 @@ export function _resolveAnimationCurve(curve: any): any {
|
||||
return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut);
|
||||
case enums.AnimationCurve.linear:
|
||||
return CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionLinear);
|
||||
case enums.AnimationCurve.spring:
|
||||
return curve;
|
||||
default:
|
||||
if (curve instanceof CAMediaTimingFunction) {
|
||||
return curve;
|
||||
}
|
||||
else if (curve instanceof common.CubicBezierAnimationCurve) {
|
||||
var animationCurve = <common.CubicBezierAnimationCurve>curve;
|
||||
return CAMediaTimingFunction.functionWithControlPoints(animationCurve.x1, animationCurve.y1, animationCurve.x2, animationCurve.y2);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
55
ui/enums/enums.d.ts
vendored
55
ui/enums/enums.d.ts
vendored
@@ -1,5 +1,7 @@
|
||||
declare module "ui/enums" {
|
||||
|
||||
import animationModule = require("ui/animation");
|
||||
|
||||
/**
|
||||
* Represents a soft keyboard flavor.
|
||||
*/
|
||||
@@ -9,25 +11,25 @@
|
||||
* iOS: [UIKeyboardTypeNumbersAndPunctuation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
|
||||
*/
|
||||
export var datetime: string;
|
||||
|
||||
|
||||
/**
|
||||
* Android: [TYPE_CLASS_PHONE](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_PHONE)
|
||||
* iOS: [UIKeyboardTypePhonePad](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
|
||||
*/
|
||||
export var phone: string;
|
||||
|
||||
|
||||
/**
|
||||
* Android: [TYPE_CLASS_NUMBER](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_NUMBER) | android.text.InputType.TYPE_NUMBER_VARIATION_NORMAL | [TYPE_NUMBER_FLAG_SIGNED](http://developer.android.com/reference/android/text/InputType.html#TYPE_NUMBER_FLAG_SIGNED) | [TYPE_NUMBER_FLAG_DECIMAL](http://developer.android.com/reference/android/text/InputType.html#TYPE_NUMBER_FLAG_DECIMAL)
|
||||
* iOS: [UIKeyboardTypeNumbersAndPunctuation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
|
||||
*/
|
||||
export var number: string;
|
||||
|
||||
|
||||
/**
|
||||
* Android: [TYPE_CLASS_TEXT](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_TEXT) | [TYPE_TEXT_VARIATION_URI](http://developer.android.com/reference/android/text/InputType.html#TYPE_TEXT_VARIATION_URI)
|
||||
* iOS: [UIKeyboardTypeURL](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
|
||||
*/
|
||||
export var url: string;
|
||||
|
||||
|
||||
/**
|
||||
* Android: [TYPE_CLASS_TEXT](http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_TEXT) | [TYPE_TEXT_VARIATION_EMAIL_ADDRESS](http://developer.android.com/reference/android/text/InputType.html#TYPE_TEXT_VARIATION_EMAIL_ADDRESS)
|
||||
* iOS: [UIKeyboardTypeEmailAddress](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIKeyboardType)
|
||||
@@ -56,13 +58,13 @@
|
||||
* iOS: [UIReturnKeyGo](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIReturnKeyType)
|
||||
*/
|
||||
export var go: string;
|
||||
|
||||
|
||||
/**
|
||||
* Android: [IME_ACTION_SEARCH](http://developer.android.com/reference/android/view/inputmethod/EditorInfo.html#IME_ACTION_SEARCH)
|
||||
* iOS: [UIReturnKeySearch](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIReturnKeyType)
|
||||
*/
|
||||
export var search: string;
|
||||
|
||||
|
||||
/**
|
||||
* Android: [IME_ACTION_SEND](http://developer.android.com/reference/android/view/inputmethod/EditorInfo.html#IME_ACTION_SEND)
|
||||
* iOS: [UIReturnKeySend](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/c/tdef/UIReturnKeyType)
|
||||
@@ -324,17 +326,17 @@
|
||||
export var none: string;
|
||||
|
||||
/**
|
||||
* Capitalize the first letter of each word automatically.
|
||||
* Capitalize the first letter of each word automatically.
|
||||
*/
|
||||
export var words: string;
|
||||
|
||||
/**
|
||||
* Capitalize the first letter of each sentence automatically.
|
||||
* Capitalize the first letter of each sentence automatically.
|
||||
*/
|
||||
export var sentences: string;
|
||||
|
||||
|
||||
/**
|
||||
* Capitalize all characters automatically.
|
||||
* Capitalize all characters automatically.
|
||||
*/
|
||||
export var allCharacters: string;
|
||||
}
|
||||
@@ -402,7 +404,7 @@
|
||||
*/
|
||||
export var popup: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies different font styles.
|
||||
*/
|
||||
@@ -411,7 +413,7 @@
|
||||
* Normal font style.
|
||||
*/
|
||||
export var normal: string;
|
||||
|
||||
|
||||
/**
|
||||
* Italic font style.
|
||||
*/
|
||||
@@ -426,7 +428,7 @@
|
||||
* No decoration.
|
||||
*/
|
||||
export var none: string;
|
||||
|
||||
|
||||
/**
|
||||
* Text decoration underline.
|
||||
*/
|
||||
@@ -446,7 +448,7 @@
|
||||
* No transform.
|
||||
*/
|
||||
export var none: string;
|
||||
|
||||
|
||||
/**
|
||||
* Text transform capitalize.
|
||||
*/
|
||||
@@ -456,7 +458,7 @@
|
||||
* Text transform uppercase.
|
||||
*/
|
||||
export var uppercase: string;
|
||||
|
||||
|
||||
/**
|
||||
* Text transform lowercase.
|
||||
*/
|
||||
@@ -471,13 +473,13 @@
|
||||
* Normal wrap.
|
||||
*/
|
||||
export var normal: string;
|
||||
|
||||
|
||||
/**
|
||||
* No wrap.
|
||||
*/
|
||||
export var nowrap: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies different font weights.
|
||||
*/
|
||||
@@ -486,13 +488,13 @@
|
||||
* Normal font weight.
|
||||
*/
|
||||
export var normal: string;
|
||||
|
||||
|
||||
/**
|
||||
* Bold font weight.
|
||||
*/
|
||||
export var bold: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies background repeat.
|
||||
*/
|
||||
@@ -522,6 +524,7 @@
|
||||
* Represents an animation curve type.
|
||||
*/
|
||||
module AnimationCurve {
|
||||
|
||||
/**
|
||||
* An ease-in curve causes the animation to begin slowly, and then speed up as it progresses.
|
||||
*/
|
||||
@@ -536,10 +539,20 @@
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A spring animation curve causes an animation to produce a spring (bounce) effect.
|
||||
*/
|
||||
export var spring: string;
|
||||
|
||||
/**
|
||||
* A custom cubic bezier function defined by its two control points. Possible values are numeric values from 0 to 1
|
||||
*/
|
||||
export function cubicBezier(x1: number, y1: number, x2: number, y2: number): animationModule.CubicBezierAnimationCurve;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export module KeyboardType {
|
||||
import animationModule = require("ui/animation");
|
||||
|
||||
export module KeyboardType {
|
||||
export var datetime = "datetime";
|
||||
export var phone = "phone";
|
||||
export var number = "number";
|
||||
@@ -162,4 +164,8 @@ export module AnimationCurve {
|
||||
export var easeOut = "easeOut";
|
||||
export var easeInOut = "easeInOut";
|
||||
export var linear = "linear";
|
||||
}
|
||||
export var spring = "spring";
|
||||
export function cubicBezier(x1: number, y1: number, x2: number, y2: number): animationModule.CubicBezierAnimationCurve {
|
||||
return new animationModule.CubicBezierAnimationCurve(x1, y1 ,x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user