Second Update from Tue 24 Mar

This commit is contained in:
Christopher Chedeau
2015-03-24 19:34:12 -07:00
parent 8068c65f12
commit ead3a740ca
121 changed files with 6808 additions and 667 deletions

View File

@@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule LayoutAnimation
* @flow
*/
'use strict';
@@ -42,6 +43,15 @@ var animChecker = createStrictShapeTypeChecker({
),
});
type Anim = {
duration?: number;
delay?: number;
springDamping?: number;
initialVelocity?: number;
type?: $Enum<typeof Types>;
property?: $Enum<typeof Properties>;
}
var configChecker = createStrictShapeTypeChecker({
duration: PropTypes.number.isRequired,
create: animChecker,
@@ -49,46 +59,56 @@ var configChecker = createStrictShapeTypeChecker({
delete: animChecker,
});
var LayoutAnimation = {
configureNext(config, onAnimationDidEnd, onError) {
configChecker({config}, 'config', 'LayoutAnimation.configureNext');
RCTUIManager.configureNextLayoutAnimation(config, onAnimationDidEnd, onError);
},
create(duration, type, creationProp) {
return {
duration,
create: {
type,
property: creationProp,
},
update: {
type,
},
};
},
Types: Types,
Properties: Properties,
configChecker: configChecker,
};
type Config = {
duration: number;
create?: Anim;
update?: Anim;
delete?: Anim;
}
LayoutAnimation.Presets = {
easeInEaseOut: LayoutAnimation.create(
0.3, Types.easeInEaseOut, Properties.opacity
),
linear: LayoutAnimation.create(
0.5, Types.linear, Properties.opacity
),
spring: {
duration: 0.7,
function configureNext(config: Config, onAnimationDidEnd?: Function, onError?: Function) {
configChecker({config}, 'config', 'LayoutAnimation.configureNext');
RCTUIManager.configureNextLayoutAnimation(config, onAnimationDidEnd, onError);
}
function create(duration: number, type, creationProp): Config {
return {
duration,
create: {
type: Types.linear,
property: Properties.opacity,
type,
property: creationProp,
},
update: {
type: Types.spring,
springDamping: 0.4,
type,
},
},
};
}
var LayoutAnimation = {
configureNext,
create,
Types,
Properties,
configChecker: configChecker,
Presets: {
easeInEaseOut: create(
0.3, Types.easeInEaseOut, Properties.opacity
),
linear: create(
0.5, Types.linear, Properties.opacity
),
spring: {
duration: 0.7,
create: {
type: Types.linear,
property: Properties.opacity,
},
update: {
type: Types.spring,
springDamping: 0.4,
},
},
}
};
module.exports = LayoutAnimation;

View File

@@ -0,0 +1,256 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
13BE3DEE1AC21097009241FE /* RCTAnimationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* RCTAnimationManager.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
58B511D91A9E6C8500147676 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libRCTAnimation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTAnimation.a; sourceTree = BUILT_PRODUCTS_DIR; };
13BE3DEC1AC21097009241FE /* RCTAnimationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationManager.h; sourceTree = "<group>"; };
13BE3DED1AC21097009241FE /* RCTAnimationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAnimationManager.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
58B511D81A9E6C8500147676 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
134814211AA4EA7D00B7C361 /* Products */ = {
isa = PBXGroup;
children = (
134814201AA4EA6300B7C361 /* libRCTAnimation.a */,
);
name = Products;
sourceTree = "<group>";
};
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
13BE3DEC1AC21097009241FE /* RCTAnimationManager.h */,
13BE3DED1AC21097009241FE /* RCTAnimationManager.m */,
134814211AA4EA7D00B7C361 /* Products */,
);
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
58B511DA1A9E6C8500147676 /* RCTAnimation */ = {
isa = PBXNativeTarget;
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimation" */;
buildPhases = (
58B511D71A9E6C8500147676 /* Sources */,
58B511D81A9E6C8500147676 /* Frameworks */,
58B511D91A9E6C8500147676 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = RCTAnimation;
productName = RCTDataManager;
productReference = 134814201AA4EA6300B7C361 /* libRCTAnimation.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
58B511D31A9E6C8500147676 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
58B511DA1A9E6C8500147676 = {
CreatedOnToolsVersion = 6.1.1;
};
};
};
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimation" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 58B511D21A9E6C8500147676;
productRefGroup = 58B511D21A9E6C8500147676;
projectDirPath = "";
projectRoot = "";
targets = (
58B511DA1A9E6C8500147676 /* RCTAnimation */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
58B511D71A9E6C8500147676 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13BE3DEE1AC21097009241FE /* RCTAnimationManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
58B511ED1A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
58B511EE1A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
58B511F01A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../ReactKit/**",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos",
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RCTAnimation;
SKIP_INSTALL = YES;
};
name = Debug;
};
58B511F11A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../ReactKit/**",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos",
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RCTAnimation;
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimation" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511ED1A9E6C8500147676 /* Debug */,
58B511EE1A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimation" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511F01A9E6C8500147676 /* Debug */,
58B511F11A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
}

View File

@@ -0,0 +1,17 @@
/**
* 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.
*/
#import <Accelerate/Accelerate.h>
#import <Foundation/Foundation.h>
#import "RCTBridgeModule.h"
@interface RCTAnimationManager : NSObject <RCTBridgeModule>
@end

View File

@@ -0,0 +1,209 @@
/**
* 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.
*/
#import "RCTAnimationManager.h"
#import <UIKit/UIKit.h>
#import "RCTSparseArray.h"
#import "RCTUIManager.h"
#if CGFLOAT_IS_DOUBLE
#define CG_APPEND(PREFIX, SUFFIX_F, SUFFIX_D) PREFIX##SUFFIX_D
#else
#define CG_APPEND(PREFIX, SUFFIX_F, SUFFIX_D) PREFIX##SUFFIX_F
#endif
@implementation RCTAnimationManager
{
RCTSparseArray *_animationRegistry; // Main thread only; animation tag -> view tag
}
@synthesize bridge = _bridge;
- (instancetype)init
{
if ((self = [super init])) {
_animationRegistry = [[RCTSparseArray alloc] init];
}
return self;
}
- (id (^)(CGFloat))interpolateFrom:(CGFloat[])fromArray to:(CGFloat[])toArray count:(NSUInteger)count typeName:(const char *)typeName
{
if (count == 1) {
CGFloat from = *fromArray, to = *toArray, delta = to - from;
return ^(CGFloat t) {
return @(from + t * delta);
};
}
CG_APPEND(vDSP_vsub,,D)(fromArray, 1, toArray, 1, toArray, 1, count);
const size_t size = count * sizeof(CGFloat);
NSData *deltaData = [NSData dataWithBytes:toArray length:size];
NSData *fromData = [NSData dataWithBytes:fromArray length:size];
return ^(CGFloat t) {
const CGFloat *delta = deltaData.bytes;
const CGFloat *_fromArray = fromData.bytes;
CGFloat value[count];
CG_APPEND(vDSP_vma,,D)(delta, 1, &t, 0, _fromArray, 1, value, 1, count);
return [NSValue valueWithBytes:value objCType:typeName];
};
}
- (void)startAnimationForTag:(NSNumber *)reactTag animationTag:(NSNumber *)animationTag duration:(double)duration delay:(double)delay easingSample:(NSArray *)easingSample properties:(NSDictionary *)properties
{
RCT_EXPORT(startAnimation);
__weak RCTAnimationManager *weakSelf = self;
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
RCTAnimationManager *strongSelf = weakSelf;
UIView *view = viewRegistry[reactTag];
if (!view) {
RCTLogWarn(@"React tag %@ is not registered with the view registry", reactTag);
return;
}
[properties enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
NSValue *toValue = nil;
if ([key isEqualToString:@"scaleXY"]) {
key = @"transform.scale";
toValue = obj[0];
} else if ([obj respondsToSelector:@selector(count)]) {
switch ([obj count]) {
case 2:
if ([obj respondsToSelector:@selector(objectForKeyedSubscript:)] && obj[@"x"]) {
toValue = [NSValue valueWithCGPoint:[RCTConvert CGPoint:obj]];
} else {
toValue = [NSValue valueWithCGSize:[RCTConvert CGSize:obj]];
}
break;
case 4:
toValue = [NSValue valueWithCGRect:[RCTConvert CGRect:obj]];
break;
case 16:
toValue = [NSValue valueWithCGAffineTransform:[RCTConvert CGAffineTransform:obj]];
break;
}
}
if (!toValue) toValue = obj;
const char *typeName = toValue.objCType;
size_t count;
switch (typeName[0]) {
case 'i':
case 'I':
case 's':
case 'S':
case 'l':
case 'L':
case 'q':
case 'Q':
count = 1;
break;
default: {
NSUInteger size;
NSGetSizeAndAlignment(typeName, &size, NULL);
count = size / sizeof(CGFloat);
break;
}
}
CGFloat toFields[count];
switch (typeName[0]) {
#define CASE(encoding, type) \
case encoding: { \
type value; \
[toValue getValue:&value]; \
toFields[0] = value; \
break; \
}
CASE('i', int)
CASE('I', unsigned int)
CASE('s', short)
CASE('S', unsigned short)
CASE('l', long)
CASE('L', unsigned long)
CASE('q', long long)
CASE('Q', unsigned long long)
#undef CASE
default:
[toValue getValue:toFields];
break;
}
NSValue *fromValue = [view.layer.presentationLayer valueForKeyPath:key];
CGFloat fromFields[count];
[fromValue getValue:fromFields];
id (^interpolationBlock)(CGFloat t) = [strongSelf interpolateFrom:fromFields to:toFields count:count typeName:typeName];
NSMutableArray *sampledValues = [NSMutableArray arrayWithCapacity:easingSample.count];
for (NSNumber *sample in easingSample) {
CGFloat t = sample.CG_APPEND(, floatValue, doubleValue);
[sampledValues addObject:interpolationBlock(t)];
}
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:key];
animation.beginTime = CACurrentMediaTime() + delay / 1000.0;
animation.duration = duration / 1000.0;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.values = sampledValues;
[view.layer setValue:toValue forKey:key];
NSString *animationKey = [NSString stringWithFormat:@"RCT.%@.%@", animationTag, key];
[view.layer addAnimation:animation forKey:animationKey];
}];
strongSelf->_animationRegistry[animationTag] = reactTag;
}];
}
- (void)stopAnimation:(NSNumber *)animationTag
{
RCT_EXPORT(stopAnimation);
__weak RCTAnimationManager *weakSelf = self;
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
RCTAnimationManager *strongSelf = weakSelf;
NSNumber *reactTag = strongSelf->_animationRegistry[animationTag];
if (!reactTag) return;
UIView *view = viewRegistry[reactTag];
for (NSString *animationKey in view.layer.animationKeys) {
if ([animationKey hasPrefix:@"RCT"]) {
NSRange periodLocation = [animationKey rangeOfString:@"." options:0 range:NSMakeRange(3, animationKey.length - 3)];
if (periodLocation.location != NSNotFound) {
NSInteger integerTag = [[animationKey substringWithRange:NSMakeRange(3, periodLocation.location)] integerValue];
if (animationTag.integerValue == integerTag) {
[view.layer removeAnimationForKey:animationKey];
}
}
}
}
strongSelf->_animationRegistry[animationTag] = nil;
}];
}
@end