Permalink
Browse files

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 #9625

Differential Revision: D4053231

fbshipit-source-id: 29048de444ff5f6d7fe7dce7897399b483ee6d2d
  • Loading branch information...
ryangomba authored and Facebook Github Bot committed Oct 20, 2016
1 parent 518915a commit 5794ff61bc205300f634674d8679281a4cba7fb3
@@ -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',
})
}
],
@@ -118,14 +118,23 @@ - (void)stepAnimation
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];
@@ -15,6 +15,8 @@ @implementation RCTInterpolationAnimatedNode
__weak RCTValueAnimatedNode *_parentNode;
NSArray<NSNumber *> *_inputRange;
NSArray<NSNumber *> *_outputRange;
+ NSString *_extrapolateLeft;
+ NSString *_extrapolateRight;
}
- (instancetype)initWithTag:(NSNumber *)tag
@@ -29,6 +31,8 @@ - (instancetype)initWithTag:(NSNumber *)tag
}
}
_outputRange = [outputRange copy];
+ _extrapolateLeft = config[@"extrapolateLeft"];
+ _extrapolateRight = config[@"extrapolateRight"];
}
return self;
}
@@ -70,19 +74,20 @@ - (void)performUpdate
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
@@ -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);
@@ -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)

0 comments on commit 5794ff6

Please sign in to comment.