Exploring Easing Gradients in React Native

Tanner West
React Native Rocket
4 min readJul 26, 2022
Photo by Sergey Pesterev on Unsplash

A few weeks ago, I was experimenting with using gradients to animate skeleton placeholders with Moti, and I noticed that many of the basic gradients I tried had discernible edges that kept them from blending well with their background component. I started doing a little research on how to create smooth gradients and I came across Andreas Larsen’s article Easing Linear Gradients.

In the article, Larsen explains how you can take the principle of easing, which you are likely familiar with if you’ve ever worked with animations, and apply it to creating gradients. The same way we use easing curves to make animations appear more “natural,” we can apply them to our gradients to create smooth transitions between colors.

To help web engineers create eased gradients, Larsen wrote a PostCSS plugin that lets you pass in cubic bezier coordinates to generate a gradient based on that curve. I really wanted to see eased gradients in action in React Native, and since we can’t use PostCSS in RN, I dug in to the source code for Larsen’s plugin to see if I could port at least part of its functionality to a React Native project.

Understanding the Basics

At the heart of his plugin is another one of Larsen’s libraries, Easing Coordinates. It contains the math functions that translate cubic bezier coordinates to sets of XY coordinates. It becomes much easier to understand what these functions do if you can visualize it, so check out this Codepen that uses some of Larsen’s code to generate coordinates, then shows them as an SVG curve with the help of D3.

If you’re familiar with easing curves, you’ll recognize this as a basic ease-in curve. If you explore the JavaScript for this example, you’ll see that the first four functions are taken directly from Larsen’s library. cubicCoordinates takes five arguments: the four points of our cubic bezier curve and an optional polySteps . The latter defines how many pairs of coordinates the function will generate.

The data that’s actually generated by this function looks like this. The curve you see is simply a graph of these coordinates.

The above example shows that Larsen’s code gives us accurate easing curve coordinates for a given sets of bezier points, but how do we actually use these coordinates to generate gradients? That’s what we’ll cover in the next section.

From graph coordinates to gradients

If you’ve worked with SVG gradients before, this next example should be very familiar. We provide a number of <Stop> elements to define where our gradient’s colors will start and end.

Typically, as in the example above, we write this manually because we just need our gradient to have two or three stops, but now we can use our bezier coordinate data to define these programmatically.

Since we used D3 in our last example, we use it again here to append our stops to our SVG linear gradient. We use a forEach loop that appends a new Stop for each of our coordinate pairs. The x coordinates will determine the stop offset, while we’ll use the y coordinates to set our color value.

We can get much more fancy with colors when we start using React Native, but for now we’ll map our y value to a number between 0 and 255, and use that number for all three parameters of an RGB value. This will result in an increasingly lighter gray color for each stop. This all might seem confusing at first, so here’s what the markup for the resulting gradient will look like.

Bringing it all to React Native

Now that we understand the fundamentals behind our eased gradient technique, we can bring what we’ve learned to React Native. I’ve built a playground app for exploring what different cubic bezier easings look like. The easing curve data for this app is taken directly from easings.net.

The app uses essentially the same techniques as the examples above. The coordinate data is generated by code from Larsen’s library. We map over the coordinates to generate our SVG stops, using x for our offset and y for our color values.

If you were able to follow along with the examples from above, this app should pretty self explanatory. The only concept we haven’t covered yet is the interpolation of colors. I’ve provided two text inputs where you can enter stop colors. Using the interpolation function from Reanimated, the app will map those colors to the y value of the selected bezier curve. The result is a smooth transition between those two colors across the stops!

Conclusion

It’s very satisfying to have eased gradients as another tool in my app building toolbox. Familiarizing myself with the idea has also helped me better understand concepts like SVG gradients and bezier curves, and I hope it’s helped you in a similar way!

As always, questions, comments, and corrections are welcome on Twitter @useRNRocket. Follow me here on Medium and on Twitter for more React Native content!

--

--