Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions Examples/UIExplorer/js/NativeAnimationsExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ const {
Animated,
StyleSheet,
TouchableWithoutFeedback,
Slider,
} = ReactNative;

var AnimatedSlider = Animated.createAnimatedComponent(Slider);

class Tester extends React.Component {
state = {
native: new Animated.Value(0),
Expand Down Expand Up @@ -228,7 +231,6 @@ exports.description = 'Test out Native Animations';
exports.examples = [
{
title: 'Multistage With Multiply and rotation',
description: 'description',
render: function() {
return (
<Tester
Expand Down Expand Up @@ -278,7 +280,6 @@ exports.examples = [
},
{
title: 'Multistage With Multiply',
description: 'description',
render: function() {
return (
<Tester
Expand Down Expand Up @@ -322,7 +323,6 @@ exports.examples = [
},
{
title: 'Scale interpolation with clamping',
description: 'description',
render: function() {
return (
<Tester
Expand Down Expand Up @@ -352,7 +352,6 @@ exports.examples = [
},
{
title: 'Opacity without interpolation',
description: 'description',
render: function() {
return (
<Tester
Expand All @@ -374,7 +373,6 @@ exports.examples = [
},
{
title: 'Rotate interpolation',
description: 'description',
render: function() {
return (
<Tester
Expand Down Expand Up @@ -403,7 +401,6 @@ exports.examples = [
},
{
title: 'translateX => Animated.spring',
description: 'description',
render: function() {
return (
<Tester
Expand Down Expand Up @@ -454,6 +451,19 @@ exports.examples = [
</Tester>
);
},
},{
title: 'Drive custom property',
render: function() {
return (
<Tester
type="timing"
config={{ duration: 1000 }}>
{anim => (
<AnimatedSlider style={{}} value={anim} />
)}
</Tester>
);
},
},
{
title: 'Animated value listener',
Expand Down
1 change: 0 additions & 1 deletion Libraries/Animated/src/AnimatedImplementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -1676,7 +1676,6 @@ class AnimatedProps extends Animated {
propsConfig[propKey] = value.__getNativeTag();
}
}
NativeAnimatedHelper.validateProps(propsConfig);
return {
type: 'props',
props: propsConfig,
Expand Down
33 changes: 10 additions & 23 deletions Libraries/Animated/src/NativeAnimatedHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,19 @@ const API = {
};

/**
* Properties allowed by the native animated implementation.
* Styles allowed by the native animated implementation.
*
* In general native animated implementation should support any numeric property that doesn't need
* to be updated through the shadow view hierarchy (all non-layout properties). This list is limited
* to the properties that will perform best when animated off the JS thread.
* to be updated through the shadow view hierarchy (all non-layout properties).
*/
const PROPS_WHITELIST = {
style: {
opacity: true,
transform: true,
/* legacy android transform properties */
scaleX: true,
scaleY: true,
translateX: true,
translateY: true,
},
const STYLES_WHITELIST = {
opacity: true,
transform: true,
/* legacy android transform properties */
scaleX: true,
scaleY: true,
translateX: true,
translateY: true,
};

const TRANSFORM_WHITELIST = {
Expand All @@ -130,14 +127,6 @@ const TRANSFORM_WHITELIST = {
perspective: true,
};

function validateProps(params: Object): void {
for (var key in params) {
if (!PROPS_WHITELIST.hasOwnProperty(key)) {
throw new Error(`Property '${key}' is not supported by native animated module`);
}
}
}

function validateTransform(configs: Array<Object>): void {
configs.forEach((config) => {
if (!TRANSFORM_WHITELIST.hasOwnProperty(config.property)) {
Expand All @@ -147,7 +136,6 @@ function validateTransform(configs: Array<Object>): void {
}

function validateStyles(styles: Object): void {
var STYLES_WHITELIST = PROPS_WHITELIST.style || {};
for (var key in styles) {
if (!STYLES_WHITELIST.hasOwnProperty(key)) {
throw new Error(`Style property '${key}' is not supported by native animated module`);
Expand Down Expand Up @@ -188,7 +176,6 @@ function isNativeAnimatedAvailable(): boolean {

module.exports = {
API,
validateProps,
validateStyles,
validateTransform,
validateInterpolation,
Expand Down
7 changes: 3 additions & 4 deletions Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@

@interface RCTPropsAnimatedNode : RCTAnimatedNode

@property (nonatomic, readonly) RCTViewPropertyMapper *propertyMapper;
- (void)connectToView:(NSNumber *)viewTag
viewName:(NSString *)viewName
uiManager:(RCTUIManager *)uiManager;

- (void)connectToView:(NSNumber *)viewTag uiManager:(RCTUIManager *)uiManager;
- (void)disconnectFromView:(NSNumber *)viewTag;

- (void)performViewUpdatesIfNecessary;

@end
41 changes: 28 additions & 13 deletions Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,33 @@

#import "RCTPropsAnimatedNode.h"

#import <React/RCTLog.h>
#import <React/RCTUIManager.h>

#import "RCTAnimationUtils.h"
#import "RCTStyleAnimatedNode.h"
#import "RCTValueAnimatedNode.h"
#import "RCTViewPropertyMapper.h"

@implementation RCTPropsAnimatedNode

- (void)connectToView:(NSNumber *)viewTag uiManager:(RCTUIManager *)uiManager
{
_propertyMapper = [[RCTViewPropertyMapper alloc] initWithViewTag:viewTag uiManager:uiManager];
@implementation RCTPropsAnimatedNode {
NSNumber *_connectedViewTag;
NSString *_connectedViewName;
RCTUIManager *_uiManager;
}

- (void)disconnectFromView:(NSNumber *)viewTag
- (void)connectToView:(NSNumber *)viewTag
viewName:(NSString *)viewName
uiManager:(RCTUIManager *)uiManager
{
_propertyMapper = nil;
_connectedViewTag = viewTag;
_connectedViewName = viewName;
_uiManager = uiManager;
}

- (void)performUpdate
- (void)disconnectFromView:(NSNumber *)viewTag
{
[super performUpdate];
[self performViewUpdatesIfNecessary];
_connectedViewTag = nil;
_connectedViewName = nil;
_uiManager = nil;
}

- (NSString *)propertyNameForParentTag:(NSNumber *)parentTag
Expand All @@ -44,8 +50,15 @@ - (NSString *)propertyNameForParentTag:(NSNumber *)parentTag
return propertyName;
}

- (void)performViewUpdatesIfNecessary
- (void)performUpdate
{
[super performUpdate];

if (!_connectedViewTag) {
RCTLogError(@"Node has not been attached to a view");
return;
}

NSMutableDictionary *props = [NSMutableDictionary dictionary];
[self.parentNodes enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull parentTag, RCTAnimatedNode * _Nonnull parentNode, BOOL * _Nonnull stop) {

Expand All @@ -61,7 +74,9 @@ - (void)performViewUpdatesIfNecessary
}];

if (props.count) {
[_propertyMapper updateViewWithDictionary:props];
[_uiManager synchronouslyUpdateViewOnUIThread:_connectedViewTag
viewName:_connectedViewName
props:props];
}
}

Expand Down
41 changes: 6 additions & 35 deletions Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,56 +33,27 @@ - (void)performUpdate
{
[super performUpdate];

CATransform3D transform = CATransform3DIdentity;

NSArray<NSDictionary *> *transformConfigs = self.config[@"transforms"];
NSMutableArray<NSDictionary *> *transform = [NSMutableArray arrayWithCapacity:transformConfigs.count];
for (NSDictionary *transformConfig in transformConfigs) {
NSString *type = transformConfig[@"type"];
NSString *property = transformConfig[@"property"];

CGFloat value;
NSNumber *value;
if ([type isEqualToString: @"animated"]) {
NSNumber *nodeTag = transformConfig[@"nodeTag"];
RCTAnimatedNode *node = self.parentNodes[nodeTag];
if (![node isKindOfClass:[RCTValueAnimatedNode class]]) {
continue;
}
RCTValueAnimatedNode *parentNode = (RCTValueAnimatedNode *)node;
value = parentNode.value;
value = @(parentNode.value);
} else {
value = [transformConfig[@"value"] floatValue];
}

if ([property isEqualToString:@"scale"]) {
transform = CATransform3DScale(transform, value, value, 1);

} else if ([property isEqualToString:@"scaleX"]) {
transform = CATransform3DScale(transform, value, 1, 1);

} else if ([property isEqualToString:@"scaleY"]) {
transform = CATransform3DScale(transform, 1, value, 1);

} else if ([property isEqualToString:@"translateX"]) {
transform = CATransform3DTranslate(transform, value, 0, 0);

} else if ([property isEqualToString:@"translateY"]) {
transform = CATransform3DTranslate(transform, 0, value, 0);

} else if ([property isEqualToString:@"rotate"]) {
transform = CATransform3DRotate(transform, value, 0, 0, 1);

} else if ([property isEqualToString:@"rotateX"]) {
transform = CATransform3DRotate(transform, value, 1, 0, 0);

} else if ([property isEqualToString:@"rotateY"]) {
transform = CATransform3DRotate(transform, value, 0, 1, 0);

} else if ([property isEqualToString:@"perspective"]) {
transform.m34 = 1.0 / -value;
value = transformConfig[@"value"];
}
[transform addObject:@{property: value}];
}

_propsDictionary[@"transform"] = [NSValue valueWithCATransform3D:transform];
_propsDictionary[@"transform"] = transform;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
/* Begin PBXBuildFile section */
13E501CC1D07A644005F35D8 /* RCTAnimationUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501B81D07A644005F35D8 /* RCTAnimationUtils.m */; };
13E501CF1D07A644005F35D8 /* RCTNativeAnimatedModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501BE1D07A644005F35D8 /* RCTNativeAnimatedModule.m */; };
13E501D41D07A644005F35D8 /* RCTViewPropertyMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501C81D07A644005F35D8 /* RCTViewPropertyMapper.m */; };
13E501E81D07A6C9005F35D8 /* RCTAdditionAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501D71D07A6C9005F35D8 /* RCTAdditionAnimatedNode.m */; };
13E501E91D07A6C9005F35D8 /* RCTAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501D91D07A6C9005F35D8 /* RCTAnimatedNode.m */; };
13E501EB1D07A6C9005F35D8 /* RCTInterpolationAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501DD1D07A6C9005F35D8 /* RCTInterpolationAnimatedNode.m */; };
Expand All @@ -22,7 +21,6 @@
19F00F221DC8847500113FEE /* RCTEventAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 19F00F211DC8847500113FEE /* RCTEventAnimation.m */; };
19F00F231DC8848E00113FEE /* RCTEventAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 19F00F211DC8847500113FEE /* RCTEventAnimation.m */; };
2D3B5EF21D9B0B3100451313 /* RCTAnimationUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501B81D07A644005F35D8 /* RCTAnimationUtils.m */; };
2D3B5EF31D9B0B3400451313 /* RCTViewPropertyMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501C81D07A644005F35D8 /* RCTViewPropertyMapper.m */; };
2D3B5EF41D9B0B3700451313 /* RCTNativeAnimatedModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501BE1D07A644005F35D8 /* RCTNativeAnimatedModule.m */; };
2D3B5EF51D9B0B4800451313 /* RCTDivisionAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C9894941D999639008027DB /* RCTDivisionAnimatedNode.m */; };
2D3B5EF61D9B0B4800451313 /* RCTDiffClampAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 193F64F31D776EC6004D1CAA /* RCTDiffClampAnimatedNode.m */; };
Expand Down Expand Up @@ -51,9 +49,7 @@
13E501B81D07A644005F35D8 /* RCTAnimationUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAnimationUtils.m; sourceTree = "<group>"; };
13E501BD1D07A644005F35D8 /* RCTNativeAnimatedModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTNativeAnimatedModule.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
13E501BE1D07A644005F35D8 /* RCTNativeAnimatedModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTNativeAnimatedModule.m; sourceTree = "<group>"; };
13E501C71D07A644005F35D8 /* RCTViewPropertyMapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTViewPropertyMapper.h; sourceTree = "<group>"; };
13E501C81D07A644005F35D8 /* RCTViewPropertyMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTViewPropertyMapper.m; sourceTree = "<group>"; };
13E501D61D07A6C9005F35D8 /* RCTAdditionAnimatedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RCTAdditionAnimatedNode.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
13E501D61D07A6C9005F35D8 /* RCTAdditionAnimatedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAdditionAnimatedNode.h; sourceTree = "<group>"; };
13E501D71D07A6C9005F35D8 /* RCTAdditionAnimatedNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAdditionAnimatedNode.m; sourceTree = "<group>"; };
13E501D81D07A6C9005F35D8 /* RCTAnimatedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimatedNode.h; sourceTree = "<group>"; };
13E501D91D07A6C9005F35D8 /* RCTAnimatedNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAnimatedNode.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -130,8 +126,6 @@
children = (
13E501B71D07A644005F35D8 /* RCTAnimationUtils.h */,
13E501B81D07A644005F35D8 /* RCTAnimationUtils.m */,
13E501C71D07A644005F35D8 /* RCTViewPropertyMapper.h */,
13E501C81D07A644005F35D8 /* RCTViewPropertyMapper.m */,
13E501BD1D07A644005F35D8 /* RCTNativeAnimatedModule.h */,
13E501BE1D07A644005F35D8 /* RCTNativeAnimatedModule.m */,
94DA09161DC7971C00AEA8C9 /* RCTNativeAnimatedNodesManager.h */,
Expand Down Expand Up @@ -245,7 +239,6 @@
2D3B5EFF1D9B0B4800451313 /* RCTTransformAnimatedNode.m in Sources */,
2D3B5EFC1D9B0B4800451313 /* RCTMultiplicationAnimatedNode.m in Sources */,
2D3B5EFD1D9B0B4800451313 /* RCTPropsAnimatedNode.m in Sources */,
2D3B5EF31D9B0B3400451313 /* RCTViewPropertyMapper.m in Sources */,
944244D01DB962DA0032A02B /* RCTFrameAnimation.m in Sources */,
944244D11DB962DC0032A02B /* RCTSpringAnimation.m in Sources */,
9476E8EC1DC9232D005D5CD1 /* RCTNativeAnimatedNodesManager.m in Sources */,
Expand Down Expand Up @@ -273,7 +266,6 @@
13E501E81D07A6C9005F35D8 /* RCTAdditionAnimatedNode.m in Sources */,
5C9894951D999639008027DB /* RCTDivisionAnimatedNode.m in Sources */,
13E501EF1D07A6C9005F35D8 /* RCTTransformAnimatedNode.m in Sources */,
13E501D41D07A644005F35D8 /* RCTViewPropertyMapper.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
3 changes: 2 additions & 1 deletion Libraries/NativeAnimation/RCTNativeAnimatedModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ - (void)setBridge:(RCTBridge *)bridge
RCT_EXPORT_METHOD(connectAnimatedNodeToView:(nonnull NSNumber *)nodeTag
viewTag:(nonnull NSNumber *)viewTag)
{
NSString *viewName = [self.bridge.uiManager viewNameForReactTag:viewTag];
[_operations addObject:^(RCTNativeAnimatedNodesManager *nodesManager) {
[nodesManager connectAnimatedNodeToView:nodeTag viewTag:viewTag];
[nodesManager connectAnimatedNodeToView:nodeTag viewTag:viewTag viewName:viewName];
}];
}

Expand Down
3 changes: 2 additions & 1 deletion Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
childTag:(nonnull NSNumber *)childTag;

- (void)connectAnimatedNodeToView:(nonnull NSNumber *)nodeTag
viewTag:(nonnull NSNumber *)viewTag;
viewTag:(nonnull NSNumber *)viewTag
viewName:(nonnull NSString *)viewName;

- (void)disconnectAnimatedNodeFromView:(nonnull NSNumber *)nodeTag
viewTag:(nonnull NSNumber *)viewTag;
Expand Down
Loading