mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-13 22:43:59 +08:00
Add support for springs for NativeAnimated on iOS
Summary: This diff adds support for native spring animations on iOS. This overlaps some spring work done by kmagiera on the Android side of things. **Test plan (required)** Run UIExplorer NativeAnimated examples before and after - compare the results. Pay special attention to the spring examples. Closes https://github.com/facebook/react-native/pull/9048 Differential Revision: D4056088 Pulled By: foghina fbshipit-source-id: a593408cb61cb850572bab4a0884f7157cece656
This commit is contained in:
committed by
Facebook Github Bot
parent
5e94114497
commit
d950db4ef7
@@ -1,40 +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.
|
||||
*/
|
||||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@class RCTValueAnimatedNode;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RCTAnimationDriverNode : NSObject
|
||||
|
||||
@property (nonatomic, readonly) NSNumber *animationId;
|
||||
@property (nonatomic, readonly) NSNumber *outputValue;
|
||||
|
||||
@property (nonatomic, readonly) BOOL animationHasBegun;
|
||||
@property (nonatomic, readonly) BOOL animationHasFinished;
|
||||
|
||||
- (instancetype)initWithId:(NSNumber *)animationId
|
||||
delay:(NSTimeInterval)delay
|
||||
toValue:(CGFloat)toValue
|
||||
frames:(NSArray<NSNumber *> *)frames
|
||||
forNode:(RCTValueAnimatedNode *)valueNode
|
||||
callBack:(nullable RCTResponseSenderBlock)callback NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)startAnimation;
|
||||
- (void)stopAnimation;
|
||||
- (void)stepAnimation;
|
||||
- (void)removeAnimation;
|
||||
- (void)cleanupAnimationUpdate;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,148 +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.
|
||||
*/
|
||||
|
||||
#import "RCTAnimationDriverNode.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTAnimationUtils.h"
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTValueAnimatedNode.h"
|
||||
|
||||
const double SINGLE_FRAME_INTERVAL = 1.0 / 60.0;
|
||||
|
||||
@implementation RCTAnimationDriverNode
|
||||
{
|
||||
NSArray<NSNumber *> *_frames;
|
||||
CGFloat _toValue;
|
||||
CGFloat _fromValue;
|
||||
NSTimeInterval _delay;
|
||||
NSTimeInterval _animationStartTime;
|
||||
NSTimeInterval _animationCurrentTime;
|
||||
RCTValueAnimatedNode *_valueNode;
|
||||
RCTResponseSenderBlock _callback;
|
||||
}
|
||||
|
||||
- (instancetype)initWithId:(nonnull NSNumber *)animationId
|
||||
delay:(NSTimeInterval)delay
|
||||
toValue:(CGFloat)toValue
|
||||
frames:(nonnull NSArray<NSNumber *> *)frames
|
||||
forNode:(nonnull RCTValueAnimatedNode *)valueNode
|
||||
callBack:(nullable RCTResponseSenderBlock)callback
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_animationId = animationId;
|
||||
_toValue = toValue;
|
||||
_fromValue = valueNode.value;
|
||||
_valueNode = valueNode;
|
||||
_delay = delay;
|
||||
_frames = [frames copy];
|
||||
_outputValue = @0;
|
||||
_callback = [callback copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
|
||||
- (void)startAnimation
|
||||
{
|
||||
_animationStartTime = CACurrentMediaTime();
|
||||
_animationCurrentTime = _animationStartTime;
|
||||
_animationHasBegun = YES;
|
||||
}
|
||||
|
||||
- (void)stopAnimation
|
||||
{
|
||||
_animationHasFinished = YES;
|
||||
}
|
||||
|
||||
- (void)removeAnimation
|
||||
{
|
||||
[self stopAnimation];
|
||||
_valueNode = nil;
|
||||
if (_callback) {
|
||||
_callback(@[@{
|
||||
@"finished": @(_animationHasFinished)
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stepAnimation
|
||||
{
|
||||
if (!_animationHasBegun || _animationHasFinished || _frames.count == 0) {
|
||||
// Animation has not begun or animation has already finished.
|
||||
return;
|
||||
}
|
||||
|
||||
NSTimeInterval currentTime = CACurrentMediaTime();
|
||||
NSTimeInterval stepInterval = currentTime - _animationCurrentTime;
|
||||
_animationCurrentTime = currentTime;
|
||||
NSTimeInterval currentDuration = _animationCurrentTime - _animationStartTime;
|
||||
|
||||
if (_delay > 0) {
|
||||
// Decrement delay
|
||||
_delay -= stepInterval;
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine how many frames have passed since last update.
|
||||
// Get index of frames that surround the current interval
|
||||
NSUInteger startIndex = floor(currentDuration / SINGLE_FRAME_INTERVAL);
|
||||
NSUInteger nextIndex = startIndex + 1;
|
||||
|
||||
if (nextIndex >= _frames.count) {
|
||||
// We are at the end of the animation
|
||||
// Update value and flag animation has ended.
|
||||
NSNumber *finalValue = _frames.lastObject;
|
||||
[self updateOutputWithFrameOutput:finalValue.doubleValue];
|
||||
[self stopAnimation];
|
||||
return;
|
||||
}
|
||||
|
||||
// Do a linear remap of the two frames to safegaurd against variable framerates
|
||||
NSNumber *fromFrameValue = _frames[startIndex];
|
||||
NSNumber *toFrameValue = _frames[nextIndex];
|
||||
NSTimeInterval fromInterval = startIndex * SINGLE_FRAME_INTERVAL;
|
||||
NSTimeInterval toInterval = nextIndex * SINGLE_FRAME_INTERVAL;
|
||||
|
||||
// Interpolate between the individual frames to ensure the animations are
|
||||
//smooth and of the proper duration regardless of the framerate.
|
||||
CGFloat frameOutput = RCTInterpolateValue(currentDuration,
|
||||
fromInterval,
|
||||
toInterval,
|
||||
fromFrameValue.doubleValue,
|
||||
toFrameValue.doubleValue,
|
||||
EXTRAPOLATE_TYPE_EXTEND,
|
||||
EXTRAPOLATE_TYPE_EXTEND);
|
||||
|
||||
[self updateOutputWithFrameOutput:frameOutput];
|
||||
}
|
||||
|
||||
- (void)updateOutputWithFrameOutput:(CGFloat)frameOutput
|
||||
{
|
||||
CGFloat outputValue = RCTInterpolateValue(frameOutput,
|
||||
0,
|
||||
1,
|
||||
_fromValue,
|
||||
_toValue,
|
||||
EXTRAPOLATE_TYPE_EXTEND,
|
||||
EXTRAPOLATE_TYPE_EXTEND);
|
||||
|
||||
_outputValue = @(outputValue);
|
||||
_valueNode.value = outputValue;
|
||||
[_valueNode setNeedsUpdate];
|
||||
}
|
||||
|
||||
- (void)cleanupAnimationUpdate
|
||||
{
|
||||
[_valueNode cleanupAnimationUpdate];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user