From 981a0a08deafbe4202aa0e38474fc75519586c7f Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 27 Mar 2023 12:38:16 -0700 Subject: [PATCH] Fix normalization of degrees in AnimatedInterpolation (#36645) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36645 This broke while changing the AnimatedInterpolation back in D40571873 and D40632443, as I assumed the native side would be able to correctly handle values such as '1rad'. However these were being sent over as strings, and were thus using the string interpolation path, which does not work here. Instead, handle both `deg` and `rad` explicitly when generating the config in JS. Resolves issue https://github.com/facebook/react-native/issues/36608 Changelog: [General][Fixed] Resolves Animated.Value.interpolate results in NaN when output is in radians Reviewed By: yungsters Differential Revision: D44406034 fbshipit-source-id: fe0f3df16f2b8ec6c31f9359e4706cacc72b9951 --- .../Libraries/Animated/NativeAnimatedHelper.js | 9 ++++++--- .../Animated/__tests__/Interpolation-test.js | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js b/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js index 2dd197617641be..e96cbd75c16e7e 100644 --- a/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js +++ b/packages/react-native/Libraries/Animated/NativeAnimatedHelper.js @@ -562,10 +562,13 @@ function transformDataType(value: number | string): number | string { if (typeof value !== 'string') { return value; } - if (/deg$/.test(value)) { + + // Normalize degrees and radians to a number expressed in radians + if (value.endsWith('deg')) { const degrees = parseFloat(value) || 0; - const radians = (degrees * Math.PI) / 180.0; - return radians; + return (degrees * Math.PI) / 180.0; + } else if (value.endsWith('rad')) { + return parseFloat(value) || 0; } else { return value; } diff --git a/packages/react-native/Libraries/Animated/__tests__/Interpolation-test.js b/packages/react-native/Libraries/Animated/__tests__/Interpolation-test.js index 0e8e342da760ea..9726b919121898 100644 --- a/packages/react-native/Libraries/Animated/__tests__/Interpolation-test.js +++ b/packages/react-native/Libraries/Animated/__tests__/Interpolation-test.js @@ -349,4 +349,20 @@ describe('Interpolation', () => { expect(interpolation(1e-12)).toBe('rgba(0, 0, 0, 0)'); expect(interpolation(2 / 3)).toBe('rgba(0, 0, 0, 0.667)'); }); + + it.each([ + ['radians', ['1rad', '2rad'], [1, 2]], + ['degrees', ['90deg', '180deg'], [Math.PI / 2, Math.PI]], + ['numbers', [1024, Math.PI], [1024, Math.PI]], + ['unknown', ['5foo', '10foo'], ['5foo', '10foo']], + ])( + 'should convert %s to numbers in the native config', + (_, outputRange, expected) => { + const config = new AnimatedInterpolation( + {}, + {inputRange: [0, 1], outputRange}, + ).__getNativeConfig(); + expect(config.outputRange).toEqual(expected); + }, + ); });