react-lottie 2.3.1 → 2.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +336 -5
- package/dist/index.js +33 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [2.3.3](https://github.com/chenqingspring/react-lottie/compare/v2.3.2...v2.3.3) (2026-11-08)
|
|
6
|
+
|
|
7
|
+
### Documentation
|
|
8
|
+
|
|
9
|
+
* document animations that reference raster images: the `assets` array, the `assetsPath` option and rewriting assets to bundler-hashed URLs ([#49](https://github.com/chenqingspring/react-lottie/issues/49), [#59](https://github.com/chenqingspring/react-lottie/issues/59))
|
|
10
|
+
* document aliasing `lottie-web` to `lottie_light`, `lottie_light_canvas` or `lottie_light_html` to cut the bundled player by about 45% ([#79](https://github.com/chenqingspring/react-lottie/issues/79))
|
|
11
|
+
* document server-side rendering and add a regression test that renders the component in a Node process without a DOM ([#17](https://github.com/chenqingspring/react-lottie/issues/17))
|
|
12
|
+
|
|
13
|
+
## [2.3.2](https://github.com/chenqingspring/react-lottie/compare/v2.3.1...v2.3.2) (2026-11-07)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* accept a namespace import (`import * as animationData`) by unwrapping its `default` export and clone frozen animation objects before handing them to lottie-web, so they no longer fail with `Cannot read property 'length' of undefined` (#24, #65)
|
|
18
|
+
* throw an actionable error when `options.animationData` is a string or when neither `animationData` nor `path` is provided, instead of lottie-web's `Cannot create property 'tf' on string` / `Cannot read property 'length' of undefined` deep in the renderer (#44)
|
|
19
|
+
* fix the README examples that read `.default` from a default import, which passed `undefined` as the animation data
|
|
20
|
+
|
|
5
21
|
## [2.3.1](https://github.com/chenqingspring/react-lottie/compare/v2.3.0...v2.3.1) (2026-11-05)
|
|
6
22
|
|
|
7
23
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -37,10 +37,76 @@ npm install --save react-lottie
|
|
|
37
37
|
> [GitHub](https://github.com/chenqingspring/react-lottie/issues) and Relay
|
|
38
38
|
> will review and fix it.
|
|
39
39
|
|
|
40
|
+
## Using from a CDN (no bundler)
|
|
41
|
+
|
|
42
|
+
The published `dist/index.js` is a CommonJS build for bundlers and npm
|
|
43
|
+
consumers. It uses `exports` and expects `react`, `prop-types` and `lottie-web`
|
|
44
|
+
to be resolvable, so loading that file with a plain `<script>` tag fails with
|
|
45
|
+
`Uncaught ReferenceError: exports is not defined`. The package does not ship a
|
|
46
|
+
UMD/browser global build.
|
|
47
|
+
|
|
48
|
+
To use react-lottie without a build step, load it as an ES module from a CDN
|
|
49
|
+
and map `react` to the same copy the page uses. [esm.sh](https://esm.sh)
|
|
50
|
+
supports `?external=react` for exactly this:
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<script type="importmap">
|
|
54
|
+
{
|
|
55
|
+
"imports": {
|
|
56
|
+
"react": "https://esm.sh/react@18",
|
|
57
|
+
"react-dom/client": "https://esm.sh/react-dom@18/client",
|
|
58
|
+
"react-lottie": "https://esm.sh/react-lottie@2?external=react"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
<script type="module">
|
|
63
|
+
import React from 'react';
|
|
64
|
+
import { createRoot } from 'react-dom/client';
|
|
65
|
+
import Lottie from 'react-lottie';
|
|
66
|
+
|
|
67
|
+
const options = {
|
|
68
|
+
path: '/animations/pinjump.json',
|
|
69
|
+
loop: true,
|
|
70
|
+
autoplay: true,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
createRoot(document.getElementById('root')).render(
|
|
74
|
+
React.createElement(Lottie, { options, height: 400, width: 400 })
|
|
75
|
+
);
|
|
76
|
+
</script>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Without a compiler for JSX, create elements with `React.createElement`, or add
|
|
80
|
+
`htm`/Babel. Keeping `react` in the import map gives the page one React
|
|
81
|
+
instance; a CDN build that bundles its own React (such as jsDelivr's `+esm`
|
|
82
|
+
output) produces two copies, which breaks context and hooks.
|
|
83
|
+
|
|
84
|
+
If you only need to play an animation and not the React wrapper, load
|
|
85
|
+
lottie-web directly and skip React entirely:
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.12.2/lottie.min.js"></script>
|
|
89
|
+
<script>
|
|
90
|
+
lottie.loadAnimation({
|
|
91
|
+
container: document.getElementById('root'),
|
|
92
|
+
path: '/animations/pinjump.json',
|
|
93
|
+
renderer: 'svg',
|
|
94
|
+
loop: true,
|
|
95
|
+
autoplay: true,
|
|
96
|
+
});
|
|
97
|
+
</script>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
An ESM CDN build still downloads React, React DOM, lottie-web and react-lottie,
|
|
101
|
+
so it removes the build step but not the bytes. For production, a bundler that
|
|
102
|
+
shares one React copy and tree-shakes lottie-web is smaller.
|
|
103
|
+
|
|
40
104
|
## Requirements
|
|
41
105
|
|
|
42
|
-
React 16.8 or newer
|
|
43
|
-
|
|
106
|
+
React 16.8 or newer, including React 17, React 18 and React 19. The
|
|
107
|
+
`react: ">=16.8.0"` peer dependency resolves without `--legacy-peer-deps` or
|
|
108
|
+
`--force`. The test suite runs against React 18; the component uses plain class
|
|
109
|
+
components and works with React 17 and React 19 as well.
|
|
44
110
|
|
|
45
111
|
## Local development
|
|
46
112
|
|
|
@@ -95,7 +161,7 @@ export default class LottieControl extends React.Component {
|
|
|
95
161
|
const defaultOptions = {
|
|
96
162
|
loop: true,
|
|
97
163
|
autoplay: true,
|
|
98
|
-
animationData
|
|
164
|
+
animationData,
|
|
99
165
|
rendererSettings: {
|
|
100
166
|
preserveAspectRatio: 'xMidYMid slice'
|
|
101
167
|
}
|
|
@@ -116,6 +182,11 @@ export default class LottieControl extends React.Component {
|
|
|
116
182
|
|
|
117
183
|
```
|
|
118
184
|
|
|
185
|
+
Pass the parsed animation object as `options.animationData`. A file path or URL
|
|
186
|
+
belongs in `options.path`; a namespace import
|
|
187
|
+
(`import * as animationData`) is unwrapped automatically but the default import
|
|
188
|
+
above is preferred.
|
|
189
|
+
|
|
119
190
|
### Loading animation data without bloating the bundle
|
|
120
191
|
|
|
121
192
|
A static import like `import animationData from './pinjump.json'` (the example
|
|
@@ -184,6 +255,170 @@ Finally, the file itself can usually get smaller: export at a lower precision,
|
|
|
184
255
|
remove unused layers and precompositions, avoid embedded raster images, and let
|
|
185
256
|
gzip/Brotli compress the JSON. LottieFiles' optimizer automates the first steps.
|
|
186
257
|
|
|
258
|
+
### Animations with raster images
|
|
259
|
+
|
|
260
|
+
An After Effects export that contains bitmap layers references those files from
|
|
261
|
+
the animation's `assets` array. Each entry carries a directory (`u`), a file name
|
|
262
|
+
(`p`) and an embedded flag (`e`):
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{ "id": "image_0", "w": 720, "h": 720, "u": "images/", "p": "img_0.png", "e": 0 }
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
With `"e": 0` lottie-web loads the file separately and resolves `u + p` relative
|
|
269
|
+
to the page, which breaks as soon as the app is served from a sub-path or
|
|
270
|
+
navigates client-side. Set `options.assetsPath` to the directory where the
|
|
271
|
+
images are deployed instead; react-lottie forwards unknown options to
|
|
272
|
+
lottie-web:
|
|
273
|
+
|
|
274
|
+
```jsx
|
|
275
|
+
const defaultOptions = {
|
|
276
|
+
path: '/animations/cypher.json',
|
|
277
|
+
assetsPath: '/animations/images/', // trailing slash required
|
|
278
|
+
loop: true,
|
|
279
|
+
autoplay: true,
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
<Lottie options={defaultOptions} height={400} width={400} />
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Copy the images next to the JSON in `public/animations/images/` so they are
|
|
286
|
+
served as static files instead of being bundled. `assetsPath` works with both
|
|
287
|
+
`path` and `animationData`, and it applies to every image in the animation.
|
|
288
|
+
|
|
289
|
+
If you want the bundler to hash and inline the images, import them yourself and
|
|
290
|
+
rewrite the asset entries before passing the data. Don't mutate the imported
|
|
291
|
+
JSON in place when it is a frozen ESM object:
|
|
292
|
+
|
|
293
|
+
```jsx
|
|
294
|
+
import img0 from './images/img_0.png';
|
|
295
|
+
import animationData from './cypher.json';
|
|
296
|
+
|
|
297
|
+
const data = {
|
|
298
|
+
...animationData,
|
|
299
|
+
assets: animationData.assets.map((asset) => (
|
|
300
|
+
asset.id === 'image_0' ? { ...asset, u: '', p: img0 } : asset
|
|
301
|
+
)),
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
<Lottie options={{ animationData: data, loop: true, autoplay: true }} />
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
`"e": 1` means the image is embedded in the JSON as a base64 data URI. That
|
|
308
|
+
keeps the animation self-contained, but it inflates the file by roughly a third
|
|
309
|
+
and prevents the browser from caching the image separately, so prefer external
|
|
310
|
+
images for anything large.
|
|
311
|
+
|
|
312
|
+
### Shrinking the lottie-web bundle
|
|
313
|
+
|
|
314
|
+
react-lottie imports the full `lottie-web` player (299 kB minified, 611 kB
|
|
315
|
+
unminified in lottie-web 5.13), which includes the expression engine and every
|
|
316
|
+
renderer. If your animations don't use expressions and you only need one
|
|
317
|
+
renderer, alias `lottie-web` to a smaller build; react-lottie keeps working
|
|
318
|
+
because those builds expose the same `loadAnimation` API.
|
|
319
|
+
|
|
320
|
+
Vite:
|
|
321
|
+
|
|
322
|
+
```js
|
|
323
|
+
// vite.config.js
|
|
324
|
+
export default defineConfig({
|
|
325
|
+
resolve: {
|
|
326
|
+
alias: {
|
|
327
|
+
'lottie-web': 'lottie-web/build/player/lottie_light.js',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
webpack (Create React App, Next.js):
|
|
334
|
+
|
|
335
|
+
```js
|
|
336
|
+
// next.config.js
|
|
337
|
+
module.exports = {
|
|
338
|
+
webpack(config) {
|
|
339
|
+
config.resolve.alias['lottie-web'] = require.resolve(
|
|
340
|
+
'lottie-web/build/player/lottie_light.js'
|
|
341
|
+
);
|
|
342
|
+
return config;
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
The light builds are about 45% smaller (164 kB vs 299 kB minified):
|
|
348
|
+
|
|
349
|
+
* `lottie_light.js` — SVG renderer only, no expressions; shapes and raster
|
|
350
|
+
images still work.
|
|
351
|
+
* `lottie_light_canvas.js` — canvas renderer only, no expressions.
|
|
352
|
+
* `lottie_light_html.js` — HTML renderer only, no expressions.
|
|
353
|
+
|
|
354
|
+
Pick the build that matches `options.renderer`: `lottie_light` only registers
|
|
355
|
+
the SVG renderer, so pass `renderer: 'svg'` (the default); use
|
|
356
|
+
`lottie_light_canvas` with `renderer: 'canvas'`. Don't alias when an animation
|
|
357
|
+
uses expressions or effects, because the light builds silently skip them.
|
|
358
|
+
|
|
359
|
+
### Performance on iOS and low-end devices
|
|
360
|
+
|
|
361
|
+
File size mostly affects how long an animation takes to download and parse, not
|
|
362
|
+
its frame rate. Once playback starts, the cost of each frame comes from what the
|
|
363
|
+
renderer has to draw: the number of layers and shapes, masks and mattes,
|
|
364
|
+
expressions, effects, and the pixel size of the canvas. A multi-megabyte export
|
|
365
|
+
is a good signal that there is a lot of that (issue #133).
|
|
366
|
+
|
|
367
|
+
On iOS 14.5, Safari, Chrome and Firefox all run on WebKit, so they render at the
|
|
368
|
+
same speed; measuring in Safari is representative. Phones are also much slower
|
|
369
|
+
than a desktop, so an animation that is smooth on a laptop can drop frames on
|
|
370
|
+
mobile.
|
|
371
|
+
|
|
372
|
+
In rough order of impact:
|
|
373
|
+
|
|
374
|
+
1. **Reduce the animation.** Remove hidden and unused layers, flatten
|
|
375
|
+
precompositions, simplify masks and mattes, drop expressions and effects, and
|
|
376
|
+
avoid embedded raster images. If one scene is still heavy, split it into
|
|
377
|
+
smaller files and play only the needed range with `segments`.
|
|
378
|
+
2. **Draw it at the size it is displayed.** `width` and `height` set the
|
|
379
|
+
container size; rendering a 1200 px animation into a 300 px slot does more
|
|
380
|
+
work than necessary. With the canvas renderer, also cap the backing-store
|
|
381
|
+
resolution: at a device pixel ratio of 3, a 400 px canvas is rasterized at
|
|
382
|
+
1200 px unless you set `dpr`.
|
|
383
|
+
3. **Compare the renderers.** `svg` (the default) is usually fastest for a few
|
|
384
|
+
large shapes and stays crisp at any size. `canvas` avoids updating hundreds
|
|
385
|
+
of DOM nodes and often wins for animations with many small shapes. Measure
|
|
386
|
+
both on the target device.
|
|
387
|
+
4. **Stop off-screen animations.** lottie-web drives every playing animation
|
|
388
|
+
from the same `requestAnimationFrame` loop, so an animation scrolled out of
|
|
389
|
+
view still costs a frame. Pause it with `isPaused`, or with `pause()` on a
|
|
390
|
+
`ref`, driven by an `IntersectionObserver`.
|
|
391
|
+
|
|
392
|
+
```jsx
|
|
393
|
+
const defaultOptions = {
|
|
394
|
+
animationData,
|
|
395
|
+
loop: true,
|
|
396
|
+
autoplay: true,
|
|
397
|
+
renderer: 'canvas',
|
|
398
|
+
rendererSettings: {
|
|
399
|
+
dpr: 1, // render at CSS resolution; use 2 for a sharper middle ground
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
<Lottie options={defaultOptions} height={300} width={300} />
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
For the default `svg` renderer, `rendererSettings.progressiveLoad` builds the
|
|
407
|
+
layers over several frames instead of blocking on the first one. It does not
|
|
408
|
+
wait for the element to scroll into view; pause off-screen animations yourself:
|
|
409
|
+
|
|
410
|
+
```jsx
|
|
411
|
+
// `visible` is kept up to date by an IntersectionObserver on a wrapper element.
|
|
412
|
+
<Lottie
|
|
413
|
+
options={{ animationData, loop: true, autoplay: false, rendererSettings: { progressiveLoad: true } }}
|
|
414
|
+
isPaused={!visible}
|
|
415
|
+
/>
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
If a reduced file still drops frames, profile it: record a timeline in Safari's
|
|
419
|
+
Web Inspector while the animation plays and check whether the time goes to
|
|
420
|
+
lottie-web's frame update or to the browser painting and compositing the layers.
|
|
421
|
+
|
|
187
422
|
### Play on hover
|
|
188
423
|
|
|
189
424
|
`eventListeners` takes lottie-web animation events (`complete`, `loopComplete`,
|
|
@@ -211,7 +446,7 @@ export default class HoverLottie extends React.Component {
|
|
|
211
446
|
const defaultOptions = {
|
|
212
447
|
loop: false,
|
|
213
448
|
autoplay: false,
|
|
214
|
-
animationData
|
|
449
|
+
animationData,
|
|
215
450
|
rendererSettings: {
|
|
216
451
|
preserveAspectRatio: 'xMidYMid slice'
|
|
217
452
|
}
|
|
@@ -298,6 +533,102 @@ The container is a `div` by default, which is not a valid child of `<p>`. Pass
|
|
|
298
533
|
lottie-web should render into. Changing `as` reloads the animation into the new
|
|
299
534
|
element and keeps the current frame.
|
|
300
535
|
|
|
536
|
+
### Switch between several animations
|
|
537
|
+
|
|
538
|
+
Each `<Lottie>` owns one lottie-web instance, so an app can render two
|
|
539
|
+
animations side by side or keep one animation per page. To choose which one is
|
|
540
|
+
shown, keep the animation data in a map and pass the entry for the current page
|
|
541
|
+
as `options.animationData` (issue #128):
|
|
542
|
+
|
|
543
|
+
```jsx
|
|
544
|
+
import homeData from './animations/home.json';
|
|
545
|
+
import aboutData from './animations/about.json';
|
|
546
|
+
|
|
547
|
+
const animations = { home: homeData, about: aboutData };
|
|
548
|
+
|
|
549
|
+
const PageAnimation = ({ page }) => (
|
|
550
|
+
<Lottie
|
|
551
|
+
options={{
|
|
552
|
+
loop: true,
|
|
553
|
+
autoplay: true,
|
|
554
|
+
animationData: animations[page],
|
|
555
|
+
}}
|
|
556
|
+
height={300}
|
|
557
|
+
width={300}
|
|
558
|
+
/>
|
|
559
|
+
);
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
Changing `options.animationData` reloads the animation into the same container,
|
|
563
|
+
so a `key` is not required. Keep the JSON modules stable: copying the data in
|
|
564
|
+
`render` (`animationData: { ...animations[page] }`) hands the component a new
|
|
565
|
+
object on every render and reloads the animation each time. If you do want to
|
|
566
|
+
start over — to replay an intro, for example — give the component a `key` so
|
|
567
|
+
React unmounts and remounts it:
|
|
568
|
+
|
|
569
|
+
```jsx
|
|
570
|
+
<Lottie key={page} options={{ ...defaultOptions, animationData: animations[page] }} />
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
Unmounting destroys the lottie-web instance, so only the visible page animates.
|
|
574
|
+
When the files are large, load them with `options.path` and fetch the JSON for
|
|
575
|
+
the next page ahead of time instead of shipping every animation in one bundle;
|
|
576
|
+
see [Loading animation data without bloating the bundle](#loading-animation-data-without-bloating-the-bundle).
|
|
577
|
+
|
|
578
|
+
### Server-side rendering
|
|
579
|
+
|
|
580
|
+
`<Lottie />` renders only a sized container element on the server; lottie-web is
|
|
581
|
+
imported but instantiated in `componentDidMount` only, so `renderToString` (and
|
|
582
|
+
Next.js/Gatsby prerendering) works and the animation starts after hydration:
|
|
583
|
+
|
|
584
|
+
```jsx
|
|
585
|
+
// server output: <div style="width:400px;height:400px;..."></div>
|
|
586
|
+
<Lottie options={defaultOptions} height={400} width={400} />
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
Importing the package outside a browser no longer throws
|
|
590
|
+
`ReferenceError: window is not defined`; lottie-web guards its DOM access at
|
|
591
|
+
module load. If your bundler still evaluates the player on the server, load the
|
|
592
|
+
component without SSR:
|
|
593
|
+
|
|
594
|
+
```jsx
|
|
595
|
+
// Next.js
|
|
596
|
+
import dynamic from 'next/dynamic';
|
|
597
|
+
|
|
598
|
+
const Lottie = dynamic(() => import('react-lottie'), { ssr: false });
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
Animations loaded from `options.path` are fetched by lottie-web after mount, so
|
|
602
|
+
nothing is requested during the server render. Avoid the hydration trap
|
|
603
|
+
described in [Animations and page navigation](#animations-and-page-navigation)
|
|
604
|
+
when the container is nested in a `<p>`.
|
|
605
|
+
|
|
606
|
+
### Animations and page navigation
|
|
607
|
+
|
|
608
|
+
react-lottie creates a lottie-web instance when the component mounts and calls
|
|
609
|
+
`destroy()` on unmount, so client-side navigation is safe as long as the page
|
|
610
|
+
really unmounts. A layout that renders every page at once (or keeps pages
|
|
611
|
+
mounted when switching tabs) keeps every animation running; mount only the
|
|
612
|
+
visible one.
|
|
613
|
+
|
|
614
|
+
One non-obvious trap on SSR frameworks such as Gatsby or Next.js: the wrapper is
|
|
615
|
+
a `div` by default, and a `div` inside a `p` is invalid HTML. The browser moves
|
|
616
|
+
the `div` out of the paragraph while parsing the server-rendered page, React
|
|
617
|
+
reports a hydration mismatch (`validateDOMNesting`), and the animation node ends
|
|
618
|
+
up outside the page subtree. Navigating back and forth can then leave animation
|
|
619
|
+
nodes behind. Render the animation with `as="span"` (issue #73) or move it
|
|
620
|
+
outside the paragraph:
|
|
621
|
+
|
|
622
|
+
```jsx
|
|
623
|
+
<p>
|
|
624
|
+
Text <Lottie as="span" options={defaultOptions} /> more text
|
|
625
|
+
</p>
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
If animations still accumulate, confirm that each page unmounts (React DevTools
|
|
629
|
+
shows the component tree changing), and pause off-screen instances as described
|
|
630
|
+
in [Performance on iOS and low-end devices](#performance-on-ios-and-low-end-devices).
|
|
631
|
+
|
|
301
632
|
### Imperative control
|
|
302
633
|
|
|
303
634
|
A `ref` to the component exposes `play()`, `pause()`, `stop()`,
|
|
@@ -329,7 +660,7 @@ the object representing the animation settings that will be instantiated by body
|
|
|
329
660
|
>
|
|
330
661
|
>**path** *optional* — a URL (or path) to a JSON animation file. Mutually exclusive with `animationData`.
|
|
331
662
|
>
|
|
332
|
-
>**renderer** *optional* [default: `svg`]
|
|
663
|
+
>**renderer** *optional* [default: `svg`] — `svg`, `canvas` or `html`. See [Performance on iOS and low-end devices](#performance-on-ios-and-low-end-devices).
|
|
333
664
|
>
|
|
334
665
|
>**rendererSettings** *required*
|
|
335
666
|
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,35 @@ var segmentsAreEqual = function segmentsAreEqual(a, b) {
|
|
|
32
32
|
return value === b[index];
|
|
33
33
|
});
|
|
34
34
|
};
|
|
35
|
+
|
|
36
|
+
/* lottie-web crashes deep inside its renderer with "Cannot read property
|
|
37
|
+
'length' of undefined" when the data is not a plain animation object. Accept
|
|
38
|
+
the shapes users actually pass (a namespace import, a frozen ESM object) and
|
|
39
|
+
fail with an actionable message for the rest (#24, #44, #65). */
|
|
40
|
+
var _normalizeAnimationData = function normalizeAnimationData(animationData, path) {
|
|
41
|
+
if (animationData === undefined || animationData === null) {
|
|
42
|
+
if (!path) {
|
|
43
|
+
throw new Error('[react-lottie] options must include `animationData` (the imported JSON) ' + 'or `path` (a URL to the JSON file).');
|
|
44
|
+
}
|
|
45
|
+
return animationData;
|
|
46
|
+
}
|
|
47
|
+
if (typeof animationData === 'string') {
|
|
48
|
+
throw new Error('[react-lottie] options.animationData must be an object, not a string. ' + 'Pass a file path or URL as options.path instead, or call JSON.parse() ' + 'on JSON text first.');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* `import * as animationData` wraps the payload in a `default` property,
|
|
52
|
+
which lottie-web cannot read (#24, #65). */
|
|
53
|
+
if (!Array.isArray(animationData.layers) && animationData["default"]) {
|
|
54
|
+
return _normalizeAnimationData(animationData["default"], path);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* lottie-web annotates the loaded animation (`__complete`), which throws on
|
|
58
|
+
the frozen objects produced by strict ESM bundlers (#24). */
|
|
59
|
+
if (Object.isFrozen(animationData)) {
|
|
60
|
+
return JSON.parse(JSON.stringify(animationData));
|
|
61
|
+
}
|
|
62
|
+
return animationData;
|
|
63
|
+
};
|
|
35
64
|
var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
36
65
|
function Lottie() {
|
|
37
66
|
var _this;
|
|
@@ -71,7 +100,7 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
71
100
|
whether either actually changed. */
|
|
72
101
|
this.animationData = animationData;
|
|
73
102
|
this.colorFilters = colorFilters;
|
|
74
|
-
var filteredAnimationData = (0, _colorFilters.applyColorFilters)(animationData, colorFilters);
|
|
103
|
+
var filteredAnimationData = (0, _colorFilters.applyColorFilters)(_normalizeAnimationData(animationData, options.path), colorFilters);
|
|
75
104
|
this.options = {
|
|
76
105
|
container: this.el,
|
|
77
106
|
renderer: renderer,
|
|
@@ -140,7 +169,7 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
140
169
|
/* `options` is caller-owned and knows nothing about the wrapper, so the
|
|
141
170
|
ref (already pointing at the newly rendered node) wins. */
|
|
142
171
|
this.options.container = this.el;
|
|
143
|
-
this.options.animationData = (0, _colorFilters.applyColorFilters)(this.props.options.animationData, this.props.colorFilters);
|
|
172
|
+
this.options.animationData = (0, _colorFilters.applyColorFilters)(_normalizeAnimationData(this.props.options.animationData, this.props.options.path), this.props.colorFilters);
|
|
144
173
|
this.anim = _lottieWeb["default"].loadAnimation(this.options);
|
|
145
174
|
this.registerEvents(this.props.eventListeners);
|
|
146
175
|
|
|
@@ -179,7 +208,8 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
179
208
|
value: function componentWillUnmount() {
|
|
180
209
|
this.deRegisterEvents(this.props.eventListeners);
|
|
181
210
|
this.destroy();
|
|
182
|
-
|
|
211
|
+
/* A failed loadAnimation (e.g. invalid animationData) leaves no options. */
|
|
212
|
+
if (this.options) this.options.animationData = null;
|
|
183
213
|
this.anim = null;
|
|
184
214
|
}
|
|
185
215
|
}, {
|