[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()) {
|
||||
offset.opacity = 0;
|
||||
} else {
|
||||
var point = [
|
||||
animationPosition(tile.toColumn()),
|
||||
animationPosition(tile.toRow()),
|
||||
];
|
||||
AnimationExperimental.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {position: point});
|
||||
var point = {
|
||||
x: animationPosition(tile.toColumn()),
|
||||
y: animationPosition(tile.toRow()),
|
||||
};
|
||||
AnimationExperimental.startAnimation({
|
||||
node: this.refs['this'],
|
||||
duration: 100,
|
||||
easing: 'easeInOutQuad',
|
||||
property: 'position',
|
||||
toValue: point,
|
||||
});
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
|
|
|
@ -16,6 +16,17 @@ var AnimationUtils = require('AnimationUtils');
|
|||
|
||||
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,
|
||||
* 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.
|
||||
*/
|
||||
var AnimationExperimental = {
|
||||
Mixin: require('AnimationExperimentalMixin'),
|
||||
|
||||
startAnimation: function(
|
||||
node: any,
|
||||
duration: number,
|
||||
delay: number,
|
||||
easing: (string | EasingFunction),
|
||||
properties: {[key: string]: any}
|
||||
anim: {
|
||||
node: any;
|
||||
duration: number;
|
||||
easing: ($Enum<typeof AnimationUtils.Defaults> | EasingFunction);
|
||||
property: $Enum<typeof Properties>;
|
||||
toValue: ValueType;
|
||||
fromValue?: ValueType;
|
||||
delay?: number;
|
||||
},
|
||||
callback?: ?(finished: bool) => void
|
||||
): number {
|
||||
var nodeHandle = +node.getNodeHandle();
|
||||
var easingSample = AnimationUtils.evaluateEasingFunction(duration, easing);
|
||||
var tag: number = RCTAnimationManager.startAnimation(
|
||||
var nodeHandle = anim.node.getNodeHandle();
|
||||
var easingSample = AnimationUtils.evaluateEasingFunction(
|
||||
anim.duration,
|
||||
anim.easing
|
||||
);
|
||||
var tag: number = AnimationUtils.allocateTag();
|
||||
var props = {};
|
||||
props[anim.property] = {to: anim.toValue};
|
||||
RCTAnimationManager.startAnimation(
|
||||
nodeHandle,
|
||||
AnimationUtils.allocateTag(),
|
||||
duration,
|
||||
delay,
|
||||
tag,
|
||||
anim.duration,
|
||||
anim.delay,
|
||||
easingSample,
|
||||
properties
|
||||
props,
|
||||
callback
|
||||
);
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
var defaults = {
|
||||
easeInQuad: function(t) {
|
||||
easeInQuad: function(t: number): number {
|
||||
return t * t;
|
||||
},
|
||||
easeOutQuad: function(t) {
|
||||
easeOutQuad: function(t: number): number {
|
||||
return -t * (t - 2);
|
||||
},
|
||||
easeInOutQuad: function(t) {
|
||||
easeInOutQuad: function(t: number): number {
|
||||
t = t * 2;
|
||||
if (t < 1) {
|
||||
return 0.5 * t * t;
|
||||
}
|
||||
return -((t - 1) * (t - 3) - 1) / 2;
|
||||
},
|
||||
easeInCubic: function(t) {
|
||||
easeInCubic: function(t: number): number {
|
||||
return t * t * t;
|
||||
},
|
||||
easeOutCubic: function(t) {
|
||||
easeOutCubic: function(t: number): number {
|
||||
t -= 1;
|
||||
return t * t * t + 1;
|
||||
},
|
||||
easeInOutCubic: function(t) {
|
||||
easeInOutCubic: function(t: number): number {
|
||||
t *= 2;
|
||||
if (t < 1) {
|
||||
return 0.5 * t * t * t;
|
||||
|
@ -48,14 +48,14 @@ var defaults = {
|
|||
t -= 2;
|
||||
return (t * t * t + 2) / 2;
|
||||
},
|
||||
easeInQuart: function(t) {
|
||||
easeInQuart: function(t: number): number {
|
||||
return t * t * t * t;
|
||||
},
|
||||
easeOutQuart: function(t) {
|
||||
easeOutQuart: function(t: number): number {
|
||||
t -= 1;
|
||||
return -(t * t * t * t - 1);
|
||||
},
|
||||
easeInOutQuart: function(t) {
|
||||
easeInOutQuart: function(t: number): number {
|
||||
t *= 2;
|
||||
if (t < 1) {
|
||||
return 0.5 * t * t * t * t;
|
||||
|
@ -63,14 +63,14 @@ var defaults = {
|
|||
t -= 2;
|
||||
return -(t * t * t * t - 2) / 2;
|
||||
},
|
||||
easeInQuint: function(t) {
|
||||
easeInQuint: function(t: number): number {
|
||||
return t * t * t * t * t;
|
||||
},
|
||||
easeOutQuint: function(t) {
|
||||
easeOutQuint: function(t: number): number {
|
||||
t -= 1;
|
||||
return t * t * t * t * t + 1;
|
||||
},
|
||||
easeInOutQuint: function(t) {
|
||||
easeInOutQuint: function(t: number): number {
|
||||
t *= 2;
|
||||
if (t < 1) {
|
||||
return (t * t * t * t * t) / 2;
|
||||
|
@ -78,22 +78,22 @@ var defaults = {
|
|||
t -= 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;
|
||||
},
|
||||
easeOutSine: function(t) {
|
||||
easeOutSine: function(t: number): number {
|
||||
return Math.sin(t * (Math.PI / 2));
|
||||
},
|
||||
easeInOutSine: function(t) {
|
||||
easeInOutSine: function(t: number): number {
|
||||
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));
|
||||
},
|
||||
easeOutExpo: function(t) {
|
||||
easeOutExpo: function(t: number): number {
|
||||
return (t === 1) ? 1 : (-Math.pow(2, -10 * t) + 1);
|
||||
},
|
||||
easeInOutExpo: function(t) {
|
||||
easeInOutExpo: function(t: number): number {
|
||||
if (t === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -106,14 +106,14 @@ var defaults = {
|
|||
}
|
||||
return (-Math.pow(2, -10 * (t - 1)) + 2) / 2;
|
||||
},
|
||||
easeInCirc: function(t) {
|
||||
easeInCirc: function(t: number): number {
|
||||
return -(Math.sqrt(1 - t * t) - 1);
|
||||
},
|
||||
easeOutCirc: function(t) {
|
||||
easeOutCirc: function(t: number): number {
|
||||
t -= 1;
|
||||
return Math.sqrt(1 - t * t);
|
||||
},
|
||||
easeInOutCirc: function(t) {
|
||||
easeInOutCirc: function(t: number): number {
|
||||
t *= 2;
|
||||
if (t < 1) {
|
||||
return -(Math.sqrt(1 - t * t) - 1) / 2;
|
||||
|
@ -121,7 +121,7 @@ var defaults = {
|
|||
t -= 2;
|
||||
return (Math.sqrt(1 - t * t) + 1) / 2;
|
||||
},
|
||||
easeInElastic: function(t) {
|
||||
easeInElastic: function(t: number): number {
|
||||
var s = 1.70158;
|
||||
var p = 0.3;
|
||||
if (t === 0) {
|
||||
|
@ -134,7 +134,7 @@ var defaults = {
|
|||
t -= 1;
|
||||
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 p = 0.3;
|
||||
if (t === 0) {
|
||||
|
@ -146,7 +146,7 @@ var defaults = {
|
|||
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;
|
||||
},
|
||||
easeInOutElastic: function(t) {
|
||||
easeInOutElastic: function(t: number): number {
|
||||
var s = 1.70158;
|
||||
var p = 0.3 * 1.5;
|
||||
if (t === 0) {
|
||||
|
@ -164,16 +164,16 @@ var defaults = {
|
|||
t -= 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;
|
||||
return t * t * ((s + 1) * t - s);
|
||||
},
|
||||
easeOutBack: function(t) {
|
||||
easeOutBack: function(t: number): number {
|
||||
var s = 1.70158;
|
||||
t -= 1;
|
||||
return (t * t * ((s + 1) * t + s) + 1);
|
||||
},
|
||||
easeInOutBack: function(t) {
|
||||
easeInOutBack: function(t: number): number {
|
||||
var s = 1.70158 * 1.525;
|
||||
t *= 2;
|
||||
if (t < 1) {
|
||||
|
@ -182,10 +182,10 @@ var defaults = {
|
|||
t -= 2;
|
||||
return (t * t * ((s + 1) * t + s) + 2) / 2;
|
||||
},
|
||||
easeInBounce: function(t) {
|
||||
easeInBounce: function(t: number): number {
|
||||
return 1 - this.easeOutBounce(1 - t);
|
||||
},
|
||||
easeOutBounce: function(t) {
|
||||
easeOutBounce: function(t: number): number {
|
||||
if (t < (1 / 2.75)) {
|
||||
return 7.5625 * t * t;
|
||||
} else if (t < (2 / 2.75)) {
|
||||
|
@ -199,7 +199,7 @@ var defaults = {
|
|||
return 7.5625 * t * t + 0.984375;
|
||||
}
|
||||
},
|
||||
easeInOutBounce: function(t) {
|
||||
easeInOutBounce: function(t: number): number {
|
||||
if (t < 0.5) {
|
||||
return this.easeInBounce(t * 2) / 2;
|
||||
}
|
||||
|
@ -234,4 +234,6 @@ module.exports = {
|
|||
|
||||
return samples;
|
||||
},
|
||||
|
||||
Defaults: defaults,
|
||||
};
|
||||
|
|
|
@ -17,18 +17,20 @@ var RCTUIManager = require('NativeModules').UIManager;
|
|||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||
var keyMirror = require('keyMirror');
|
||||
|
||||
var Types = keyMirror({
|
||||
var TypesEnum = {
|
||||
spring: true,
|
||||
linear: true,
|
||||
easeInEaseOut: true,
|
||||
easeIn: true,
|
||||
easeOut: true,
|
||||
});
|
||||
};
|
||||
var Types = keyMirror(TypesEnum);
|
||||
|
||||
var Properties = keyMirror({
|
||||
var PropertiesEnum = {
|
||||
opacity: true,
|
||||
scaleXY: true,
|
||||
});
|
||||
};
|
||||
var Properties = keyMirror(PropertiesEnum);
|
||||
|
||||
var animChecker = createStrictShapeTypeChecker({
|
||||
duration: PropTypes.number,
|
||||
|
@ -48,8 +50,8 @@ type Anim = {
|
|||
delay?: number;
|
||||
springDamping?: number;
|
||||
initialVelocity?: number;
|
||||
type?: $Enum<typeof Types>;
|
||||
property?: $Enum<typeof Properties>;
|
||||
type?: $Enum<typeof TypesEnum>;
|
||||
property?: $Enum<typeof PropertiesEnum>;
|
||||
}
|
||||
|
||||
var configChecker = createStrictShapeTypeChecker({
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
#if CGFLOAT_IS_DOUBLE
|
||||
#define CG_APPEND(PREFIX, SUFFIX_F, SUFFIX_D) PREFIX##SUFFIX_D
|
||||
|
@ -23,6 +24,8 @@
|
|||
@implementation RCTAnimationExperimentalManager
|
||||
{
|
||||
RCTSparseArray *_animationRegistry; // Main thread only; animation tag -> view tag
|
||||
RCTSparseArray *_callbackRegistry; // Main thread only; animation tag -> callback
|
||||
NSDictionary *_keypathMapping;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
@ -33,6 +36,33 @@ RCT_EXPORT_MODULE()
|
|||
{
|
||||
if ((self = [super 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;
|
||||
|
@ -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
|
||||
duration:(NSTimeInterval)duration
|
||||
delay:(NSTimeInterval)delay
|
||||
easingSample:(NSArray *)easingSample
|
||||
properties:(NSDictionary *)properties)
|
||||
properties:(NSDictionary *)properties
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
__weak RCTAnimationExperimentalManager *weakSelf = self;
|
||||
[_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);
|
||||
return;
|
||||
}
|
||||
|
||||
[properties enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
|
||||
__block BOOL completionBlockSet = NO;
|
||||
[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;
|
||||
if ([key isEqualToString:@"scaleXY"]) {
|
||||
key = @"transform.scale";
|
||||
toValue = obj[0];
|
||||
if ([keypath isEqualToString:@"transform.scale"]) {
|
||||
CGPoint point = [RCTConvert CGPoint:obj];
|
||||
if (point.x != point.y) {
|
||||
return RCTInvalidAnimationProp(strongSelf->_callbackRegistry, animationTag, keypath, obj);
|
||||
}
|
||||
toValue = @(point.x);
|
||||
} else if ([obj respondsToSelector:@selector(count)]) {
|
||||
switch ([obj count]) {
|
||||
case 2:
|
||||
|
@ -100,11 +152,15 @@ RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
|||
case 16:
|
||||
toValue = [NSValue valueWithCGAffineTransform:[RCTConvert CGAffineTransform:obj]];
|
||||
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;
|
||||
|
||||
size_t count;
|
||||
|
@ -155,7 +211,7 @@ RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
|||
break;
|
||||
}
|
||||
|
||||
NSValue *fromValue = [view.layer.presentationLayer valueForKeyPath:key];
|
||||
NSValue *fromValue = [view.layer.presentationLayer valueForKeyPath:keypath];
|
||||
CGFloat fromFields[count];
|
||||
[fromValue getValue:fromFields];
|
||||
|
||||
|
@ -166,19 +222,32 @@ RCT_EXPORT_METHOD(startAnimationForTag:(NSNumber *)reactTag
|
|||
CGFloat t = sample.CG_APPEND(, floatValue, doubleValue);
|
||||
[sampledValues addObject:interpolationBlock(t)];
|
||||
}
|
||||
|
||||
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:key];
|
||||
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keypath];
|
||||
animation.beginTime = CACurrentMediaTime() + delay;
|
||||
animation.duration = duration;
|
||||
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];
|
||||
}];
|
||||
|
||||
@try {
|
||||
[view.layer setValue:toValue forKey:keypath];
|
||||
NSString *animationKey = [@"RCT" stringByAppendingString:RCTJSONStringify(@{@"tag": animationTag, @"key": keypath}, nil)];
|
||||
[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;
|
||||
}];
|
||||
}
|
||||
|
@ -194,19 +263,25 @@ RCT_EXPORT_METHOD(stopAnimation:(NSNumber *)animationTag)
|
|||
|
||||
UIView *view = viewRegistry[reactTag];
|
||||
for (NSString *animationKey in view.layer.animationKeys) {
|
||||
if ([animationKey hasPrefix:@"RCT"]) {
|
||||
NSRange periodLocation = [animationKey rangeOfString:@"." options:0 range:(NSRange){3, animationKey.length - 3}];
|
||||
if (periodLocation.location != NSNotFound) {
|
||||
NSInteger integerTag = [[animationKey substringWithRange:(NSRange){3, periodLocation.location}] integerValue];
|
||||
if (animationTag.integerValue == integerTag) {
|
||||
[view.layer removeAnimationForKey:animationKey];
|
||||
}
|
||||
if ([animationKey hasPrefix:@"RCT{"]) {
|
||||
NSDictionary *data = RCTJSONParse([animationKey substringFromIndex:3], nil);
|
||||
if (animationTag.integerValue == [data[@"tag"] integerValue]) {
|
||||
[view.layer removeAnimationForKey:animationKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RCTResponseSenderBlock cb = strongSelf->_callbackRegistry[animationTag];
|
||||
if (cb) {
|
||||
cb(@[@NO]);
|
||||
strongSelf->_callbackRegistry[animationTag] = nil;
|
||||
}
|
||||
strongSelf->_animationRegistry[animationTag] = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return @{@"Properties": [_keypathMapping allKeys] };
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -22,7 +22,7 @@ var copyProperties = require('copyProperties');
|
|||
var onlyChild = require('onlyChild');
|
||||
|
||||
type State = {
|
||||
animationID: ?number;
|
||||
animationID: ?number;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -60,7 +60,7 @@ var TouchableBounce = React.createClass({
|
|||
value: number,
|
||||
velocity: number,
|
||||
bounciness: number,
|
||||
fromValue?: ?Function | number,
|
||||
fromValue?: ?number,
|
||||
callback?: ?Function
|
||||
) {
|
||||
if (POPAnimation) {
|
||||
|
@ -71,21 +71,21 @@ var TouchableBounce = React.createClass({
|
|||
toValue: [value, value],
|
||||
velocity: [velocity, velocity],
|
||||
springBounciness: bounciness,
|
||||
fromValue: (undefined: ?any),
|
||||
fromValue: fromValue ? [fromValue, fromValue] : undefined,
|
||||
};
|
||||
if (fromValue) {
|
||||
anim.fromValue = [fromValue, fromValue];
|
||||
}
|
||||
this.state.animationID = POPAnimation.createSpringAnimation(anim);
|
||||
this.addAnimation(this.state.animationID, callback);
|
||||
} else {
|
||||
AnimationExperimental.startAnimation(this, 300, 0, 'easeOutBack', {scaleXY: [value, value]});
|
||||
if (fromValue && typeof fromValue === 'function') {
|
||||
callback = fromValue;
|
||||
}
|
||||
if (callback) {
|
||||
setTimeout(callback, 300);
|
||||
}
|
||||
AnimationExperimental.startAnimation(
|
||||
{
|
||||
node: this,
|
||||
duration: 300,
|
||||
easing: 'easeOutBack',
|
||||
property: 'scaleXY',
|
||||
toValue: { x: value, y: value},
|
||||
},
|
||||
callback
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue