From ae0d714bbdd2eb9d114c17c3945b2f678f60b65a 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 2dd19761764..e96cbd75c16 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 0e8e342da76..9726b919121 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); + }, + ); });