• Overview
  • Guides
    • Looping
    • Easing and Interpolating
    • Layers
    • Groups
    • Using TypeScript


React Ensemble executes regions sequentially, meaning one region won't start until the one before it has finished. If we were to configure a region to start when another region was still running, TrackUtils.gen would throw an error.

Track Diagram

So what about if we want to have two regions overlap? For instance, what if we want regions one and two to start at the same time?

For executing regions concurrently, React Ensemble offers the concept of track layers. A layer is essentially a sub-track for regions to be placed in so they can run at the same time as other sub-tracks (layers).

Layer Diagram

Layers are executed independently of one another. Therefore, if two regions are put on separate layers, they will run at the same time.

Setting Layers

Set a region's layer by specifying a string as its layer property. This string is the layer's name. Any other regions within the track that have the same layer name will be put on the same layer.

If it's easier, you can use TrackUtils.layer to set one or more regions' layers. This function can take a string or a number as the layer name, which will be cast to a string.

Working in Multiple Layers

Since layers are independent of each other, it can be easier to visualize multiple layers by using the helper function TrackUtils.multi.

With multi, you can pass in layers as separate arrays or regions and they'll be converted into a regular track with layer names (based on each sub-track's index).

Alternatively, you can pass multi an object with each value being one or more regions. Layers will be assigned based on each key.

Keep in mind, multi is just nice syntax. You can use all the features of layering by configuring the right properties on your track regions. All multi does is add them for you.

For example, that last call to multi outputs this region, which is called a group:

Skip to the Groups guide to learn more about groups.

Layer Resolution

It's important to note that every layer is essentially its own animation, meaning each layer has a potential value for every state property at any given frame.

In other words, if your animation has state { x: number, y: string } and multiple layers, every layer will have its own value for x and y on each frame. Obviously, we can only draw one x to the screen, so how do we decide which layer's x to use?

To solve this problem, React Ensemble uses a layer resolver. This is a function that takes information about all the layers using a state property and decides which value is the right one to draw.

A Practical Example

Consider the following track:

This animation has two layers: 1 and 2. If x has a default value of 0, the following is true:

  • At time = 0, x is changed from 0 to 123 on layer 1
  • At time = 500, x is changed from 0 to 99 on layer 2

Since we have two layers, there are two possible x values we could draw at any frame of the animation. Let's consider some possible ways to resolve this.

First Option: Prioritize the first layer

With this resolver, we always choose the x value from the first layer. Our animation would look like this:

  • At time = 0, x is changed from 0 to 123
  • x remains 123 for the rest of the animation

The information from layer 2 is lost. This probably isn't the best option.

Second Option: Prioritize the last layer

If we always choose the x from the last layer instead, our animation would look like this:

  • x is 0 until time = 500
  • At time = 500, x is changed from 0 to 99
  • x remains 99 for the rest of the animation

Just like in the first option, we're losing the information from one of the layers.

Third Option: Choose the value that's changed most recently

With this resolver, we choose the x value that has changed most recently. Here's how that would look:

  • At time = 0, x is changed from 0 to 123
  • x is 123 until time = 500
  • At time = 500, x is changed from 123 to 99
  • x remains 99 for the rest of the animation

This is similar to how React Ensemble's default layer resolver works, as you'll see in the next section.

The Default Layer Resolver

React Ensemble's default layer resolver is overrideLast, accessible at TrackUtils.layerResolvers.overrideLast

As hinted by its name, the overrideLast resolver selects the value candidate with the lowest age (least amount of time since it was last updated).

If multiple candidates have the same age, the one with the highest layer rank will be used. Layer rank is calculated by alphanumerically sorting all layer names that exist in the track. In other words, if there's a tie, a layer named 10 will beat a layer named 9.

Writing a Resolver

You can override the layer resolver for an animation by setting the resolver prop in your Timeline.

A layer resolver must match the following signature:

stateKey is the name of the state property being evaluated, and layers contains information about the property's use in every layer.

For example, let's write a resolver that returns the sum of all instances of x across all layers.

Further Reading

Easing and Interpolating
Copyright © 2020 Joseph Cowman. All rights reserved.
React Ensemble is licensed under the MIT License.