react-lottie icon indicating copy to clipboard operation
react-lottie copied to clipboard

How to locate /images/ for the animation

Open sgript opened this issue 6 years ago β€’ 26 comments

Hey there,

So we've got a data.json full of our animation data and an /images/ directory including the images that will be animated, given to us by our designer. However, I didn't see any mention of how the /images/ paths can be found through react-lottie? Unsure if this is the correct place to ask, but if anyone has come across this issue (as I myself don't know enough about After Effects - which it was exported with), could you advise?

I have seen this issue crop up on lottie-web itself and people suggest a way so that the /images/ folder doesn't appear on export, or does react-lottie have something like lottie-web, when it comes to picking up assetPaths for the .json? To ensure it finds the images.

Apologies if this seems vague, I'm just not very well versed in the design process itself.

sgript avatar Jul 10 '18 14:07 sgript

Hey @sgript

I solved it by creating my own json withing a javascript file.

Instead of using the animation.json directly, create a animation.js file where you import the image and replace the [image_in_question].png occurrences for your image_in_question_name. Remember to fix the folders path and delete it.

You are basically recreating the json with your own paths. This way, your image paths will be correct.

import image_in_question_name from './images/[image_in_question].png'

export default {"v": ...... ANIMATION JSON ....... };

This worked for me and I am using gatsby.

Hope it helps!

andreragsilva avatar Aug 24 '18 17:08 andreragsilva

I'm building a chrome extension and in that case images get a special path. I can access that path from javascript. How would I change the JSON so that it uses the correct path?

wahlforss avatar Sep 27 '18 14:09 wahlforss

@wahlforss look at this example:

import img_0 from './images/img_0.png'

export default {
  v: '5.2.1',
  fr: 25,
  ip: 1,
  op: 74,
  w: 500,
  h: 500,
  nm: 'pulseloop',
  ddd: 0,
  assets: [
    { id: 'image_0', w: 701, h: 632, u: '', p: img_0, e: 0 },
    {
      id: 'comp_0',
      layers: [
        {
          ddd: 0,
          ind: 1,
          ty: 2,
          nm: img_0,
          cl: 'png',
          refId: 'image_0',
....

I changed the u:'path-to-folder' to u: '' and all the occurrences where you use the image name to img_0 which represents the image direct path.

Hope it helps πŸ‘

andreragsilva avatar Sep 27 '18 15:09 andreragsilva

@rageofflames

Thank you man! That fixed it :)

wahlforss avatar Sep 27 '18 15:09 wahlforss

@rageofflames @sgript

Hey! it seems you can also just place it in the public folder with the same path structure ('./public/images/img_0.png) and it will work.

haven't tested with multiple files so names might clash too, in which case renaming .png names as mentioned before will work too.

had a quick read through the animation.json and found that the structure of the json is different from the one @rageofflames posted, so because versions, YMMV.

*tested on react-lottie 1.2.3

panzerstadt avatar Oct 18 '18 08:10 panzerstadt

@panzerstadt Yes, adding directly to the public folder makes the image available but how did you automate the process of placing the image in the public folder?

If the structure is different, you just have to assure the image path is correct πŸ‘

andreragsilva avatar Oct 18 '18 12:10 andreragsilva

oh sorry about that @rageofflames , I might not have been answering the main thread directly. I manually edited them because i was only dealing with a small number of animations.

I only mentioned it in case others came along (like me) looking for the easiest way to make lottie pngs work in react and didn't know that we could just place it in the public folder.

your method looks really good for automating image imports, I'll do that from now on!

panzerstadt avatar Oct 26 '18 04:10 panzerstadt

@wahlforss look at this example:

import img_0 from './images/img_0.png'

export default {
  v: '5.2.1',
  fr: 25,
  ip: 1,
  op: 74,
  w: 500,
  h: 500,
  nm: 'pulseloop',
  ddd: 0,
  assets: [
    { id: 'image_0', w: 701, h: 632, u: '', p: img_0, e: 0 },
    {
      id: 'comp_0',
      layers: [
        {
          ddd: 0,
          ind: 1,
          ty: 2,
          nm: img_0,
          cl: 'png',
          refId: 'image_0',
....

I changed the u:'path-to-folder' to u: '' and all the occurrences where you use the image name to img_0 which represents the image direct path.

Hope it helps

Thank you!

erikfenriz avatar Nov 01 '18 10:11 erikfenriz

The images aren't visible outside public folder, move the png's to the public folder (you can put them wherever, like in "public/animations/[animationName]/"). In the .json, change u:"images/" for the folder where your images are ( using the last example should be u:animations/[animationName]/ )

jmaru avatar Dec 28 '18 22:12 jmaru

@wahlforss look at this example:

import img_0 from './images/img_0.png'

export default {
  v: '5.2.1',
  fr: 25,
  ip: 1,
  op: 74,
  w: 500,
  h: 500,
  nm: 'pulseloop',
  ddd: 0,
  assets: [
    { id: 'image_0', w: 701, h: 632, u: '', p: img_0, e: 0 },
    {
      id: 'comp_0',
      layers: [
        {
          ddd: 0,
          ind: 1,
          ty: 2,
          nm: img_0,
          cl: 'png',
          refId: 'image_0',
....

I changed the u:'path-to-folder' to u: '' and all the occurrences where you use the image name to img_0 which represents the image direct path.

Hope it helps πŸ‘

Thanks dude, this worked!

rowgregory avatar Apr 01 '19 20:04 rowgregory

I understand the solution that is given in previous answers, but I can't seem to figure out how to import and use this as animationData for the Lottie component.

My snippet:

import * as React from 'react';
import Lottie from 'react-lottie';
import animationData from '../../assets/animations/background-animation/animation.js';

export default class BackgroundAnimation extends React.Component {

    constructor(props) {
      super(props);
      this.state = {isStopped: false, isPaused: false};
    }
  
    render() {  
      const defaultOptions = {
        loop: true,
        autoplay: true, 
        animationData: animationData,
        rendererSettings: {
          preserveAspectRatio: 'xMidYMid slice'
        }
      };
  
      return <Lottie options={defaultOptions}/>
    }
  }

Skagoo avatar Apr 03 '19 11:04 Skagoo

@Skagoo

import animationData from '../../assets/animations/background-animation/animation.js';

Try removing the .js extension and if it doesn't work can you share the animation.js file?

andreragsilva avatar Apr 03 '19 12:04 andreragsilva

Make sure the path to the animationData is correct and then make the json file a js file and import the pictures into js file you are trying to use. Then in assets in the js file change the β€œp” to the imported picture variable name. I used β€œimg_0” and so on

Sent from my iPhone

On Apr 3, 2019, at 7:05 AM, Sacha [email protected] wrote:

I understand the solution that is given in previous answers, but I can't seem to figure out how to import and use this as animationData for the Lottie component.

My snippet:

import * as React from 'react'; import Lottie from 'react-lottie'; import animationData from '../../assets/animations/background-animation/animation.js';

export default class BackgroundAnimation extends React.Component {

constructor(props) {
  super(props);
  this.state = {isStopped: false, isPaused: false};
}

render() {  
  const defaultOptions = {
    loop: true,
    autoplay: true, 
    animationData: animationData,
    rendererSettings: {
      preserveAspectRatio: 'xMidYMid slice'
    }
  };

  return <Lottie options={defaultOptions}/>
}

} β€” You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

rowgregory avatar Apr 03 '19 12:04 rowgregory

Thanks for replying.
@rowgregory, what you described is exactly what I did. The issue I'm facing tho is that the import of the animation.js file throws Uncaught Error: Cannot find module '../../assets/animations/background-animation/animation.js'

@rageofflames, removing the .js extension results in the same error Uncaught Error: Cannot find module '../../assets/animations/background-animation/animation' but without the .js ofcourse. This is a snippet from my animation.js file.

import img_0 from './images/img_0.png'
import img_1 from './images/img_1.png'
...

export default {
    "v": "5.4.4",
    "fr": 30,
    "ip": 0,
    "op": 930,
    "w": 1920,
    "h": 1080,
    "nm": "TV - landscape",
    "ddd": 0,
    "assets": [
        {
            "id": "image_0",
            "w": 2349,
            "h": 1134,
            "u": "",
            "p": img_0,
            "e": 0
        },
        {
            "id": "image_1",
            "w": 1138,
            "h": 1139,
            "u": "",
            "p": img_1,
            "e": 0
        },
        ...
     ]
}

Skagoo avatar Apr 03 '19 12:04 Skagoo

@Skagoo your code appears to be similar to mine, the problem seems to be related to the paths and it's hard to help you πŸ€”Check the import path, recompile, manually check if the file is at the expected path...

andreragsilva avatar Apr 03 '19 12:04 andreragsilva

Yeah you probably need to get rid of ../../

Sent from my iPhone

On Apr 3, 2019, at 8:42 AM, Sacha [email protected] wrote:

Thanks for replying. @rowgregory, what you described is exactly what I did. The issue I'm facing tho is that the import of the animation.js file throws Uncaught Error: Cannot find module '../../assets/animations/background-animation/animation.js'

@rageofflames, removing the .js extension results in the same error Uncaught Error: Cannot find module '../../assets/animations/background-animation/animation' but without the .js ofcourse. This is a snippet from my animation.js file.

import img_0 from './images/img_0.png' import img_1 from './images/img_1.png' ...

export default { "v": "5.4.4", "fr": 30, "ip": 0, "op": 930, "w": 1920, "h": 1080, "nm": "TV - landscape", "ddd": 0, "assets": [ { "id": "image_0", "w": 2349, "h": 1134, "u": "", "p": img_0, "e": 0 }, { "id": "image_1", "w": 1138, "h": 1139, "u": "", "p": img_1, "e": 0 }, ... ] } β€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

rowgregory avatar Apr 03 '19 13:04 rowgregory

@rageofflames after digging a bit deeper I found the following issue Module not found: Error: Can't resolve 'source-map-loader' in '/Users/sacha/Documents/dev/DocFoundry/af-doc-fe/src'

@rowgregory I've tried that as well.. Been playing around with the path but that doesn't seem to do the trick.

This is the relevant project structure.

.
└── src
    β”œβ”€β”€ assets
    β”‚   └── animations
    β”‚       └── background-animation
    β”‚           β”œβ”€β”€ images
    β”‚           β”‚   β”œβ”€β”€ img_0.png
    β”‚           β”‚   └── img_1.png
    β”‚           └── animation.js
    └── modules
        └── Waldo
            └── BackgroundAnimation.tsx

Thanks for helping me out, I will keep you posted if anything changes.

Skagoo avatar Apr 03 '19 13:04 Skagoo

Update: If I place the contents of animation.js in the same file as BackgroundAnimation.tsx It works perfectly fine. So it is indeed an issue in the import reference.. Can't seem to find out what is wrong with the statement though.

EDIT Tis issue is still not resolved, for now I am placing the json animationData in the same file, BackgroundAnimation.tsx.

Skagoo avatar Apr 03 '19 13:04 Skagoo

My issue was fixed by placing the json in a .tsx file instead of .js.

Skagoo avatar Apr 17 '19 12:04 Skagoo

I've found another way and I guess this is easier than converting JSON to JS. If you are using Gatsby, you should move your assets for the animation to the static folder. The static folder should be at the root of your project.

For example. -static --animations ---img_0.png ---img_1.png ---img_2.png

After that in your JSON file you should only change the path parameter - "u": "animations/" and that's it.

Gatsby automatically copies the static folder into the public folder, and here you will see new folder animations from the static folder with your images, that you created.

necheporenko avatar Mar 27 '20 12:03 necheporenko

@wahlforss look at this example:

import img_0 from './images/img_0.png'

export default {
  v: '5.2.1',
  fr: 25,
  ip: 1,
  op: 74,
  w: 500,
  h: 500,
  nm: 'pulseloop',
  ddd: 0,
  assets: [
    { id: 'image_0', w: 701, h: 632, u: '', p: img_0, e: 0 },
    {
      id: 'comp_0',
      layers: [
        {
          ddd: 0,
          ind: 1,
          ty: 2,
          nm: img_0,
          cl: 'png',
          refId: 'image_0',
....

I changed the u:'path-to-folder' to u: '' and all the occurrences where you use the image name to img_0 which represents the image direct path.

Hope it helps πŸ‘

thanks a lot !!!!!!

sophieChenyx avatar Sep 30 '20 03:09 sophieChenyx

I found myself processing a lot of Lottie files this way so I wrote a really hacky node script if anyone's interested - it takes a command line argument of the path of the .json file and the images/ folder and writes an index.js file there with the correct image imports and asset "p" names:

const fs = require('fs');
const util = require('util');
const path = require("path")

const readdir = util.promisify(fs.readdir);

const filePath = process.argv.slice(2)[0]

async function getFileNames(pathToDir) {
    let names;
    try {
        names = await readdir(pathToDir);
    } catch (err) {
        console.log(err);
    }
    if (names === undefined) {
        console.log('undefined');
    } else {
        return names
    }
}


// provide the location of .json file and /images w/ path

let jsonFile
let imageNames


getFileNames(filePath).then(allFiles => {
    allFiles.forEach(file => {
        if (path.extname(file) === ".json") {
            jsonFile = file
        }
    })


    let json = JSON.parse(fs.readFileSync(filePath + "/" + jsonFile, 'utf8'))


    json.assets.forEach(asset => {
        if (asset.id.slice(0, 5) === "image") {
            asset.u = ''
            const assetString = asset.p.replace(".png", "")
            asset.p = "REPLACE" + assetString + "REPLACE"
        }
    })

    getFileNames(filePath + "/images").then(res => {
        imageNames = res
        imageNames = imageNames.map(image => "import " + image.replace(".png", "") + " from './images/" + image + "'")
        let finalFile = imageNames.join("\n") + "\n" +
            // then read json file and remove "u":"images/","p":"img_2.png" => "u":"","p":img_2
            "export default " + JSON.stringify(json).replace(/"REPLACE|REPLACE"/g, "")
        fs.writeFile(filePath + "/" + "index.js", finalFile, err => err && console.log("error", err))
    })
})

So you could invoke it like:

node <this-scripts-name>.js /Users/YOURUSERNAME/Downloads/lotties/my-lottie-folder

joelwilsonmt avatar Mar 02 '21 22:03 joelwilsonmt

I've found another way and I guess this is easier than converting JSON to JS. If you are using Gatsby, you should move your assets for the animation to the static folder. The static folder should be at the root of your project.

For example. -static --animations ---img_0.png ---img_1.png ---img_2.png

After that in your JSON file you should only change the path parameter - "u": "animations/" and that's it.

Gatsby automatically copies the static folder into the public folder, and here you will see new folder animations from the static folder with your images, that you created.

Hope this works for NextJS, but sadly it doesnt.

Anybody working with image lottie on NextJS?

----- EDIT ---- It worked. I missed trailing / on the path

softmarshmallow avatar Mar 05 '21 17:03 softmarshmallow

In addition to the solution above, for the NextJS the static folder is currently deprecated and you can move the your animation folder into your public folder directly. In your JSON file only change the path parameter - "u": "animation's directory name/" like the solution above

Hammed-Oluwatoyin avatar Jul 08 '21 20:07 Hammed-Oluwatoyin

Hey @sgript

I solved it by creating my own json withing a javascript file.

Instead of using the animation.json directly, create a animation.js file where you import the image and replace the [image_in_question].png occurrences for your image_in_question_name. Remember to fix the folders path and delete it.

You are basically recreating the json with your own paths. This way, your image paths will be correct.

import image_in_question_name from './images/[image_in_question].png'

export default {"v": ...... ANIMATION JSON ....... };

This worked for me and I am using gatsby.

Hope it helps!

Thanks This worked :smiley:

annu12340 avatar Jan 31 '22 04:01 annu12340

animations @necheporenko It really works perfectly from me. Thanks a lot. :)

tptspe avatar Dec 28 '22 04:12 tptspe