[ReactNative] fixup AnimationExperimental a bit
This commit is contained in:
parent
bd7b9da64a
commit
9ea0002774
|
@ -73,19 +73,29 @@ class Tile extends React.Component {
|
||||||
if (tile.isNew()) {
|
if (tile.isNew()) {
|
||||||
offset.opacity = 0;
|
offset.opacity = 0;
|
||||||
} else {
|
} else {
|
||||||
var point = [
|
var point = {
|
||||||
animationPosition(tile.toColumn()),
|
x: animationPosition(tile.toColumn()),
|
||||||
animationPosition(tile.toRow()),
|
y: animationPosition(tile.toRow()),
|
||||||
];
|
};
|
||||||
AnimationExperimental.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {position: point});
|
AnimationExperimental.startAnimation({
|
||||||
|
node: this.refs['this'],
|
||||||
|
duration: 100,
|
||||||
|
easing: 'easeInOutQuad',
|
||||||
|
property: 'position',
|
||||||
|
toValue: point,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
AnimationExperimental.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {opacity: 1});
|
AnimationExperimental.startAnimation({
|
||||||
|
node: this.refs['this'],
|
||||||
|
duration: 100,
|
||||||
|
easing: 'easeInOutQuad',
|
||||||
|
property: 'opacity',
|
||||||
|
toValue: 1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -16,6 +16,17 @@ var AnimationUtils = require('AnimationUtils');
|
||||||
|
|
||||||
type EasingFunction = (t: number) => number;
|
type EasingFunction = (t: number) => number;
|
||||||
|
|
||||||
|
var Properties = {
|
||||||
|
opacity: true,
|
||||||
|
position: true,
|
||||||
|
positionX: true,
|
||||||
|
positionY: true,
|
||||||
|
rotation: true,
|
||||||
|
scaleXY: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
type ValueType = number | Array<number> | {[key: string]: number};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an experimental module that is under development, incomplete,
|
* This is an experimental module that is under development, incomplete,
|
||||||
* potentially buggy, not used in any production apps, and will probably change
|
* potentially buggy, not used in any production apps, and will probably change
|
||||||
|
@ -24,24 +35,34 @@ type EasingFunction = (t: number) => number;
|
||||||
* Use at your own risk.
|
* Use at your own risk.
|
||||||
*/
|
*/
|
||||||
var AnimationExperimental = {
|
var AnimationExperimental = {
|
||||||
Mixin: require('AnimationExperimentalMixin'),
|
|
||||||
|
|
||||||
startAnimation: function(
|
startAnimation: function(
|
||||||
node: any,
|
anim: {
|
||||||
duration: number,
|
node: any;
|
||||||
delay: number,
|
duration: number;
|
||||||
easing: (string | EasingFunction),
|
easing: ($Enum<typeof AnimationUtils.Defaults> | EasingFunction);
|
||||||
properties: {[key: string]: any}
|
property: $Enum<typeof Properties>;
|
||||||
|
toValue: ValueType;
|
||||||
|
fromValue?: ValueType;
|
||||||
|
delay?: number;
|
||||||
|
},
|
||||||
|
callback?: ?(finished: bool) => void
|
||||||
): number {
|
): number {
|
||||||
var nodeHandle = +node.getNodeHandle();
|
var nodeHandle = anim.node.getNodeHandle();
|
||||||
var easingSample = AnimationUtils.evaluateEasingFunction(duration, easing);
|
var easingSample = AnimationUtils.evaluateEasingFunction(
|
||||||
var tag: number = RCTAnimationManager.startAnimation(
|
anim.duration,
|
||||||
|
anim.easing
|
||||||
|
);
|
||||||
|
var tag: number = AnimationUtils.allocateTag();
|
||||||
|
var props = {};
|
||||||
|
props[anim.property] = {to: anim.toValue};
|
||||||
|
RCTAnimationManager.startAnimation(
|
||||||
nodeHandle,
|
nodeHandle,
|
||||||
AnimationUtils.allocateTag(),
|
tag,
|
||||||
duration,
|
anim.duration,
|
||||||
delay,
|
anim.delay,
|
||||||
easingSample,
|
easingSample,
|
||||||
properties
|
props,
|
||||||
|
callback
|
||||||
);
|
);
|
||||||
return tag;
|
return tag;
|
||||||
},
|
},
|
||||||
|
@ -51,4 +72,18 @@ var AnimationExperimental = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (__DEV__) {
|
||||||
|
if (RCTAnimationManager && RCTAnimationManager.Properties) {
|
||||||
|
var a = Object.keys(Properties);
|
||||||
|
var b = RCTAnimationManager.Properties;
|
||||||
|
var diff = a.filter((i) => b.indexOf(i) < 0).concat(
|
||||||
|
b.filter((i) => a.indexOf(i) < 0)
|
||||||
|
);
|
||||||
|
if (diff.length > 0) {
|
||||||
|
throw new Error('JS animation properties don\'t match native properties.' +
|
||||||
|
JSON.stringify(diff, null, ' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = AnimationExperimental;
|
module.exports = AnimationExperimental;
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2015-present, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*
|
|
||||||
* @providesModule AnimationExperimentalMixin
|
|
||||||
* @flow
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var AnimationUtils = require('AnimationUtils');
|
|
||||||
var RCTAnimationManager = require('NativeModules').AnimationExperimentalManager;
|
|
||||||
|
|
||||||
var invariant = require('invariant');
|
|
||||||
|
|
||||||
type EasingFunction = (t: number) => number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an experimental module that is under development, incomplete,
|
|
||||||
* potentially buggy, not used in any production apps, and will probably change
|
|
||||||
* in non-backward compatible ways.
|
|
||||||
*
|
|
||||||
* Use at your own risk.
|
|
||||||
*/
|
|
||||||
var AnimationExperimentalMixin = {
|
|
||||||
getInitialState: function(): Object {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
|
|
||||||
startAnimation: function(
|
|
||||||
refKey: string,
|
|
||||||
duration: number,
|
|
||||||
delay: number,
|
|
||||||
easing: (string | EasingFunction),
|
|
||||||
properties: {[key: string]: any}
|
|
||||||
): number {
|
|
||||||
var ref = this.refs[refKey];
|
|
||||||
invariant(
|
|
||||||
ref,
|
|
||||||
'Invalid refKey ' + refKey + '; ' +
|
|
||||||
'valid refs: ' + JSON.stringify(Object.keys(this.refs))
|
|
||||||
);
|
|
||||||
|
|
||||||
var nodeHandle = +ref.getNodeHandle();
|
|
||||||
var easingSample = AnimationUtils.evaluateEasingFunction(duration, easing);
|
|
||||||
var tag: number = RCTAnimationManager.startAnimation(nodeHandle, AnimationUtils.allocateTag(), duration, delay, easingSample, properties);
|
|
||||||
return tag;
|
|
||||||
},
|
|
||||||
|
|
||||||
stopAnimation: function(tag: number) {
|
|
||||||
RCTAnimationManager.stopAnimation(tag);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = AnimationExperimentalMixin;
|
|
|
@ -20,27 +20,27 @@
|
||||||
type EasingFunction = (t: number) => number;
|
type EasingFunction = (t: number) => number;
|
||||||
|
|
||||||
var defaults = {
|
var defaults = {
|
||||||
easeInQuad: function(t) {
|
easeInQuad: function(t: number): number {
|
||||||
return t * t;
|
return t * t;
|
||||||
},
|
},
|
||||||
easeOutQuad: function(t) {
|
easeOutQuad: function(t: number): number {
|
||||||
return -t * (t - 2);
|
return -t * (t - 2);
|
||||||
},
|
},
|
||||||
easeInOutQuad: function(t) {
|
easeInOutQuad: function(t: number): number {
|
||||||
t = t * 2;
|
t = t * 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
return 0.5 * t * t;
|
return 0.5 * t * t;
|
||||||
}
|
}
|
||||||
return -((t - 1) * (t - 3) - 1) / 2;
|
return -((t - 1) * (t - 3) - 1) / 2;
|
||||||
},
|
},
|
||||||
easeInCubic: function(t) {
|
easeInCubic: function(t: number): number {
|
||||||
return t * t * t;
|
return t * t * t;
|
||||||
},
|
},
|
||||||
easeOutCubic: function(t) {
|
easeOutCubic: function(t: number): number {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
return t * t * t + 1;
|
return t * t * t + 1;
|
||||||
},
|
},
|
||||||
easeInOutCubic: function(t) {
|
easeInOutCubic: function(t: number): number {
|
||||||
t *= 2;
|
t *= 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
return 0.5 * t * t * t;
|
return 0.5 * t * t * t;
|
||||||
|
@ -48,14 +48,14 @@ var defaults = {
|
||||||
t -= 2;
|
t -= 2;
|
||||||
return (t * t * t + 2) / 2;
|
return (t * t * t + 2) / 2;
|
||||||
},
|
},
|
||||||
easeInQuart: function(t) {
|
easeInQuart: function(t: number): number {
|
||||||
return t * t * t * t;
|
return t * t * t * t;
|
||||||
},
|
},
|
||||||
easeOutQuart: function(t) {
|
easeOutQuart: function(t: number): number {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
return -(t * t * t * t - 1);
|
return -(t * t * t * t - 1);
|
||||||
},
|
},
|
||||||
easeInOutQuart: function(t) {
|
easeInOutQuart: function(t: number): number {
|
||||||
t *= 2;
|
t *= 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
return 0.5 * t * t * t * t;
|
return 0.5 * t * t * t * t;
|
||||||
|
@ -63,14 +63,14 @@ var defaults = {
|
||||||
t -= 2;
|
t -= 2;
|
||||||
return -(t * t * t * t - 2) / 2;
|
return -(t * t * t * t - 2) / 2;
|
||||||
},
|
},
|
||||||
easeInQuint: function(t) {
|
easeInQuint: function(t: number): number {
|
||||||
return t * t * t * t * t;
|
return t * t * t * t * t;
|
||||||
},
|
},
|
||||||
easeOutQuint: function(t) {
|
easeOutQuint: function(t: number): number {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
return t * t * t * t * t + 1;
|
return t * t * t * t * t + 1;
|
||||||
},
|
},
|
||||||
easeInOutQuint: function(t) {
|
easeInOutQuint: function(t: number): number {
|
||||||
t *= 2;
|
t *= 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
return (t * t * t * t * t) / 2;
|
return (t * t * t * t * t) / 2;
|
||||||
|
@ -78,22 +78,22 @@ var defaults = {
|
||||||
t -= 2;
|
t -= 2;
|
||||||
return (t * t * t * t * t + 2) / 2;
|
return (t * t * t * t * t + 2) / 2;
|
||||||
},
|
},
|
||||||
easeInSine: function(t) {
|
easeInSine: function(t: number): number {
|
||||||
return -Math.cos(t * (Math.PI / 2)) + 1;
|
return -Math.cos(t * (Math.PI / 2)) + 1;
|
||||||
},
|
},
|
||||||
easeOutSine: function(t) {
|
easeOutSine: function(t: number): number {
|
||||||
return Math.sin(t * (Math.PI / 2));
|
return Math.sin(t * (Math.PI / 2));
|
||||||
},
|
},
|
||||||
easeInOutSine: function(t) {
|
easeInOutSine: function(t: number): number {
|
||||||
return -(Math.cos(Math.PI * t) - 1) / 2;
|
return -(Math.cos(Math.PI * t) - 1) / 2;
|
||||||
},
|
},
|
||||||
easeInExpo: function(t) {
|
easeInExpo: function(t: number): number {
|
||||||
return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1));
|
return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1));
|
||||||
},
|
},
|
||||||
easeOutExpo: function(t) {
|
easeOutExpo: function(t: number): number {
|
||||||
return (t === 1) ? 1 : (-Math.pow(2, -10 * t) + 1);
|
return (t === 1) ? 1 : (-Math.pow(2, -10 * t) + 1);
|
||||||
},
|
},
|
||||||
easeInOutExpo: function(t) {
|
easeInOutExpo: function(t: number): number {
|
||||||
if (t === 0) {
|
if (t === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -106,14 +106,14 @@ var defaults = {
|
||||||
}
|
}
|
||||||
return (-Math.pow(2, -10 * (t - 1)) + 2) / 2;
|
return (-Math.pow(2, -10 * (t - 1)) + 2) / 2;
|
||||||
},
|
},
|
||||||
easeInCirc: function(t) {
|
easeInCirc: function(t: number): number {
|
||||||
return -(Math.sqrt(1 - t * t) - 1);
|
return -(Math.sqrt(1 - t * t) - 1);
|
||||||
},
|
},
|
||||||
easeOutCirc: function(t) {
|
easeOutCirc: function(t: number): number {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
return Math.sqrt(1 - t * t);
|
return Math.sqrt(1 - t * t);
|
||||||
},
|
},
|
||||||
easeInOutCirc: function(t) {
|
easeInOutCirc: function(t: number): number {
|
||||||
t *= 2;
|
t *= 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
return -(Math.sqrt(1 - t * t) - 1) / 2;
|
return -(Math.sqrt(1 - t * t) - 1) / 2;
|
||||||
|
@ -121,7 +121,7 @@ var defaults = {
|
||||||
t -= 2;
|
t -= 2;
|
||||||
return (Math.sqrt(1 - t * t) + 1) / 2;
|
return (Math.sqrt(1 - t * t) + 1) / 2;
|
||||||
},
|
},
|
||||||
easeInElastic: function(t) {
|
easeInElastic: function(t: number): number {
|
||||||
var s = 1.70158;
|
var s = 1.70158;
|
||||||
var p = 0.3;
|
var p = 0.3;
|
||||||
if (t === 0) {
|
if (t === 0) {
|
||||||
|
@ -134,7 +134,7 @@ var defaults = {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
return -(Math.pow(2, 10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
|
return -(Math.pow(2, 10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
|
||||||
},
|
},
|
||||||
easeOutElastic: function(t) {
|
easeOutElastic: function(t: number): number {
|
||||||
var s = 1.70158;
|
var s = 1.70158;
|
||||||
var p = 0.3;
|
var p = 0.3;
|
||||||
if (t === 0) {
|
if (t === 0) {
|
||||||
|
@ -146,7 +146,7 @@ var defaults = {
|
||||||
var s = p / (2 * Math.PI) * Math.asin(1);
|
var s = p / (2 * Math.PI) * Math.asin(1);
|
||||||
return Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
|
return Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
|
||||||
},
|
},
|
||||||
easeInOutElastic: function(t) {
|
easeInOutElastic: function(t: number): number {
|
||||||
var s = 1.70158;
|
var s = 1.70158;
|
||||||
var p = 0.3 * 1.5;
|
var p = 0.3 * 1.5;
|
||||||
if (t === 0) {
|
if (t === 0) {
|
||||||
|
@ -164,16 +164,16 @@ var defaults = {
|
||||||
t -= 1;
|
t -= 1;
|
||||||
return Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) / 2 + 1;
|
return Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) / 2 + 1;
|
||||||
},
|
},
|
||||||
easeInBack: function(t) {
|
easeInBack: function(t: number): number {
|
||||||
var s = 1.70158;
|
var s = 1.70158;
|
||||||
return t * t * ((s + 1) * t - s);
|
return t * t * ((s + 1) * t - s);
|
||||||
},
|
},
|
||||||
easeOutBack: function(t) {
|
easeOutBack: function(t: number): number {
|
||||||
var s = 1.70158;
|
var s = 1.70158;
|
||||||
t -= 1;
|
t -= 1;
|
||||||
return (t * t * ((s + 1) * t + s) + 1);
|
return (t * t * ((s + 1) * t + s) + 1);
|
||||||
},
|
},
|
||||||
easeInOutBack: function(t) {
|
easeInOutBack: function(t: number): number {
|
||||||
var s = 1.70158 * 1.525;
|
var s = 1.70158 * 1.525;
|
||||||
t *= 2;
|
t *= 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
|
@ -182,10 +182,10 @@ var defaults = {
|
||||||
t -= 2;
|
t -= 2;
|
||||||
return (t * t * ((s + 1) * t + s) + 2) / 2;
|
return (t * t * ((s + 1) * t + s) + 2) / 2;
|
||||||
},
|
},
|
||||||
easeInBounce: function(t) {
|
easeInBounce: function(t: number): number {
|
||||||
return 1 - this.easeOutBounce(1 - t);
|
return 1 - this.easeOutBounce(1 - t);
|
||||||
},
|
},
|
||||||
easeOutBounce: function(t) {
|
easeOutBounce: function(t: number): number {
|
||||||
if (t < (1 / 2.75)) {
|
if (t < (1 / 2.75)) {
|
||||||
return 7.5625 * t * t;
|
return 7.5625 * t * t;
|
||||||
} else if (t < (2 / 2.75)) {
|
} else if (t < (2 / 2.75)) {
|
||||||
|
@ -199,7 +199,7 @@ var defaults = {
|
||||||
return 7.5625 * t * t + 0.984375;
|
return 7.5625 * t * t + 0.984375;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
easeInOutBounce: function(t) {
|
easeInOutBounce: function(t: number): number {
|
||||||
if (t < 0.5) {
|
if (t < 0.5) {
|
||||||
return this.easeInBounce(t * 2) / 2;
|
return this.easeInBounce(t * 2) / 2;
|
||||||
}
|
}
|
||||||
|
@ -234,4 +234,6 @@ module.exports = {
|
||||||
|
|
||||||
return samples;
|
return samples;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Defaults: defaults,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,18 +17,20 @@ var RCTUIManager = require('NativeModules').UIManager;
|
||||||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||||
var keyMirror = require('keyMirror');
|
var keyMirror = require('keyMirror');
|
||||||
|
|
||||||
var Types = keyMirror({
|
var TypesEnum = {
|
||||||
spring: true,
|
spring: true,
|
||||||
linear: true,
|
linear: true,
|
||||||
easeInEaseOut: true,
|
easeInEaseOut: true,
|
||||||
easeIn: true,
|
easeIn: true,
|
||||||
easeOut: true,
|
easeOut: true,
|
||||||
});
|
};
|
||||||
|
var Types = keyMirror(TypesEnum);
|
||||||
|
|
||||||
var Properties = keyMirror({
|
var PropertiesEnum = {
|
||||||
opacity: true,
|
opacity: true,
|
||||||
scaleXY: true,
|
scaleXY: true,
|
||||||
});
|
};
|
||||||
|
var Properties = keyMirror(PropertiesEnum);
|
||||||
|
|
||||||
var animChecker = createStrictShapeTypeChecker({
|
var animChecker = createStrictShapeTypeChecker({
|
||||||
duration: PropTypes.number,
|
duration: PropTypes.number,
|
||||||
|
@ -48,8 +50,8 @@ type Anim = {
|
||||||
delay?: number;
|
delay?: number;
|
||||||
springDamping?: number;
|
springDamping?: number;
|
||||||
initialVelocity?: number;
|
initialVelocity?: number;
|
||||||
type?: $Enum<typeof Types>;
|
type?: $Enum<typeof TypesEnum>;
|
||||||
property?: $Enum<typeof Properties>;
|
property?: $Enum<typeof PropertiesEnum>;
|
||||||
}
|
}
|
||||||
|
|
||||||
var configChecker = createStrictShapeTypeChecker({
|
var configChecker = createStrictShapeTypeChecker({
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#import "RCTSparseArray.h"
|
#import "RCTSparseArray.h"
|
||||||
#import "RCTUIManager.h"
|
#import "RCTUIManager.h"
|
||||||
|
#import "RCTUtils.h"
|
||||||
|
|
||||||
#if CGFLOAT_IS_DOUBLE
|
#if CGFLOAT_IS_DOUBLE
|
||||||
#define CG_APPEND(PREFIX, SUFFIX_F, SUFFIX_D) PREFIX##SUFFIX_D
|
#define CG_APPEND(PREFIX, SUFFIX_F, SUFFIX_D) PREFIX##SUFFIX_D
|
||||||
|
@ -23,6 +24,8 @@
|
||||||
@implementation RCTAnimationExperimentalManager
|
@implementation RCTAnimationExperimentalManager
|
||||||
{
|
{
|
||||||
RCTSparseArray *_animationRegistry; // Main thread only; animation tag -> view tag
|
RCTSparseArray *_animationRegistry; // Main thread only; animation tag -> view tag
|
||||||
|
RCTSparseArray *_callbackRegistry; // Main thread only; animation tag -> callback
|
||||||
|
NSDictionary *_keypathMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_MODULE()
|
RCT_EXPORT_MODULE()
|
||||||
|
@ -33,6 +36,33 @@ RCT_EXPORT_MODULE()
|
||||||
{
|
{
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
_animationRegistry = [[RCTSparseArray alloc] init];
|
_animationRegistry = [[RCTSparseArray alloc] init];
|
||||||
|
_callbackRegistry = [[RCTSparseArray alloc] init];
|
||||||
|
_keypathMapping = @{
|
||||||
|
@"opacity": @{
|
||||||
|
@"keypath": @"opacity",
|
||||||
|
@"type": @"NSNumber",
|
||||||
|
},
|
||||||
|
@"position": @{
|
||||||
|
@"keypath": @"position",
|
||||||
|
@"type": @"CGPoint",
|
||||||
|
},
|
||||||
|
@"positionX": @{
|
||||||
|
@"keypath": @"position.x",
|
||||||
|
@"type": @"NSNumber",
|
||||||
|
},
|
||||||
|
@"positionY": @{
|
||||||
|
@"keypath": @"position.y",
|
||||||
|
@"type": @"NSNumber",
|
||||||
|
},
|
||||||
|
@"rotation": @{
|
||||||
|
@"keypath": @"transform.rotation.z",
|
||||||
|
@"type": @"NSNumber",
|
||||||
|
},
|
||||||
|
@"scaleXY": @{
|
||||||
|
@"keypath": @"transform.scale",
|
||||||
|
@"type": @"CGPoint",
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -63,12 +93,25 @@ RCT_EXPORT_MODULE()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
static void RCTInvalidAnimationProp(RCTSparseArray *callbacks, NSNumber *tag, NSString *key, id value)
|
||||||
|
{
|
||||||
|
RCTResponseSenderBlock callback = callbacks[tag];
|
||||||
|
RCTLogError(@"Invalid animation property `%@ = %@`", key, value);
|
||||||
|
if (callback) {
|
||||||
|
callback(@[@NO]);
|
||||||
|
callbacks[tag] = nil;
|
||||||
|
}
|
||||||
|
[CATransaction commit];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(startAnimation:(NSNumber *)reactTag
|
||||||
animationTag:(NSNumber *)animationTag
|
animationTag:(NSNumber *)animationTag
|
||||||
duration:(NSTimeInterval)duration
|
duration:(NSTimeInterval)duration
|
||||||
delay:(NSTimeInterval)delay
|
delay:(NSTimeInterval)delay
|
||||||
easingSample:(NSArray *)easingSample
|
easingSample:(NSArray *)easingSample
|
||||||
properties:(NSDictionary *)properties)
|
properties:(NSDictionary *)properties
|
||||||
|
callback:(RCTResponseSenderBlock)callback)
|
||||||
{
|
{
|
||||||
__weak RCTAnimationExperimentalManager *weakSelf = self;
|
__weak RCTAnimationExperimentalManager *weakSelf = self;
|
||||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||||
|
@ -79,12 +122,21 @@ RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
||||||
RCTLogWarn(@"React tag #%@ is not registered with the view registry", reactTag);
|
RCTLogWarn(@"React tag #%@ is not registered with the view registry", reactTag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
__block BOOL completionBlockSet = NO;
|
||||||
[properties enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
|
[CATransaction begin];
|
||||||
|
for (NSString *prop in properties) {
|
||||||
|
NSString *keypath = _keypathMapping[prop][@"keypath"];
|
||||||
|
id obj = properties[prop][@"to"];
|
||||||
|
if (!keypath) {
|
||||||
|
return RCTInvalidAnimationProp(strongSelf->_callbackRegistry, animationTag, keypath, obj);
|
||||||
|
}
|
||||||
NSValue *toValue = nil;
|
NSValue *toValue = nil;
|
||||||
if ([key isEqualToString:@"scaleXY"]) {
|
if ([keypath isEqualToString:@"transform.scale"]) {
|
||||||
key = @"transform.scale";
|
CGPoint point = [RCTConvert CGPoint:obj];
|
||||||
toValue = obj[0];
|
if (point.x != point.y) {
|
||||||
|
return RCTInvalidAnimationProp(strongSelf->_callbackRegistry, animationTag, keypath, obj);
|
||||||
|
}
|
||||||
|
toValue = @(point.x);
|
||||||
} else if ([obj respondsToSelector:@selector(count)]) {
|
} else if ([obj respondsToSelector:@selector(count)]) {
|
||||||
switch ([obj count]) {
|
switch ([obj count]) {
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -100,11 +152,15 @@ RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
||||||
case 16:
|
case 16:
|
||||||
toValue = [NSValue valueWithCGAffineTransform:[RCTConvert CGAffineTransform:obj]];
|
toValue = [NSValue valueWithCGAffineTransform:[RCTConvert CGAffineTransform:obj]];
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return RCTInvalidAnimationProp(strongSelf->_callbackRegistry, animationTag, keypath, obj);
|
||||||
}
|
}
|
||||||
|
} else if (![obj respondsToSelector:@selector(objCType)]) {
|
||||||
|
return RCTInvalidAnimationProp(strongSelf->_callbackRegistry, animationTag, keypath, obj);
|
||||||
|
}
|
||||||
|
if (!toValue) {
|
||||||
|
toValue = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!toValue) toValue = obj;
|
|
||||||
|
|
||||||
const char *typeName = toValue.objCType;
|
const char *typeName = toValue.objCType;
|
||||||
|
|
||||||
size_t count;
|
size_t count;
|
||||||
|
@ -155,7 +211,7 @@ RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSValue *fromValue = [view.layer.presentationLayer valueForKeyPath:key];
|
NSValue *fromValue = [view.layer.presentationLayer valueForKeyPath:keypath];
|
||||||
CGFloat fromFields[count];
|
CGFloat fromFields[count];
|
||||||
[fromValue getValue:fromFields];
|
[fromValue getValue:fromFields];
|
||||||
|
|
||||||
|
@ -166,19 +222,32 @@ RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
||||||
CGFloat t = sample.CG_APPEND(, floatValue, doubleValue);
|
CGFloat t = sample.CG_APPEND(, floatValue, doubleValue);
|
||||||
[sampledValues addObject:interpolationBlock(t)];
|
[sampledValues addObject:interpolationBlock(t)];
|
||||||
}
|
}
|
||||||
|
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keypath];
|
||||||
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:key];
|
|
||||||
animation.beginTime = CACurrentMediaTime() + delay;
|
animation.beginTime = CACurrentMediaTime() + delay;
|
||||||
animation.duration = duration;
|
animation.duration = duration;
|
||||||
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||||
animation.values = sampledValues;
|
animation.values = sampledValues;
|
||||||
|
@try {
|
||||||
[view.layer setValue:toValue forKey:key];
|
[view.layer setValue:toValue forKey:keypath];
|
||||||
|
NSString *animationKey = [@"RCT" stringByAppendingString:RCTJSONStringify(@{@"tag": animationTag, @"key": keypath}, nil)];
|
||||||
NSString *animationKey = [NSString stringWithFormat:@"RCT.%@.%@", animationTag, key];
|
|
||||||
[view.layer addAnimation:animation forKey:animationKey];
|
[view.layer addAnimation:animation forKey:animationKey];
|
||||||
|
if (!completionBlockSet) {
|
||||||
|
strongSelf->_callbackRegistry[animationTag] = callback;
|
||||||
|
[CATransaction setCompletionBlock:^{
|
||||||
|
RCTResponseSenderBlock cb = strongSelf->_callbackRegistry[animationTag];
|
||||||
|
if (cb) {
|
||||||
|
cb(@[@YES]);
|
||||||
|
strongSelf->_callbackRegistry[animationTag] = nil;
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
completionBlockSet = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
return RCTInvalidAnimationProp(strongSelf->_callbackRegistry, animationTag, keypath, toValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[CATransaction commit];
|
||||||
strongSelf->_animationRegistry[animationTag] = reactTag;
|
strongSelf->_animationRegistry[animationTag] = reactTag;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -194,19 +263,25 @@ RCT_EXPORT_METHOD(stopAnimation:(NSNumber *)animationTag)
|
||||||
|
|
||||||
UIView *view = viewRegistry[reactTag];
|
UIView *view = viewRegistry[reactTag];
|
||||||
for (NSString *animationKey in view.layer.animationKeys) {
|
for (NSString *animationKey in view.layer.animationKeys) {
|
||||||
if ([animationKey hasPrefix:@"RCT"]) {
|
if ([animationKey hasPrefix:@"RCT{"]) {
|
||||||
NSRange periodLocation = [animationKey rangeOfString:@"." options:0 range:(NSRange){3, animationKey.length - 3}];
|
NSDictionary *data = RCTJSONParse([animationKey substringFromIndex:3], nil);
|
||||||
if (periodLocation.location != NSNotFound) {
|
if (animationTag.integerValue == [data[@"tag"] integerValue]) {
|
||||||
NSInteger integerTag = [[animationKey substringWithRange:(NSRange){3, periodLocation.location}] integerValue];
|
|
||||||
if (animationTag.integerValue == integerTag) {
|
|
||||||
[view.layer removeAnimationForKey:animationKey];
|
[view.layer removeAnimationForKey:animationKey];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RCTResponseSenderBlock cb = strongSelf->_callbackRegistry[animationTag];
|
||||||
|
if (cb) {
|
||||||
|
cb(@[@NO]);
|
||||||
|
strongSelf->_callbackRegistry[animationTag] = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf->_animationRegistry[animationTag] = nil;
|
strongSelf->_animationRegistry[animationTag] = nil;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)constantsToExport
|
||||||
|
{
|
||||||
|
return @{@"Properties": [_keypathMapping allKeys] };
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -60,7 +60,7 @@ var TouchableBounce = React.createClass({
|
||||||
value: number,
|
value: number,
|
||||||
velocity: number,
|
velocity: number,
|
||||||
bounciness: number,
|
bounciness: number,
|
||||||
fromValue?: ?Function | number,
|
fromValue?: ?number,
|
||||||
callback?: ?Function
|
callback?: ?Function
|
||||||
) {
|
) {
|
||||||
if (POPAnimation) {
|
if (POPAnimation) {
|
||||||
|
@ -71,21 +71,21 @@ var TouchableBounce = React.createClass({
|
||||||
toValue: [value, value],
|
toValue: [value, value],
|
||||||
velocity: [velocity, velocity],
|
velocity: [velocity, velocity],
|
||||||
springBounciness: bounciness,
|
springBounciness: bounciness,
|
||||||
fromValue: (undefined: ?any),
|
fromValue: fromValue ? [fromValue, fromValue] : undefined,
|
||||||
};
|
};
|
||||||
if (fromValue) {
|
|
||||||
anim.fromValue = [fromValue, fromValue];
|
|
||||||
}
|
|
||||||
this.state.animationID = POPAnimation.createSpringAnimation(anim);
|
this.state.animationID = POPAnimation.createSpringAnimation(anim);
|
||||||
this.addAnimation(this.state.animationID, callback);
|
this.addAnimation(this.state.animationID, callback);
|
||||||
} else {
|
} else {
|
||||||
AnimationExperimental.startAnimation(this, 300, 0, 'easeOutBack', {scaleXY: [value, value]});
|
AnimationExperimental.startAnimation(
|
||||||
if (fromValue && typeof fromValue === 'function') {
|
{
|
||||||
callback = fromValue;
|
node: this,
|
||||||
}
|
duration: 300,
|
||||||
if (callback) {
|
easing: 'easeOutBack',
|
||||||
setTimeout(callback, 300);
|
property: 'scaleXY',
|
||||||
}
|
toValue: { x: value, y: value},
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue