Add support for native animations on iOS

Summary:
Currently on iOS animations are being performed on the JS thread. This ports animations over to the native thread and performs them natively. A lot of this work has already been done on Android, but this PR enables a few animation nodes that Android doesn't yet support such as Transform, Multiplication, and Addition nodes.
Also there is a demo of the native animations added to the UIExplorer app.
Closes https://github.com/facebook/react-native/pull/7884

Differential Revision: D3401811

Pulled By: nicklockwood

fbshipit-source-id: c8d750b75e4410923e17eaeb6dcaf079a09942e2
This commit is contained in:
Brandon Withrow
2016-06-07 20:40:54 -07:00
committed by Facebook Github Bot 4
parent 7357ccc370
commit 5ecdb252c3
31 changed files with 1983 additions and 4 deletions

View File

@@ -243,7 +243,7 @@ class TimingAnimation extends Animation {
this._duration = config.duration !== undefined ? config.duration : 500;
this._delay = config.delay !== undefined ? config.delay : 0;
this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true;
this._useNativeDriver = !!config.useNativeDriver;
this._useNativeDriver = config.useNativeDriver !== undefined ? config.useNativeDriver : false;
}
_getNativeAnimationConfig(): any {
@@ -256,6 +256,7 @@ class TimingAnimation extends Animation {
type: 'frames',
frames,
toValue: this._toValue,
delay: this._delay
};
}
@@ -1086,6 +1087,18 @@ class AnimatedTransform extends AnimatedWithChildren {
this._transforms = transforms;
}
__makeNative() {
super.__makeNative();
this._transforms.forEach(transform => {
for (var key in transform) {
var value = transform[key];
if (value instanceof Animated) {
value.__makeNative();
}
}
});
}
__getValue(): Array<Object> {
return this._transforms.map(transform => {
var result = {};
@@ -1138,6 +1151,25 @@ class AnimatedTransform extends AnimatedWithChildren {
}
});
}
__getNativeConfig(): any {
var transConfig = {};
this._transforms.forEach(transform => {
for (var key in transform) {
var value = transform[key];
if (value instanceof Animated) {
transConfig[key] = value.__getNativeTag();
}
}
});
NativeAnimatedHelper.validateTransform(transConfig);
return {
type: 'transform',
transform: transConfig,
};
}
}
class AnimatedStyle extends AnimatedWithChildren {

View File

@@ -74,16 +74,22 @@ var API = {
var PROPS_WHITELIST = {
style: {
opacity: true,
transform: true,
/* legacy android transform properties */
scaleX: true,
scaleY: true,
rotation: true,
translateX: true,
translateY: true,
},
};
var TRANSFORM_WHITELIST = {
translateX: true,
translateY: true,
scale: true,
rotate: true,
};
function validateProps(params: Object): void {
for (var key in params) {
if (!PROPS_WHITELIST.hasOwnProperty(key)) {
@@ -92,6 +98,14 @@ function validateProps(params: Object): void {
}
}
function validateTransform(config: Object): void {
for (var key in config) {
if (!TRANSFORM_WHITELIST.hasOwnProperty(key)) {
throw new Error(`Property '${key}' is not supported by native animated module`);
}
}
}
function validateStyles(styles: Object): void {
var STYLES_WHITELIST = PROPS_WHITELIST.style || {};
for (var key in styles) {
@@ -129,6 +143,7 @@ module.exports = {
API,
validateProps,
validateStyles,
validateTransform,
validateInterpolation,
generateNewNodeTag,
generateNewAnimationId,