Add support for clamping for NativeAnimated on iOS

Summary:
This diff adds support for clamping on iOS. It separates out code originally submitted in #9048.

Test plan (required)

Run UIExplorer NativeAnimated examples before and after - compare the results. Pay special attention to the new clamped spring example.
Closes https://github.com/facebook/react-native/pull/9625

Differential Revision: D4053231

fbshipit-source-id: 29048de444ff5f6d7fe7dce7897399b483ee6d2d
This commit is contained in:
Ryan Gomba 2016-10-20 14:12:37 -07:00 committed by Facebook Github Bot
parent 518915a750
commit 5794ff61bc
5 changed files with 70 additions and 21 deletions

View File

@ -320,7 +320,7 @@ exports.examples = [
},
},
{
title: 'Scale interpolation',
title: 'Scale interpolation with clamping',
description: 'description',
render: function() {
return (
@ -335,8 +335,9 @@ exports.examples = [
transform: [
{
scale: anim.interpolate({
inputRange: [0, 1],
inputRange: [0, 0.5],
outputRange: [1, 1.4],
extrapolateRight: 'clamp',
})
}
],

View File

@ -118,14 +118,23 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
fromInterval,
toInterval,
fromFrameValue.doubleValue,
toFrameValue.doubleValue);
toFrameValue.doubleValue,
EXTRAPOLATE_TYPE_EXTEND,
EXTRAPOLATE_TYPE_EXTEND);
[self updateOutputWithFrameOutput:frameOutput];
}
- (void)updateOutputWithFrameOutput:(CGFloat)frameOutput
{
CGFloat outputValue = RCTInterpolateValue(frameOutput, 0, 1, _fromValue, _toValue);
CGFloat outputValue = RCTInterpolateValue(frameOutput,
0,
1,
_fromValue,
_toValue,
EXTRAPOLATE_TYPE_EXTEND,
EXTRAPOLATE_TYPE_EXTEND);
_outputValue = @(outputValue);
_valueNode.value = outputValue;
[_valueNode setNeedsUpdate];

View File

@ -15,6 +15,8 @@
__weak RCTValueAnimatedNode *_parentNode;
NSArray<NSNumber *> *_inputRange;
NSArray<NSNumber *> *_outputRange;
NSString *_extrapolateLeft;
NSString *_extrapolateRight;
}
- (instancetype)initWithTag:(NSNumber *)tag
@ -29,6 +31,8 @@
}
}
_outputRange = [outputRange copy];
_extrapolateLeft = config[@"extrapolateLeft"];
_extrapolateRight = config[@"extrapolateRight"];
}
return self;
}
@ -70,19 +74,20 @@
return;
}
NSUInteger rangeIndex = [self findIndexOfNearestValue:_parentNode.value
inRange:_inputRange];
CGFloat inputValue = _parentNode.value;
NSUInteger rangeIndex = [self findIndexOfNearestValue:inputValue inRange:_inputRange];
NSNumber *inputMin = _inputRange[rangeIndex];
NSNumber *inputMax = _inputRange[rangeIndex + 1];
NSNumber *outputMin = _outputRange[rangeIndex];
NSNumber *outputMax = _outputRange[rangeIndex + 1];
CGFloat outputValue = RCTInterpolateValue(_parentNode.value,
inputMin.doubleValue,
inputMax.doubleValue,
outputMin.doubleValue,
outputMax.doubleValue);
self.value = outputValue;
self.value = RCTInterpolateValue(inputValue,
inputMin.doubleValue,
inputMax.doubleValue,
outputMin.doubleValue,
outputMax.doubleValue,
_extrapolateLeft,
_extrapolateRight);
}
@end

View File

@ -12,11 +12,17 @@
#import "RCTDefines.h"
static NSString * const EXTRAPOLATE_TYPE_IDENTITY = @"identity";
static NSString * const EXTRAPOLATE_TYPE_CLAMP = @"clamp";
static NSString * const EXTRAPOLATE_TYPE_EXTEND = @"extend";
RCT_EXTERN CGFloat RCTInterpolateValue(CGFloat value,
CGFloat fromMin,
CGFloat fromMax,
CGFloat toMin,
CGFloat toMax);
CGFloat inputMin,
CGFloat inputMax,
CGFloat outputMin,
CGFloat outputMax,
NSString *extrapolateLeft,
NSString *extrapolateRight);
RCT_EXTERN CGFloat RCTRadiansToDegrees(CGFloat radians);
RCT_EXTERN CGFloat RCTDegreesToRadians(CGFloat degrees);

View File

@ -9,16 +9,44 @@
#import "RCTAnimationUtils.h"
#import "RCTLog.h"
/**
* Interpolates value by remapping it linearly fromMin->fromMax to toMin->toMax
*/
CGFloat RCTInterpolateValue(CGFloat value,
CGFloat fromMin,
CGFloat fromMax,
CGFloat toMin,
CGFloat toMax)
CGFloat inputMin,
CGFloat inputMax,
CGFloat outputMin,
CGFloat outputMax,
NSString *extrapolateLeft,
NSString *extrapolateRight)
{
return toMin + (value - fromMin) * (toMax - toMin) / (fromMax - fromMin);
if (value < inputMin) {
if ([extrapolateLeft isEqualToString:EXTRAPOLATE_TYPE_IDENTITY]) {
return value;
} else if ([extrapolateLeft isEqualToString:EXTRAPOLATE_TYPE_CLAMP]) {
value = inputMin;
} else if ([extrapolateLeft isEqualToString:EXTRAPOLATE_TYPE_EXTEND]) {
// noop
} else {
RCTLogError(@"Invalid extrapolation type %@ for left extrapolation", extrapolateLeft);
}
}
if (value > inputMax) {
if ([extrapolateRight isEqualToString:EXTRAPOLATE_TYPE_IDENTITY]) {
return value;
} else if ([extrapolateRight isEqualToString:EXTRAPOLATE_TYPE_CLAMP]) {
value = inputMax;
} else if ([extrapolateRight isEqualToString:EXTRAPOLATE_TYPE_EXTEND]) {
// noop
} else {
RCTLogError(@"Invalid extrapolation type %@ for right extrapolation", extrapolateRight);
}
}
return outputMin + (value - inputMin) * (outputMax - outputMin) / (inputMax - inputMin);
}
CGFloat RCTRadiansToDegrees(CGFloat radians)