RCTAnimationUtils.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #import <React/RCTAnimationUtils.h>
  8. #import <React/RCTLog.h>
  9. static NSUInteger _RCTFindIndexOfNearestValue(CGFloat value, NSArray<NSNumber *> *range)
  10. {
  11. NSUInteger index;
  12. NSUInteger rangeCount = range.count;
  13. for (index = 1; index < rangeCount - 1; index++) {
  14. NSNumber *inputValue = range[index];
  15. if (inputValue.doubleValue >= value) {
  16. break;
  17. }
  18. }
  19. return index - 1;
  20. }
  21. /**
  22. * Interpolates value by remapping it linearly fromMin->fromMax to toMin->toMax
  23. */
  24. CGFloat RCTInterpolateValue(CGFloat value,
  25. CGFloat inputMin,
  26. CGFloat inputMax,
  27. CGFloat outputMin,
  28. CGFloat outputMax,
  29. NSString *extrapolateLeft,
  30. NSString *extrapolateRight)
  31. {
  32. if (value < inputMin) {
  33. if ([extrapolateLeft isEqualToString:EXTRAPOLATE_TYPE_IDENTITY]) {
  34. return value;
  35. } else if ([extrapolateLeft isEqualToString:EXTRAPOLATE_TYPE_CLAMP]) {
  36. value = inputMin;
  37. } else if ([extrapolateLeft isEqualToString:EXTRAPOLATE_TYPE_EXTEND]) {
  38. // noop
  39. } else {
  40. RCTLogError(@"Invalid extrapolation type %@ for left extrapolation", extrapolateLeft);
  41. }
  42. }
  43. if (value > inputMax) {
  44. if ([extrapolateRight isEqualToString:EXTRAPOLATE_TYPE_IDENTITY]) {
  45. return value;
  46. } else if ([extrapolateRight isEqualToString:EXTRAPOLATE_TYPE_CLAMP]) {
  47. value = inputMax;
  48. } else if ([extrapolateRight isEqualToString:EXTRAPOLATE_TYPE_EXTEND]) {
  49. // noop
  50. } else {
  51. RCTLogError(@"Invalid extrapolation type %@ for right extrapolation", extrapolateRight);
  52. }
  53. }
  54. return outputMin + (value - inputMin) * (outputMax - outputMin) / (inputMax - inputMin);
  55. }
  56. /**
  57. * Interpolates value by mapping it from the inputRange to the outputRange.
  58. */
  59. CGFloat RCTInterpolateValueInRange(CGFloat value,
  60. NSArray<NSNumber *> *inputRange,
  61. NSArray<NSNumber *> *outputRange,
  62. NSString *extrapolateLeft,
  63. NSString *extrapolateRight)
  64. {
  65. NSUInteger rangeIndex = _RCTFindIndexOfNearestValue(value, inputRange);
  66. CGFloat inputMin = inputRange[rangeIndex].doubleValue;
  67. CGFloat inputMax = inputRange[rangeIndex + 1].doubleValue;
  68. CGFloat outputMin = outputRange[rangeIndex].doubleValue;
  69. CGFloat outputMax = outputRange[rangeIndex + 1].doubleValue;
  70. return RCTInterpolateValue(value,
  71. inputMin,
  72. inputMax,
  73. outputMin,
  74. outputMax,
  75. extrapolateLeft,
  76. extrapolateRight);
  77. }
  78. CGFloat RCTRadiansToDegrees(CGFloat radians)
  79. {
  80. return radians * 180.0 / M_PI;
  81. }
  82. CGFloat RCTDegreesToRadians(CGFloat degrees)
  83. {
  84. return degrees / 180.0 * M_PI;
  85. }
  86. #if TARGET_IPHONE_SIMULATOR
  87. // Based on https://stackoverflow.com/a/13307674
  88. float UIAnimationDragCoefficient(void);
  89. #endif
  90. CGFloat RCTAnimationDragCoefficient()
  91. {
  92. #if TARGET_IPHONE_SIMULATOR
  93. if (NSClassFromString(@"XCTest") != nil) {
  94. // UIAnimationDragCoefficient is 10.0 in tests for some reason, but
  95. // we need it to be 1.0. Fixes T34233294
  96. return 1.0;
  97. } else {
  98. return (CGFloat)UIAnimationDragCoefficient();
  99. }
  100. #else
  101. return 1.0;
  102. #endif
  103. }