Search Docs
Loading...
Skip to content

Import Lottie Animations

Load Lottie animations that the Lottie importer converted into editable blocks, change their slots through variables and read their markers.

Two imported Lottie badges, the first with its brand slot recolored green

10 mins
estimated time
GitHub

Lottie is a JSON format for vector animation. The @imgly/lottie-importer package turns each layer of a Lottie .json file or a dotLottie .lottie archive into blocks inside one group. Shape, text, solid, image and precomp layers become native blocks that keep their animation as keyframe tracks, so users can select and edit them like any other block.

The importer runs in Node.js and the browser. There is no Lottie importer on iOS and macOS. Import the file once with the Node.js importer, save the scene as an .imgly archive, and load that archive in the app.

Loading the Converted Archive#

engine.scene.load(from:overrideEditorConfig:waitForResources:) loads the .imgly archive and replaces the current scene.

// `overrideEditorConfig: true` also loads the variables that the importer created for the slots.
try await engine.scene.load(from: archiveURL, overrideEditorConfig: true, waitForResources: true)

Point archiveURL at a bundled archive, resolved with Bundle.main.url(forResource:withExtension:), or at a download from your server. The archive bundles the scene with its resources, including the Lottie documents of layers that play back from a video fill. Pass overrideEditorConfig as true, so the engine also loads the variables that the importer created for the Lottie slots. It replaces the variables and the other editor settings of the engine with those of the archive.

Finding the Imported Blocks#

Each import is one group on the page. Each block in the group carries the name of its Lottie layer. When a layer can move outside the composition, the group also holds a block named “Composition clip” that clips the group to the composition. The animated transform, opacity and properties of a layer are keyframe tracks on its block.

// Each import is one group on the page. Its blocks carry the names of the Lottie layers.
guard let page = try engine.scene.getPages().first,
let group = try engine.block.getChildren(page).first else { return }
let layerNames = try engine.block.getChildren(group).map { try engine.block.getName($0) }
print("Imported layers:", layerNames)
// The animation of a layer is a set of keyframe tracks on its block.
if let ring = engine.block.find(byName: "Ring").first {
print("Animated properties of the ring:", try engine.block.getAnimatedProperties(ring))
}

A layer with a feature that has no native block equivalent, such as a 3D layer, became a graphic block. Its video fill plays a Lottie document that holds only that layer, so the layer still animates but users cannot edit its content.

Changing Slots Through Variables#

A Lottie slot is a value that a file marks for replacement with a slot id (sid). The importer turned each color, number, image and text slot into a variable named after the slot id. When a variable with that name already existed, it picked the first free name: <id> (2), <id> (3) and so on. The example archive holds two imports of the same badge, so the first one uses brand and the second brand (2).

// The "brand" slot became a color variable. Setting it recolors every fill that uses the slot.
try engine.variable.set(key: "brand", color: .rgba(r: 0.13, g: 0.55, b: 0.45, a: 1))

Setting the variable changes every bound property: a layer opacity, an image, and a shape fill or stroke color. An opacity variable holds the block opacity from 0 to 1. An animated slot keeps its keyframes, and they override the value that the variable sets.

Reading Markers#

The importer added the Lottie markers to the scene. engine.scene.getMarkers() returns each marker with its name, its time in seconds from the start of the composition, and its duration in seconds. Each import appends its markers, so the example archive holds the markers of both badges.

// Lottie markers became scene markers, in seconds.
for marker in try engine.scene.getMarkers() {
print("Marker \"\(marker.name)\" at \(marker.time)s for \(marker.duration)s")
}

Saving the Scene#

To save the scene again, use engine.scene.saveToArchive(), which bundles the Lottie documents of fallback layers. After loading an archive, these documents are transient buffer:// resources, so a string save fails with SCENE.DISALLOWED_SCHEMES unless you relocate them first. The Node.js importer itself creates them as data: URIs, which a string save accepts only when its allowed resource schemes include data.

Importing Versus a Lottie Video Fill#

You can still set a .json or .lottie URI as the fill/video/fileURI of a video fill. That plays the whole animation as one block, and users cannot edit its layers. The Lottie Fills guide shows how, and how the fill loads the images and fonts that the Lottie references. The fill draws the values of the animation’s slots. Like the importer, it ignores the themes of a .lottie archive. An image slot draws only when it embeds its image as a base64 data:image/ URI. The fill ignores the slots when the animation is larger than 32 MiB. For a .lottie archive, that size includes the images in the archive. A .lottie file in a video fill must be a valid dotLottie archive, with at most 1,024 entries, 128 MiB uncompressed and 32 MiB for the animation JSON. Otherwise the fill goes into the error state with SCENE.LOTTIE_ARCHIVE_INVALID, SCENE.LOTTIE_ARCHIVE_TOO_MANY_ENTRIES, SCENE.LOTTIE_ARCHIVE_TOO_LARGE or SCENE.LOTTIE_ARCHIVE_UNSAFE_PATH.

API Reference#

Method Description
engine.scene.load(from:overrideEditorConfig:waitForResources:) Load the converted archive with its variables
engine.scene.getPages() Find the page that holds the imported groups
engine.block.getChildren(_:) List the groups on the page and the blocks inside a group
engine.block.getName(_:) Read the layer name of an imported block
engine.block.find(byName:) Find an imported block by its layer name
engine.block.getAnimatedProperties(_:) List the properties that a layer animates
engine.variable.set(key:color:) Change a color slot
engine.scene.getMarkers() Read the markers that the importer added

Next Steps#