From ae0ad1fc7e8d7a591b5b1c0789c39bdcdfd3f388 Mon Sep 17 00:00:00 2001 From: Zack Date: Thu, 25 Feb 2016 17:18:27 -0800 Subject: [PATCH] Implement modulo operator method Summary:This is an initial take on how to allow for value wrapping in Animated (currently `.timing` only). It adds a wrap config options which is an array specifying a range of values to be wrapped around. Anytime the delta of `toValue and fromValue > wrapDistance / 2` instead of animating the long way it will animate towards the range extremity and then after breaching the range it will readjust to animated to the true toValue. Example Usage: ```js Animated.timing( this.state.animatedDegrees, {toValue: Math.random()*360, wrap: [0, 360]} ).start() ``` This is presumably very valuable in rotation based animations, but could also be useful in other applications like wrapping the edges of the viewport. Questions & Todo: - Is `wrap` as a config key semantically meaningful and accurate? - Is there a way to expose this as a config option on `.interpolate` rather than timing - Generalize to all animated API's (spring, decay), and will this work with ValueXY out of the box? - Add tests Closes https://github.com/facebook/react-native/pull/5743 Differential Revision: D2979992 fb-gh-sync-id: 69be510feba8c43acb10c253036f5854adff9258 shipit-source-id: 69be510feba8c43acb10c253036f5854adff9258 --- .../Animated/src/AnimatedImplementation.js | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Libraries/Animated/src/AnimatedImplementation.js b/Libraries/Animated/src/AnimatedImplementation.js index 830ab929d..4c7a85a4d 100644 --- a/Libraries/Animated/src/AnimatedImplementation.js +++ b/Libraries/Animated/src/AnimatedImplementation.js @@ -898,6 +898,33 @@ class AnimatedMultiplication extends AnimatedWithChildren { } } +class AnimatedModulo extends AnimatedWithChildren { + _a: Animated; + _modulus: number; + + constructor(a: Animated, modulus: number) { + super(); + this._a = a; + this._modulus = modulus; + } + + __getValue(): number { + return (this._a.__getValue() % this._modulus + this._modulus) % this._modulus; + } + + interpolate(config: InterpolationConfigType): AnimatedInterpolation { + return new AnimatedInterpolation(this, Interpolation.create(config)); + } + + __attach(): void { + this._a.__addChild(this); + } + + __detach(): void { + this._a.__removeChild(this); + } +} + class AnimatedTransform extends AnimatedWithChildren { _transforms: Array; @@ -1233,6 +1260,14 @@ var multiply = function( return new AnimatedMultiplication(a, b); }; +var modulo = function( + a: Animated, + modulus: number +): AnimatedModulo { + return new AnimatedModulo(a, modulus); +}; + + var maybeVectorAnim = function( value: AnimatedValue | AnimatedValueXY, config: Object, @@ -1604,6 +1639,12 @@ module.exports = { */ multiply, + /** + * Creates a new Animated value that is the (non-negative) modulo of the + * provided Animated value + */ + modulo, + /** * Starts an animation after the given delay. */