Lock an Animation within the Screen Dimensions in React Native

In this lesson we'll use Animated.ValueXY and Dimensions to create an animated element that cannot be animated outside of the screen dimensions. It takes advantage of the extrapolate: "clamp" feature of interpolate.

Code

You must be a Member to view code

Transcript

Instructor: 00:00 In order to clamp an animation of an element within the screen dimensions, we're going to need the screen dimensions. We're going to import dimensions from React Native. Then we're going to destructure width and height from Dimensions.get('window').

00:15 The next thing we're going to need to do is set up an animation. In our componentWillMount, we'll say this.animation = new Animated.ValueXY(). Then we'll set up a slightly contrived animation in our componentDidMount. We'll animate to two times the height and the width of our screen. We're going to say Animated.parallel. That takes an array.

00:46 We'll do Animated.timing(this.animation.x) -- because we want to animate them separately to the different width and heights -- toValue of width*2 for a duration of 500 milliseconds. We'll additionally do that for the y property of our animation, but instead of width we'll do the height.

01:11 Now that we have our contrived example in place, let's set up our style. We're going to say const moveStyle is equal to an object with a transform. The transform takes an array of transforms, so we'll say translateX = this.animation.x and translateY = this.animation.y.

01:36 Then we'll apply this moveStyle to our Animated.View and call start on our componentDidMount animation so that when it refreshes we can see that it zooms off the screen. Let's remove this, because we want to see our box.

01:58 In order to make it stay on the screen and within the bounds of the screen, we're going to need to use interpolation. We're going to set up input ranges because we're going to use the inputRange and the outputRange that are exactly the same. Say const widthRange = 0which would be this x corner, and the width of the screen minus the box dimensions.

02:26 We currently have a defined box of 50x50, but you could calculate the element that you're using and do the subtraction yourself for a dynamically sized element. We'll also set up the height range -- and that will also be zero, which will be up here -- and then the height of the screen minus the box dimensions as well.

02:52 Now, with these in place, we can go ahead and set up our interpolations. We'll say const xAnimation = this.animation.x.interpolate. Our inputRange will be width range. Our outputRange will be exactly the same as the input.

03:11 It's a one-to-one mapping, but we can use extrapolate: 'clamp' to clamp both sides. Regardless of what the inputRange is coming from the top, if it goes beyond the width of our screen, it will always be clamped to the width of the screen minus the box dimensions.

03:30 Now we can go ahead and set that up for our y side as well. We'll say yAnimation for the y bit here and swap this out with -- fix that spelling -- height range. Then we need to replace the animations with our interpolated animations, so we'll say xAnimation and yAnimation.

03:58 Now, if we go ahead and restart our animation, we can see that it'll fly across the screen, but it will never go beyond the bounds of the screen.