Some Easy Workflow Tips to Keep Bodymovin JSON Sizes Down and Performance Up

Aaron Schurman
15 min readMay 4, 2020

--

When working within the UI Motion Design space, finding the time, budget and desire to focus design hours on delight is just the first hurdle to get over. Setting up workflows and learning new techniques can be a time consuming process that some tight-budget projects can not afford. In this article, I will take you through some powerful workflow efficiencies that will help you get smaller JSONs on export and overcome possible performance bumps.

Cleaning Up Your Shape Layers and Organizing Their Content

When importing complex illustrated elements into After Effects, through either Overlord or direct import and conversion of an Illustrator document, you will end up with either a very large number of Shape Layers in your comp or one Shape Layer with an unmanageable amount of sublayers in its ‘Contents’ section. If these layers are left as they are you will have major workflow issues that will slow down the animation process as well as add unnecessary data to your final JSON output. Although it will add production time on to the front end of the animation process, properly organizing all the layers and removing as many ‘Groups’, ‘Fill’, ‘Stroke’, ‘Merge Path’ parameters that are part of the sublayers by default will save you valuable time during the animation phase as well as allow you to navigate the file more easily. The JSONs that are exported from Bodymovin will include data for all these layer and parameter references, and they can really add up over time when working with complicated compositions. Let’s use Hunter as our example:

The difference between file organization from when Hunter was imported into After Effects to when I started animating looked something like this:

From the image you can see a few things. First, I named every layer and its sublayers. Seems obvious, but this step is something some animators tend to cut out to save time. Best practices are to name as much as you can so that you don’t waste time being lost in your own file, especially when working with this many layers.

Second, I try to group items based around how I imagine I am going to animate them. Grouping together things like ‘Helmet’, ‘Ear lines’, ‘Snout’ under one layer named ‘Head’ allows me to change the anchor point, adjust the position/rotation/etc of the layer and, in doing so, all the sublayers will be included with the parent transforms. More importantly, this kind of grouping allows me to use the keyframing parameters within the base ‘Transform’ properties of a layer, instead of the ‘Transform’ properties of a shape sublayer, which have more powerful tools for editing curves as well as the ability to separate the X and Y dimensions in position. This is animation 101; nothing new here. However, with Bodymovin, all the layers and all their parameters are saved within the JSON, so if you use layer names that are too long, that’s going to affect the data size of your export. If you don’t group objects and have a large number of ‘Fill 1’ or ‘Stroke 1’ parameters, it will affect the data size of your export. To compensate for this, grouping together elements so that they share these common fills or strokes can save a lot of data size in the final JSON. In the picture below, you will notice I have 3 paths under ‘Head stripes’ sharing the same ‘Stroke 1’ and ‘Fill 1’.

By doing that, I have cut out 2 references to a ‘Stroke 1’, 2 references to a ‘Fill 1’, and all the extra data that may be used in defining those in a JSON. Doesn’t seem like that much data, but if you have an animation that has 150 layers, it can add up really fast.

TL;DR – More layers with redundant parameters like ‘Fill 1’ or excessively long layer names will cause your JSON to bloat on export and taking the time to organize and name all the layers will help you alleviate much of the unnecessary data clutter that leads to bigger files.

Deleting Hidden Layers and Shapes

When working with Bodymovin in the early days, it had a bad habit of including data from hidden layers or hidden sublayers during the export phase and creation of the JSON. Since then, Bodymovin has been updated to ignore hidden layers unless specified in the settings icon within the Bodymovin export window. If you have quite a few hidden layers or hidden sublayers it would be worth checking to make sure all that extra data isn’t affecting the final output, just for your own peace of mind. As of now, this should no longer be an issue for final exports.

More Points in Your Paths, More Data in Your JSON

When working with complicated Illustrations, it’s best to understand how Bodymovin translates those shapes into data. In order to draw a vector shape, it plots a series of points on a grid in code and uses arcs, lines and shapes defined in code to make up the illustration. All of this is then finished off with code that defines the fills and strokes of the different pieces. If each point, each arc, each line is defined by bits of code, it stands to reason that the more of them you have in an illustration, the bigger the JSON file is going to be. Much of the illustration style in YouTube Kids has had some organic influence to keep the characters from feeling too stiff or too perfect. Kids are messy, so our characters who interact with them should reflect a bit of that authentic rawness. In our initial approach to illustration, our style was skewed much more organic and loose. Because of that, there were a lot of points making up each piece, which is fine if the final asset is displayed as PNGs. In order for these illustrations to be animated, they needed to be cleaned up considerably, and the amount of points being plotted was greatly reduced. By looking at the image below, you can see that many of the lines were converted to strokes from fills and simplified. The arms and legs were also converted to strokes instead of filled paths to make the animation of those pieces easier as well as reducing the amount of keyframe data that would be used in animating those parts.

More Keyframes in Your Timeline, More Data in Your JSON

This one should be obvious, but needs to be at least mentioned. For every keyframe that is used on a layer, data is generated. When animating, the larger amount of keyframes you use will directly translate to a larger JSON export. This is really important to understand because if you are animating a large amount of properties and some of your keyframes are on parameters that haven’t changed, then those keyframes are useless data that’s bloating the final JSON. Shown in the image below, the best practice is to delete the excess keyframes that aren’t animating so that they won’t be compiled into the final export.

Deleting Unused Keyframes on Trimmed Layers

One small optimization that hasn’t been built into Bodymovin yet is the discarding of excess keyframes that reside outside of a trimmed layer. For example, say you have a layer with very complex keyframing and you have duplicated that layer 5 times and trimmed it at different places so that you could change it’s Z position alternating above and below another layer throughout the composition, when you go to render out the final JSON you will realize that the file is now significantly larger than it should be for how the animation is set up. The reason for this is that instead of ignoring the keyframes that sit outside of the start and end point for a layer, Bodymovin exports all of them. So instead of splitting your animation data across 5 different layers, you’ve just duplicated that complex info 5 times. Best way to deal with correcting this is by deleting all the keyframes in a layer that have no impact leading into, during, or leading out of the layer. In the image below, I have shown how you would go about cleaning up your layers in order to keep excess data and bloat out of the final JSON. Notice that you can’t just get rid of any keyframe data that exists outside of the layer bounds because your keyframes probably won’t be perfectly aligned with your trim. You want to make sure that the keyframes you are deleting will have no impact on the layer you are cleaning up.

While in the process of creating animations like this, it’s always best to have one untouched layer hidden away in case you split the layers and delete the wrong keyframes and loose precious animation time.

Animation of Procedural Parameters vs Path Points

Bit of a tongue twister, but another important aspect of how Bodymovin JSONs can get bloated is shown through how it exports different keyframe data, or more so, how After Effects displays data in keyframes differently. If you animate a layer with the core level procedural transform properties like position, rotation, scale, opacity, etc. you are using a fairly small amount of data. Position has a data point for X and Y, Scale has a data point for width and height and so on. When exporting this data to JSON it takes up a small amount of file size, but as mentioned above, if you export loads of these for a 60fps workflow, it can add up. Compare this to a workflow where you are animating a lot of paths in the shape layers. The paths that make up all the shape layers contain any number of points and each of those points are represented by a piece of data plotting it’s location on a grid. If you animate an illustration‘s path data, you will see a steep rise in how big the final JSON will be because you are not just animating a small set of data like X and Y of position of a layer, but you are animating the X and Y position of every point you are changing in that path as well as the position of each bezier handle that is attached to every point in that path. If your paths in an illustration add up to 500 points total and you animate all those points, that’s as much X and Y position data as if you were changing the position of 500 layers, throw in all the data representing the bezier handles of the path and it’s quite a bit more. This kind of animation is all doable, but it incurs a cost and is good to be aware of.

Track Mattes and Their Caveats

One of the coolest features in After Effects has always been track mattes. Being able to animate a mask as well as animate the content underneath is such a fun tool and can often make for some really unique effects and animations. Initially Bodymovin and Lottie didn’t support track mattes very well and caused a lot of performance issues on Android especially. Good news is that the support for track mattes are much better with the evolution of these tools with support for alpha mattes and inverted alpha mattes, but there are still some drawbacks to using them. Because all assets need to be rasterized during the playback rendering process, Lottie will be building the track mattes as raster assets to composite back into the composition with implementation costing some performance. If you can make it work for your animation, there can be a lower impact on performance if you use a layer mask instead of a track matte because animating the points of a mask cost less than if Lottie has to render an entire layer. But if you need to use a track matte it should work in most scenarios, with some caveats to be aware of.

First, because of the way the track mattes are rendered and composited back into the animation, comp size won’t have an impact on final performance. When the track matte is rendered offscreen, it is scaled up or down to the screen size before being used, so there will be heavier processing power needed when rendering to something like an iPad Pro vs an older phone because of the difference in screen resolutions. Where performance starts to be a concern is around the surface area of the mask and the complexities of the intersections that need to be rendered. Since the track matte is being rendered to an offscreen buffer it will be more processing intensive to render and composite a matte that covers 75% of the composition versus a smaller matte that only covers 15%. You may also see better performance, depending on the complexity of the assets, when using 2 or 3 smaller track mattes versus one big track matte. Using a bitmap as a track matte is also supported and may even provide a bit of a performance bump if you are using a very complex asset as a matte, but if you are using a shape layer as a matte and it’s fairly low in complexity it will process faster than the bitmap.

Another performance issue to be aware of is the complexity of intersections between the track mattes and other assets. You will find that if you use a track matte on a very complicated precomp with numerous layers it’s going to be much more of a performance hit when processing and applying the matte during playback. Also, if you apply track mattes to precomps containing track mattes you are multiplying the processing needed because Lottie may have to render both mattes at the same time. One way to avoid performance issues in these situations is to be wary of how much you are animating the track mattes themselves. The more a track matte changes from frame to frame, the more chances there are it will need to be reprocessed and re-rendered.

Inverted mattes can be another source to keep in mind while trying to optimize a workflow that uses track mattes. When Lottie renders the mattes during playback and applies them as masks, there is an extra step of inverting the colors that has to be done before the layer can be composited back into the animation. The performance hit may not be great, but it’s worth keeping in mind when building your animation.

Lastly, there should be some considerations around file cleanup when using track mattes, specifically around accidentally using fill modes on a track matte layer. During the animation process, if you had a layer with a ‘Gradient Fill’ on it and you duplicated it to create a track matte layer but you forgot to delete the ‘Gradient Fill’ it would still be processed as though it was visible, even though only the alpha data of that layer is being utilized. It seems like a small oversight, but can add up over time if not managed.

Using track mattes wisely can really work to your benefit and make some cool animated experiences as long as you understand the constraints and boundaries that will provide a smooth interactive experience.

TL;DR – Track mattes will give you performance hits from large surface areas, being rendered to devices with larger pixel density, using really complicated layers for masking, compounding the amount of masking going on in a composition, using inverted alpha mattes, animating the matte layers a lot and not cleaning up your files leaving behind data like ‘Gradient Fill’ layer effects on matte layers that are only being used for alpha data.

The Problems of Merge Paths and How to Get Around Them

As of now, the Merge Paths effect within Shape Layers in After Effects has basic support through Bodymovin and Lottie. Unfortunately, Merge Paths is an extremely important part of a lot of workflows using vector assets. You need Merge Paths to cut the center out of the letter ‘O’ so that you can see through the center of the letter when it’s placed on top of other elements, colors or backgrounds. Luckily, there are some tricks to use within After Effects that will give exported JSONs similar functionality and allow you to get around having to bank on Merge Paths.

If the object needing to be animated is a mono-stroke, one easy option is to just use one path with a high stroke width setting instead of two paths using Merge Paths. This works well on things like the letter ‘O’ mentioned above or if needing to animate a ring of some sort. If you need to animate the two rings independent of each other, you can animate the scale of the path while animating the stroke width of the path to simulate two independent paths that are animating separately. Bonus of this approach is that the vector asset is built using half the points and is easier to animate.

Another approach is if you need to work with a varied stroke you can layer multiple paths on top of each other in your shape layer and slightly modify the paths to get desired effect without having to manage a really complex compound path. Utilizing paths with strokes applied will always be one of the simplest approaches to animating assets for mobile. The number of points may be lower depending on the complexity of a scene, but overall the points will be easier to animate and control instead of trying to animate the inside and outside points of a compound path.

For much more complex compound shapes, there’s a couple tricks you can use in After Effects through stacking paths, utilizing the path directions and using ‘Fill Rule’ to cut one object out of another. When creating paths in After Effects or Illustrator, both applications keep track of which direction the path was created, clock-wise or counter clock-wise. These directions are really important to creating a compound path that renders correctly. We will use the example image shown below to discuss how to build compound assets correctly.

In this example, I will focus on a few key components. First is stacking the two paths within the same group with its fill and stroke. Second will be the path direction icons highlighted on the right.

In order to be able to build compound paths in a way that renders properly, it all starts by grouping the participating paths in the same shape layer group. This will tell After Effects and Bodymovin/Lottie which paths are suppose to intersect to create the compound shape. Order of which path is on top or on bottom is irrelevant. The more important aspect is which direction the paths were created which leads us into the second point.

As mentioned above, the direction in which a path is created is very important to this process. As far as I am aware, there’s no easy way to tell this except through trial and error. In the example above the word ‘COMPOUND’ was created using a font in Illustrator and then converted to outlines and exported to After Effects using the plugin Overlord. When working through this example, it appears that the font I used for the example was built using paths that were already reversed from each other, which means that somewhere along the creation of the letter ‘O’ in this font, one path was built in a clock-wise direction while the other was built in a counter clock-wise direction. The confusion comes when you look at the path direction buttons highlighted to the right on the image above. If you were to take After Effects’ word for it, you would assume that both paths are created in the same direction because of the way the buttons are highlighted, but unfortunately this is a mistake on After Effects part. In a perfect UI world, an animator would hope that when you bring the two paths in After Effects, it would be setup properly, but below I have shown why that isn’t the case.

On the left is the way the UI should be, on the right is the way the UI works as of now when two paths are built opposite direction of each other. So where does that leave us. When bringing two paths into AE, some experimentation needs to be done to get the compound path displayed properly. That means, if you bring in two paths that are already reversed from each other, then the ‘incorrect’ setup I have highlighted above should give you the results you are looking for. On the other hand, if you bring in two paths that were built going the same direction, then the ‘correct’ setup shown above is the way you want to setup the path directions. When you change the direction of one of the two paths, After Effects should display the compound path correctly if your path directions buttons are set correctly.

TL;DR – In order to get your compound paths to display correctly, some experimentation will be needed with the path direction buttons. If compound path is displayed correctly in AE, it should export correctly for Bodymovin and Lottie.

An Evolving Workflow

Since Lottie and Bodymovin are still evolving, some of this info will be part of ongoing discussions, changes and updates. It’s always great to hear input on workflow tips and tricks, especially where every bit of data counts when exporting for mobile. Please feel free to share your thoughts and tips in the comments below. Thank you for reading!

--

--