I am using Vue.js and Laravel for my project and recently added two animations using a plugin named Lottie. Each animation is a component, and they both use an individual JSON file to animate a group of PNG images (similar to a PNG sequence). These two JSON files are stored locally in the project folder under the path /public/data/.
Firstly the JSON files are not being read unless I put in the absolute path (/users/username/documents/projectname/public/data/filename.json), is there no way I can get this to work just by using /data/filename.json?
Secondly, when I add the code below in my component, my JS files are compiled to separate chunks as expected:
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
I get the following error when the animation tries to run:
Invalid prop: type check failed for prop "data". Expected Object, got Function
found in
---> <VueLottie>
However when I import my json file using a normal import in my component like below it works fine and shows the animation:
import animationData from "/users/username/documents/projectname/public/data/filename.json";
My animation components are both set up like this:
<template>
<vue-lottie ref="lottie" loop autoplay :data="animationData" :height="400" :width="400"></vue-lottie>
</template>
<script>
import vueLottie from "vue-lottie-ssr";
import animationData from '/users/username/documents/projectname/public/data/filename.json'
export default {
name: 'animation',
components: {
vueLottie
},
data () {
return {
speed: 1,
animationData
}
},
computed: {
lottie () {
return this.$refs.lottie
}
}
}
</script>
I have also tried getting the JSON file via an axios call when the component mounts, but the same error occurs.
Update
I updated my code so that each component is lazy loaded instead of the JSON file. Like so:
components: {
WinAnimation: () => import("./WinAnimation.vue");
LoseAnimation: () => import("./LoseAnimation.vue");
}
However now I'm getting the following error:
Unknown custom element: <win-animation> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Update 2
I realised why I was getting an error message. The correct way was to add the following at the top of my script inside the parent vue file.
const winAnimation = () => import("./WinAnimation.vue");
const loseAnimation = () => import("./LoseAnimation.vue");
and then inside export default {...} I forgot to add the names, so:
components: { winAnimation, loseAnimation }
Now my code has been split and my app.js file size has reduced by almost a half! :)
1st - don't use vue-lottie library. If you take a look at the source code, the main and only thing which should be provided by this library is component src/lottie.vue
(+ it's dependency lottie-web) but for some reason, NPM package also contains whole demo app including the demo JSON file (src/assets/pinjump.json
)
If you take a look at lottie.vue
component, its just very little and very simple wrapper for lottie-web
which provides main functionality. By getting rid of vue-lottie
you will get following benefits:
vue-lottie
completely ignores one of the lottie-web
options which is using path
instead of animationData
- documentation is not very clear here but I would guess that by providing path
, the library will try download the animation data ad-hoc so you don't need to include it in your bundle. Worth trying imho...
Loading animation data on demand
lottie-web
which is also not small. And Vue will handle loading of the component without any additional code changes...import(".....")
) is returning Promise and lottie-web
(and in turn vue-lottie
) is expecting object. So you must do something like this:<script>
import lottie from 'lottie-web';
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
export default {
mounted () {
animationData().then(function(data) {
this.anim = lottie.loadAnimation({
// other options
animationData: data
})
});
}
}
</script>
You should be always very careful when considering adding 3rd party components into your project. One more thing I'v noticed is that lottie-web
has destroy()
method in it's API. This indicates that it is creating some resources (DOM elements probably) which needs to be cleaned up. This is something vue-lottie
component is not handling at all and can lead to nasty memory leaks in your app. You can read about the problem here