blob: 1dceb5bec0408dd7aedb7edf97db01f49f9361ca [file] [log] [blame]
import { LottieAnimation, LottieAsset, LottieLayer } from '../types';
export interface ExtraLayerData {
layer: LottieLayer;
parentId: string;
precompName: string;
}
export interface TextData {
id: string;
name: string;
text: string;
maxChars?: number; // If not defined, we don't constrain the <textarea>
precompName: string;
items: ExtraLayerData[];
}
export const replaceTexts = (
texts: TextData[],
currentAnimation: LottieAnimation
): LottieAnimation => {
const animation = JSON.parse(
JSON.stringify(currentAnimation)
) as LottieAnimation;
texts.forEach((textData) => {
textData.items.forEach((item: ExtraLayerData) => {
let layers;
// Searches for composition that contains this layer
if (!item.parentId) {
layers = animation.layers;
} else {
const asset = animation.assets.find(
(assetItem: LottieAsset) => assetItem.id === item.parentId
);
layers = asset ? asset.layers : [];
}
// Replaces current animation layer with new layer value
layers.forEach((layer: LottieLayer, index: number) => {
if (layer.ind === item.layer.ind && layer.nm === item.layer.nm) {
layers[index] = item.layer;
}
});
});
});
return animation;
};
const replaceTextsInLayers = (
textsDictionary: Record<string, string>,
layers: LottieLayer[]
) => {
const LAYER_TEXT_TYPE = 5;
layers.forEach((layer: LottieLayer) => {
if (layer.ty === LAYER_TEXT_TYPE && textsDictionary[layer.nm]) {
// It's read as: Layer > Text Element > Text document > First Keyframe > Start Value > Text
const textElement: any = layer.t;
textElement.d.k[0].s.t = textsDictionary[layer.nm];
}
});
};
export const replaceTextsByLayerName = (
texts: TextData[],
currentAnimation: LottieAnimation
): LottieAnimation => {
if (!texts) {
return currentAnimation;
}
// Make a copy of the original animation.
const animation: LottieAnimation = JSON.parse(
JSON.stringify(currentAnimation)
) as LottieAnimation;
// Create dictionary to access data by name instead of iterating on every layer
const textsDictionary = texts.reduce(
(dict: Record<string, string>, text: TextData) => {
dict[text.name] = text.text;
return dict;
},
{}
);
replaceTextsInLayers(textsDictionary, animation.layers);
animation.assets
.filter((asset: LottieAsset) => asset.layers)
.forEach((asset: LottieAsset) =>
replaceTextsInLayers(textsDictionary, asset.layers)
);
return animation;
};