diff --git a/Libraries/Animated/src/AnimatedImplementation.js b/Libraries/Animated/src/AnimatedImplementation.js index 283ee64ea5e..7f21c4ffb5b 100644 --- a/Libraries/Animated/src/AnimatedImplementation.js +++ b/Libraries/Animated/src/AnimatedImplementation.js @@ -1160,21 +1160,24 @@ class AnimatedTransform extends AnimatedWithChildren { } __getNativeConfig(): any { - var transConfig = {}; + var transConfigs = []; this._transforms.forEach(transform => { for (var key in transform) { var value = transform[key]; if (value instanceof Animated) { - transConfig[key] = value.__getNativeTag(); + transConfigs.push({ + property: key, + nodeTag: value.__getNativeTag(), + }); } } }); - NativeAnimatedHelper.validateTransform(transConfig); + NativeAnimatedHelper.validateTransform(transConfigs); return { type: 'transform', - transform: transConfig, + transforms: transConfigs, }; } } diff --git a/Libraries/Animated/src/NativeAnimatedHelper.js b/Libraries/Animated/src/NativeAnimatedHelper.js index befbad13148..3380df24097 100644 --- a/Libraries/Animated/src/NativeAnimatedHelper.js +++ b/Libraries/Animated/src/NativeAnimatedHelper.js @@ -87,7 +87,12 @@ var TRANSFORM_WHITELIST = { translateX: true, translateY: true, scale: true, + scaleX: true, + scaleY: true, rotate: true, + rotateX: true, + rotateY: true, + perspective: true, }; function validateProps(params: Object): void { @@ -98,12 +103,12 @@ 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 validateTransform(configs: Array): void { + configs.forEach((config) => { + if (!TRANSFORM_WHITELIST.hasOwnProperty(config.property)) { + throw new Error(`Property '${config.property}' is not supported by native animated module`); } - } + }); } function validateStyles(styles: Object): void { diff --git a/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.h b/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.h index f3a6cd5dfe4..9a3dbbe32dd 100644 --- a/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.h +++ b/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.h @@ -11,6 +11,6 @@ @interface RCTStyleAnimatedNode : RCTAnimatedNode -- (NSDictionary *)updatedPropsDictionary; +- (NSDictionary *)updatedPropsDictionary; @end diff --git a/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.m b/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.m index 3dbfd327984..2c349bd22e8 100644 --- a/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.m +++ b/Libraries/NativeAnimation/Nodes/RCTStyleAnimatedNode.m @@ -14,7 +14,7 @@ @implementation RCTStyleAnimatedNode { - NSMutableDictionary *_updatedPropsDictionary; + NSMutableDictionary *_updatedPropsDictionary; } - (instancetype)initWithTag:(NSNumber *)tag diff --git a/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.h b/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.h index 6d1cfc840af..41366172d84 100644 --- a/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.h +++ b/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.h @@ -11,6 +11,6 @@ @interface RCTTransformAnimatedNode : RCTAnimatedNode -- (NSDictionary *)updatedPropsDictionary; +- (NSDictionary *)updatedPropsDictionary; @end diff --git a/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.m b/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.m index 1dcabd0a9ed..2f2799ff878 100644 --- a/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.m +++ b/Libraries/NativeAnimation/Nodes/RCTTransformAnimatedNode.m @@ -12,7 +12,7 @@ @implementation RCTTransformAnimatedNode { - NSMutableDictionary *_updatedPropsDictionary; + NSMutableDictionary *_updatedPropsDictionary; } - (instancetype)initWithTag:(NSNumber *)tag @@ -33,14 +33,50 @@ { [super performUpdate]; - NSDictionary *transforms = self.config[@"transform"]; - [transforms enumerateKeysAndObjectsUsingBlock:^(NSString *property, NSNumber *nodeTag, __unused BOOL *stop) { + CATransform3D transform = CATransform3DIdentity; + + NSArray *transformConfigs = self.config[@"transforms"]; + for (NSDictionary *transformConfig in transformConfigs) { + NSNumber *nodeTag = transformConfig[@"nodeTag"]; + RCTAnimatedNode *node = self.parentNodes[nodeTag]; if (node.hasUpdated && [node isKindOfClass:[RCTValueAnimatedNode class]]) { RCTValueAnimatedNode *parentNode = (RCTValueAnimatedNode *)node; - self->_updatedPropsDictionary[property] = @(parentNode.value); + + NSString *property = transformConfig[@"property"]; + CGFloat value = parentNode.value; + + 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; + } } - }]; + } + + _updatedPropsDictionary[@"transform"] = [NSValue valueWithCATransform3D:transform]; } - (void)cleanupAnimationUpdate diff --git a/Libraries/NativeAnimation/RCTViewPropertyMapper.h b/Libraries/NativeAnimation/RCTViewPropertyMapper.h index 29bbee754a7..791825c938b 100644 --- a/Libraries/NativeAnimation/RCTViewPropertyMapper.h +++ b/Libraries/NativeAnimation/RCTViewPropertyMapper.h @@ -6,6 +6,7 @@ * 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. */ + #import @class RCTNativeAnimatedModule; @@ -17,6 +18,6 @@ - (instancetype)initWithViewTag:(NSNumber *)viewTag animationModule:(RCTNativeAnimatedModule *)animationModule NS_DESIGNATED_INITIALIZER; -- (void)updateViewWithDictionary:(NSDictionary *)updates; +- (void)updateViewWithDictionary:(NSDictionary *)updates; @end diff --git a/Libraries/NativeAnimation/RCTViewPropertyMapper.m b/Libraries/NativeAnimation/RCTViewPropertyMapper.m index bfa9803a65e..c38296b903b 100644 --- a/Libraries/NativeAnimation/RCTViewPropertyMapper.m +++ b/Libraries/NativeAnimation/RCTViewPropertyMapper.m @@ -12,16 +12,12 @@ #import #import "RCTBridge.h" +#import "RCTConvert.h" #import "RCTUIManager.h" #import "RCTNativeAnimatedModule.h" @implementation RCTViewPropertyMapper { - CGFloat _translateX; - CGFloat _translateY; - CGFloat _scaleX; - CGFloat _scaleY; - CGFloat _rotation; RCTNativeAnimatedModule *_animationModule; } @@ -31,63 +27,33 @@ if ((self = [super init])) { _animationModule = animationModule; _viewTag = viewTag; - _translateX = 0; - _translateY = 0; - _scaleX = 1; - _scaleY = 1; - _rotation = 0; + _animationModule = animationModule; } return self; } RCT_NOT_IMPLEMENTED(- (instancetype)init) -- (void)updateViewWithDictionary:(NSDictionary *)updates +- (void)updateViewWithDictionary:(NSDictionary *)updates { - if (updates.count) { - UIView *view = [_animationModule.bridge.uiManager viewForReactTag:_viewTag]; - if (!view) { - return; - } + if (!updates.count) { + return; + } - NSNumber *opacity = updates[@"opacity"]; - if (opacity) { - view.alpha = opacity.doubleValue; - } + UIView *view = [_animationModule.bridge.uiManager viewForReactTag:_viewTag]; + if (!view) { + return; + } - NSNumber *scale = updates[@"scale"]; - if (scale) { - _scaleX = scale.doubleValue; - _scaleY = scale.doubleValue; - } - NSNumber *scaleX = updates[@"scaleX"]; - if (scaleX) { - _scaleX = scaleX.doubleValue; - } - NSNumber *scaleY = updates[@"scaleY"]; - if (scaleY) { - _scaleY = scaleY.doubleValue; - } - NSNumber *translateX = updates[@"translateX"]; - if (translateX) { - _translateX = translateX.doubleValue; - } - NSNumber *translateY = updates[@"translateY"]; - if (translateY) { - _translateY = translateY.doubleValue; - } - NSNumber *rotation = updates[@"rotate"]; - if (rotation) { - _rotation = rotation.doubleValue; - } + NSNumber *opacity = [RCTConvert NSNumber:updates[@"opacity"]]; + if (opacity) { + view.alpha = opacity.floatValue; + } - if (translateX || translateY || scale || scaleX || scaleY || rotation) { - CATransform3D xform = CATransform3DMakeScale(_scaleX, _scaleY, 0); - xform = CATransform3DTranslate(xform, _translateX, _translateY, 0); - xform = CATransform3DRotate(xform, _rotation, 0, 0, 1); - view.layer.allowsEdgeAntialiasing = YES; - view.layer.transform = xform; - } + NSObject *transform = updates[@"transform"]; + if ([transform isKindOfClass:[NSValue class]]) { + view.layer.allowsEdgeAntialiasing = YES; + view.layer.transform = ((NSValue *)transform).CATransform3DValue; } }