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:
parent
518915a750
commit
5794ff61bc
|
@ -320,7 +320,7 @@ exports.examples = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Scale interpolation',
|
title: 'Scale interpolation with clamping',
|
||||||
description: 'description',
|
description: 'description',
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
|
@ -335,8 +335,9 @@ exports.examples = [
|
||||||
transform: [
|
transform: [
|
||||||
{
|
{
|
||||||
scale: anim.interpolate({
|
scale: anim.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 0.5],
|
||||||
outputRange: [1, 1.4],
|
outputRange: [1, 1.4],
|
||||||
|
extrapolateRight: 'clamp',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -118,14 +118,23 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||||
fromInterval,
|
fromInterval,
|
||||||
toInterval,
|
toInterval,
|
||||||
fromFrameValue.doubleValue,
|
fromFrameValue.doubleValue,
|
||||||
toFrameValue.doubleValue);
|
toFrameValue.doubleValue,
|
||||||
|
EXTRAPOLATE_TYPE_EXTEND,
|
||||||
|
EXTRAPOLATE_TYPE_EXTEND);
|
||||||
|
|
||||||
[self updateOutputWithFrameOutput:frameOutput];
|
[self updateOutputWithFrameOutput:frameOutput];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateOutputWithFrameOutput:(CGFloat)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);
|
_outputValue = @(outputValue);
|
||||||
_valueNode.value = outputValue;
|
_valueNode.value = outputValue;
|
||||||
[_valueNode setNeedsUpdate];
|
[_valueNode setNeedsUpdate];
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
__weak RCTValueAnimatedNode *_parentNode;
|
__weak RCTValueAnimatedNode *_parentNode;
|
||||||
NSArray<NSNumber *> *_inputRange;
|
NSArray<NSNumber *> *_inputRange;
|
||||||
NSArray<NSNumber *> *_outputRange;
|
NSArray<NSNumber *> *_outputRange;
|
||||||
|
NSString *_extrapolateLeft;
|
||||||
|
NSString *_extrapolateRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithTag:(NSNumber *)tag
|
- (instancetype)initWithTag:(NSNumber *)tag
|
||||||
|
@ -29,6 +31,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_outputRange = [outputRange copy];
|
_outputRange = [outputRange copy];
|
||||||
|
_extrapolateLeft = config[@"extrapolateLeft"];
|
||||||
|
_extrapolateRight = config[@"extrapolateRight"];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -70,19 +74,20 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSUInteger rangeIndex = [self findIndexOfNearestValue:_parentNode.value
|
CGFloat inputValue = _parentNode.value;
|
||||||
inRange:_inputRange];
|
NSUInteger rangeIndex = [self findIndexOfNearestValue:inputValue inRange:_inputRange];
|
||||||
NSNumber *inputMin = _inputRange[rangeIndex];
|
NSNumber *inputMin = _inputRange[rangeIndex];
|
||||||
NSNumber *inputMax = _inputRange[rangeIndex + 1];
|
NSNumber *inputMax = _inputRange[rangeIndex + 1];
|
||||||
NSNumber *outputMin = _outputRange[rangeIndex];
|
NSNumber *outputMin = _outputRange[rangeIndex];
|
||||||
NSNumber *outputMax = _outputRange[rangeIndex + 1];
|
NSNumber *outputMax = _outputRange[rangeIndex + 1];
|
||||||
|
|
||||||
CGFloat outputValue = RCTInterpolateValue(_parentNode.value,
|
self.value = RCTInterpolateValue(inputValue,
|
||||||
inputMin.doubleValue,
|
inputMin.doubleValue,
|
||||||
inputMax.doubleValue,
|
inputMax.doubleValue,
|
||||||
outputMin.doubleValue,
|
outputMin.doubleValue,
|
||||||
outputMax.doubleValue);
|
outputMax.doubleValue,
|
||||||
self.value = outputValue;
|
_extrapolateLeft,
|
||||||
|
_extrapolateRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -12,11 +12,17 @@
|
||||||
|
|
||||||
#import "RCTDefines.h"
|
#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,
|
RCT_EXTERN CGFloat RCTInterpolateValue(CGFloat value,
|
||||||
CGFloat fromMin,
|
CGFloat inputMin,
|
||||||
CGFloat fromMax,
|
CGFloat inputMax,
|
||||||
CGFloat toMin,
|
CGFloat outputMin,
|
||||||
CGFloat toMax);
|
CGFloat outputMax,
|
||||||
|
NSString *extrapolateLeft,
|
||||||
|
NSString *extrapolateRight);
|
||||||
|
|
||||||
RCT_EXTERN CGFloat RCTRadiansToDegrees(CGFloat radians);
|
RCT_EXTERN CGFloat RCTRadiansToDegrees(CGFloat radians);
|
||||||
RCT_EXTERN CGFloat RCTDegreesToRadians(CGFloat degrees);
|
RCT_EXTERN CGFloat RCTDegreesToRadians(CGFloat degrees);
|
||||||
|
|
|
@ -9,16 +9,44 @@
|
||||||
|
|
||||||
#import "RCTAnimationUtils.h"
|
#import "RCTAnimationUtils.h"
|
||||||
|
|
||||||
|
#import "RCTLog.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interpolates value by remapping it linearly fromMin->fromMax to toMin->toMax
|
* Interpolates value by remapping it linearly fromMin->fromMax to toMin->toMax
|
||||||
*/
|
*/
|
||||||
CGFloat RCTInterpolateValue(CGFloat value,
|
CGFloat RCTInterpolateValue(CGFloat value,
|
||||||
CGFloat fromMin,
|
CGFloat inputMin,
|
||||||
CGFloat fromMax,
|
CGFloat inputMax,
|
||||||
CGFloat toMin,
|
CGFloat outputMin,
|
||||||
CGFloat toMax)
|
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)
|
CGFloat RCTRadiansToDegrees(CGFloat radians)
|
||||||
|
|
Loading…
Reference in New Issue