react-lottie 2.3.3 → 2.4.1
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 +22 -0
- package/README.md +276 -6
- package/dist/index.js +34 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
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.4.1](https://github.com/chenqingspring/react-lottie/compare/v2.4.0...v2.4.1) (2026-11-08)
|
|
6
|
+
|
|
7
|
+
### Documentation
|
|
8
|
+
|
|
9
|
+
* explain that `rendererSettings` belongs inside `options`, not on `<Lottie />`, and how `preserveAspectRatio` fits (`meet`), crops (`slice`) or stretches (`none`) an animation ([#98](https://github.com/chenqingspring/react-lottie/issues/98))
|
|
10
|
+
* explain why an embedded base64 image can raise `Invalid or unexpected token` from an `eval` inside a lottie expression, and how to find the offending expression ([#88](https://github.com/chenqingspring/react-lottie/issues/88))
|
|
11
|
+
* document taking a presentational animation out of the tab order and exposing it to screen readers with `tabIndex`, `ariaRole` and `ariaLabel` ([#130](https://github.com/chenqingspring/react-lottie/issues/130))
|
|
12
|
+
* add a Storybook demo of the `preserveAspectRatio` modes on a square animation in a wide container
|
|
13
|
+
|
|
14
|
+
## [2.4.0](https://github.com/chenqingspring/react-lottie/compare/v2.3.3...v2.4.0) (2026-11-08)
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* apply `options.locationHref` before loading, so Safari keeps the masks, mattes, gradients and filters that lottie-web bakes into `url(#id)` references when the page uses a `<base>` tag or is served from a sub-path; changing it reloads the animation ([#111](https://github.com/chenqingspring/react-lottie/issues/111))
|
|
19
|
+
* expose the container `margin` as a prop, accepting any CSS `margin` value or a number of pixels (default `0 auto`), applied before `style` so an explicit `style.margin` still wins ([#107](https://github.com/chenqingspring/react-lottie/issues/107))
|
|
20
|
+
|
|
21
|
+
### Documentation
|
|
22
|
+
|
|
23
|
+
* explain how to load animation data from a URL and why a URL belongs in `options.path`, not `animationData` ([#106](https://github.com/chenqingspring/react-lottie/issues/106))
|
|
24
|
+
* explain the default click-to-pause behaviour and the `isClickToPauseDisabled` opt-out ([#110](https://github.com/chenqingspring/react-lottie/issues/110))
|
|
25
|
+
* state that the `componentWill*` lifecycles deprecated in React 16.3 and removed in React 17 are not used ([#112](https://github.com/chenqingspring/react-lottie/issues/112), [#119](https://github.com/chenqingspring/react-lottie/issues/119))
|
|
26
|
+
|
|
5
27
|
## [2.3.3](https://github.com/chenqingspring/react-lottie/compare/v2.3.2...v2.3.3) (2026-11-08)
|
|
6
28
|
|
|
7
29
|
### Documentation
|
package/README.md
CHANGED
|
@@ -108,6 +108,13 @@ React 16.8 or newer, including React 17, React 18 and React 19. The
|
|
|
108
108
|
`--force`. The test suite runs against React 18; the component uses plain class
|
|
109
109
|
components and works with React 17 and React 19 as well.
|
|
110
110
|
|
|
111
|
+
The component is a class, but it only uses the lifecycles React still supports
|
|
112
|
+
(`componentDidMount`, `componentDidUpdate`, `componentWillUnmount`). The
|
|
113
|
+
`componentWill*` methods that React 16.3 deprecated and React 17 stopped
|
|
114
|
+
calling were removed in 2.0.0, so React 17 and newer do not warn about legacy
|
|
115
|
+
lifecycles or skip the data/`path` reload ([#77](https://github.com/chenqingspring/react-lottie/issues/77),
|
|
116
|
+
[#119](https://github.com/chenqingspring/react-lottie/issues/119)).
|
|
117
|
+
|
|
111
118
|
## Local development
|
|
112
119
|
|
|
113
120
|
Run the Storybook stories with `npm start` (port 9010) and the test suite with
|
|
@@ -187,6 +194,53 @@ belongs in `options.path`; a namespace import
|
|
|
187
194
|
(`import * as animationData`) is unwrapped automatically but the default import
|
|
188
195
|
above is preferred.
|
|
189
196
|
|
|
197
|
+
### Loading animation data from a URL
|
|
198
|
+
|
|
199
|
+
Put the URL in `options.path`, not `options.animationData`. `animationData` is
|
|
200
|
+
the parsed JSON object; lottie-web cannot fetch a string, so react-lottie throws
|
|
201
|
+
an explanatory error if you pass one (issue #106):
|
|
202
|
+
|
|
203
|
+
```jsx
|
|
204
|
+
const defaultOptions = {
|
|
205
|
+
path: 'https://someurl.com/animationData.json',
|
|
206
|
+
loop: true,
|
|
207
|
+
autoplay: true,
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
<Lottie options={defaultOptions} width="1293px" height="300px" />
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
`path` accepts an absolute URL, a site-root path or a relative path. lottie-web
|
|
214
|
+
fetches it after mount (nothing is requested during server rendering), and
|
|
215
|
+
changing `path` reloads the animation. Because lottie-web owns the request,
|
|
216
|
+
`colorFilters` is not applied — fetch the JSON yourself and pass the parsed
|
|
217
|
+
object as `animationData` if you need to recolor it or send request headers:
|
|
218
|
+
|
|
219
|
+
```jsx
|
|
220
|
+
import { useEffect, useState } from 'react';
|
|
221
|
+
|
|
222
|
+
function RemoteAnimation() {
|
|
223
|
+
const [animationData, setAnimationData] = useState(null);
|
|
224
|
+
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
let cancelled = false;
|
|
227
|
+
fetch('https://someurl.com/animationData.json')
|
|
228
|
+
.then((response) => response.json())
|
|
229
|
+
.then((data) => { if (!cancelled) setAnimationData(data); });
|
|
230
|
+
return () => { cancelled = true; };
|
|
231
|
+
}, []);
|
|
232
|
+
|
|
233
|
+
if (!animationData) return null;
|
|
234
|
+
|
|
235
|
+
return (
|
|
236
|
+
<Lottie options={{ animationData, loop: true, autoplay: true }} height={300} />
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
See [Loading animation data without bloating the bundle](#loading-animation-data-without-bloating-the-bundle)
|
|
242
|
+
for the bundle-size trade-offs between these approaches.
|
|
243
|
+
|
|
190
244
|
### Loading animation data without bloating the bundle
|
|
191
245
|
|
|
192
246
|
A static import like `import animationData from './pinjump.json'` (the example
|
|
@@ -309,6 +363,35 @@ keeps the animation self-contained, but it inflates the file by roughly a third
|
|
|
309
363
|
and prevents the browser from caching the image separately, so prefer external
|
|
310
364
|
images for anything large.
|
|
311
365
|
|
|
366
|
+
### `Invalid or unexpected token` with embedded images
|
|
367
|
+
|
|
368
|
+
Embedded base64 images do work: an asset with `"e": 1` and a `p` value that
|
|
369
|
+
starts with `data:image/png;base64,` is decoded like any other image, and the
|
|
370
|
+
layer only has to reference it through `refId`.
|
|
371
|
+
|
|
372
|
+
The `Uncaught SyntaxError: Invalid or unexpected token` thrown from
|
|
373
|
+
`eval (eval at initiateExpression ...)` is not about the image. It comes from an
|
|
374
|
+
**expression** inside the animation. lottie-web compiles expressions with
|
|
375
|
+
`eval` when the animation loads. Newer After Effects versions can save an
|
|
376
|
+
expression in an encoded `@JSXBIN@…` form, which lottie-web cannot parse, so
|
|
377
|
+
the `eval` throws while the layer's effects are prepared
|
|
378
|
+
(`IImageElement.prepareProperties`). The same error can appear in animations
|
|
379
|
+
with no images at all.
|
|
380
|
+
|
|
381
|
+
Fixes, in order of preference:
|
|
382
|
+
|
|
383
|
+
- Remove the expressions in After Effects, or bake them to keyframes
|
|
384
|
+
(**Animation → Keyframe Assistant → Convert Expression to Keyframes**), then
|
|
385
|
+
export again. The animation keeps looking the same without runtime
|
|
386
|
+
evaluation.
|
|
387
|
+
- Keep the expression only if it is plain JavaScript, and make sure a Content
|
|
388
|
+
Security Policy is not blocking `eval` (it needs `'unsafe-eval'`). Otherwise
|
|
389
|
+
move that behaviour out of the animation.
|
|
390
|
+
- If the expression is not needed for playback, alias `lottie-web` to one of
|
|
391
|
+
the [light builds](#shrinking-the-lottie-web-bundle): they have no expression
|
|
392
|
+
engine and skip expressions instead of throwing. They skip the effect's
|
|
393
|
+
behaviour too, so only do this when the visual result is acceptable.
|
|
394
|
+
|
|
312
395
|
### Shrinking the lottie-web bundle
|
|
313
396
|
|
|
314
397
|
react-lottie imports the full `lottie-web` player (299 kB minified, 611 kB
|
|
@@ -419,6 +502,94 @@ If a reduced file still drops frames, profile it: record a timeline in Safari's
|
|
|
419
502
|
Web Inspector while the animation plays and check whether the time goes to
|
|
420
503
|
lottie-web's frame update or to the browser painting and compositing the layers.
|
|
421
504
|
|
|
505
|
+
### Fit or crop an animation (preserveAspectRatio)
|
|
506
|
+
|
|
507
|
+
The SVG that lottie-web generates has its own `viewBox`, and the browser scales
|
|
508
|
+
it to the container according to `preserveAspectRatio`. lottie-web's default is
|
|
509
|
+
`xMidYMid meet`, which letterboxes the animation. Use `xMidYMid slice` to fill
|
|
510
|
+
the container and crop the overflow instead, or `none` to stretch it.
|
|
511
|
+
|
|
512
|
+
`rendererSettings` belongs **inside `options`**, next to `animationData` or
|
|
513
|
+
`path`. A `rendererSettings` prop on `<Lottie />` itself is ignored, because the
|
|
514
|
+
component only forwards `options` to `lottie.loadAnimation()`:
|
|
515
|
+
|
|
516
|
+
```jsx
|
|
517
|
+
const defaultOptions = {
|
|
518
|
+
animationData,
|
|
519
|
+
loop: true,
|
|
520
|
+
autoplay: true,
|
|
521
|
+
rendererSettings: {
|
|
522
|
+
preserveAspectRatio: 'xMidYMid slice',
|
|
523
|
+
},
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
// A wide box for a square animation, so `slice` has something to crop.
|
|
527
|
+
<Lottie options={defaultOptions} height={200} width={400} />
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Two things make a working setting look broken:
|
|
531
|
+
|
|
532
|
+
- `meet` and `slice` render identically when the container has the same aspect
|
|
533
|
+
ratio as the animation. Sizing a square animation with `height={400}
|
|
534
|
+
width={400}` leaves nothing to crop or letterbox.
|
|
535
|
+
- The value is applied when the animation loads. Changing
|
|
536
|
+
`options.rendererSettings` on a mounted component does not re-apply it;
|
|
537
|
+
remount the animation (or change its `key`) to pick up a new value.
|
|
538
|
+
|
|
539
|
+
If the `<svg>` in the inspector still lacks `preserveAspectRatio`, check what
|
|
540
|
+
you pass as `options.animationData`. An ES module namespace
|
|
541
|
+
(`import * as animationData`) is unwrapped for you, but any payload lottie-web
|
|
542
|
+
cannot read leaves it without a `viewBox`, so the attribute has nothing to
|
|
543
|
+
scale. See [Usage](#usage).
|
|
544
|
+
|
|
545
|
+
The canvas renderer reads `preserveAspectRatio` too.
|
|
546
|
+
|
|
547
|
+
### Masks are missing in Safari
|
|
548
|
+
|
|
549
|
+
Safari resolves the `url(#…)` references that lottie-web generates for masks,
|
|
550
|
+
mattes, gradients and filters against the document's base URL. When the page
|
|
551
|
+
has a `<base href>` tag, or the animation is served from a path the browser
|
|
552
|
+
resolves differently, those references point at the wrong document and Safari
|
|
553
|
+
renders the animation without its masks. Chrome and Firefox usually still find
|
|
554
|
+
them.
|
|
555
|
+
|
|
556
|
+
lottie-web's documented workaround is to call `lottie.setLocationHref()` before
|
|
557
|
+
the animation is generated. react-lottie exposes it as `options.locationHref`:
|
|
558
|
+
|
|
559
|
+
```jsx
|
|
560
|
+
const defaultOptions = {
|
|
561
|
+
animationData,
|
|
562
|
+
loop: true,
|
|
563
|
+
autoplay: true,
|
|
564
|
+
locationHref: window.location.href,
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
<Lottie options={defaultOptions} height={400} width={400} />
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
Pass the URL the page is actually served from, without the `#` fragment.
|
|
571
|
+
lottie-web joins the value with `#<id>` when it builds the references, so a
|
|
572
|
+
fragment produces broken URLs. The value is global to lottie-web, so pass the
|
|
573
|
+
same `locationHref` to every `<Lottie />` on the page. Changing it regenerates
|
|
574
|
+
the animation, because the base URL is baked into the generated markup.
|
|
575
|
+
|
|
576
|
+
If you already import lottie-web yourself, calling the function directly works
|
|
577
|
+
too, as long as the bundler resolves it to the same copy react-lottie uses:
|
|
578
|
+
|
|
579
|
+
```js
|
|
580
|
+
import lottie from 'lottie-web';
|
|
581
|
+
|
|
582
|
+
lottie.setLocationHref(window.location.href);
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
Run that before the first animation mounts, for example at application startup.
|
|
586
|
+
|
|
587
|
+
If the masks are still missing with the correct href, the artwork is the likely
|
|
588
|
+
cause: complex masks and alpha mattes are the least reliable part of the SVG
|
|
589
|
+
renderer. Compare with the [canvas renderer](#performance-on-ios-and-low-end-devices),
|
|
590
|
+
or open the same JSON in lottie-web's own preview to confirm the problem is
|
|
591
|
+
renderer-level rather than a react-lottie bug.
|
|
592
|
+
|
|
422
593
|
### Play on hover
|
|
423
594
|
|
|
424
595
|
`eventListeners` takes lottie-web animation events (`complete`, `loopComplete`,
|
|
@@ -467,6 +638,42 @@ export default class HoverLottie extends React.Component {
|
|
|
467
638
|
|
|
468
639
|
```
|
|
469
640
|
|
|
641
|
+
### Click to pause
|
|
642
|
+
|
|
643
|
+
Clicking or tapping the animation pauses it, and clicking again resumes it.
|
|
644
|
+
This is on by default: the container also has `ariaRole="button"`, so an
|
|
645
|
+
animation that looks decorative is still an interactive control (issue
|
|
646
|
+
[#110](https://github.com/chenqingspring/react-lottie/issues/110)).
|
|
647
|
+
|
|
648
|
+
Disable it when the animation is decorative, or when you want a click to do
|
|
649
|
+
something else:
|
|
650
|
+
|
|
651
|
+
```jsx
|
|
652
|
+
<Lottie options={defaultOptions} isClickToPauseDisabled />
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
A decorative animation should also leave the tab order. Pair
|
|
656
|
+
`isClickToPauseDisabled` with `tabIndex={-1}` so keyboard users do not land on
|
|
657
|
+
an animation they cannot interact with (issue
|
|
658
|
+
[#130](https://github.com/chenqingspring/react-lottie/issues/130)):
|
|
659
|
+
|
|
660
|
+
```jsx
|
|
661
|
+
<Lottie options={defaultOptions} isClickToPauseDisabled tabIndex={-1} />
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
The component has no `onClick` prop. Put your handler on a wrapper element
|
|
665
|
+
instead; the click bubbles from the animation container to the wrapper:
|
|
666
|
+
|
|
667
|
+
```jsx
|
|
668
|
+
<div onClick={() => openDetails()}>
|
|
669
|
+
<Lottie options={defaultOptions} isClickToPauseDisabled />
|
|
670
|
+
</div>
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
Without `isClickToPauseDisabled` both run: playback toggles and the wrapper's
|
|
674
|
+
handler still fires after it. Leave the prop out when you want click-to-pause as
|
|
675
|
+
well.
|
|
676
|
+
|
|
470
677
|
### Play a segment
|
|
471
678
|
|
|
472
679
|
Pass `segments` to play a frame range instead of the whole animation. The
|
|
@@ -525,7 +732,7 @@ The container is a `div` by default, which is not a valid child of `<p>`. Pass
|
|
|
525
732
|
|
|
526
733
|
```jsx
|
|
527
734
|
<p>
|
|
528
|
-
Text <Lottie as="span" options={defaultOptions} ariaRole="img" /> more text
|
|
735
|
+
Text <Lottie as="span" options={defaultOptions} ariaRole="img" tabIndex={-1} /> more text
|
|
529
736
|
</p>
|
|
530
737
|
```
|
|
531
738
|
|
|
@@ -662,7 +869,9 @@ the object representing the animation settings that will be instantiated by body
|
|
|
662
869
|
>
|
|
663
870
|
>**renderer** *optional* [default: `svg`] — `svg`, `canvas` or `html`. See [Performance on iOS and low-end devices](#performance-on-ios-and-low-end-devices).
|
|
664
871
|
>
|
|
665
|
-
>**rendererSettings** *
|
|
872
|
+
>**rendererSettings** *optional* — settings forwarded to lottie-web's renderer, such as `preserveAspectRatio`, `progressiveLoad`, `className` and `id`. Must be inside `options`, not a prop on `<Lottie />`. Read once when the animation loads. See [Fit or crop an animation](#fit-or-crop-an-animation-preserveaspectratio).
|
|
873
|
+
>
|
|
874
|
+
>**locationHref** *optional* — the base URL lottie-web writes into its SVG mask, matte, gradient and filter references, applied with `setLocationHref()` before the animation is generated. Use it when Safari drops masks because of a `<base>` tag. See [Masks are missing in Safari](#masks-are-missing-in-safari).
|
|
666
875
|
|
|
667
876
|
**colorFilters** *optional* [default: `[]`]
|
|
668
877
|
|
|
@@ -677,6 +886,17 @@ pixel value for containers width.
|
|
|
677
886
|
|
|
678
887
|
pixel value for containers height.
|
|
679
888
|
|
|
889
|
+
**margin** *optional* [default: `0 auto`]
|
|
890
|
+
|
|
891
|
+
Margin of the container. Accepts any CSS `margin` value (`'20px'`,
|
|
892
|
+
`'10px auto'`, `'1rem 2rem'`) or a number of pixels. Use it instead of
|
|
893
|
+
`style.margin` when the default `0 auto` misbehaves in a browser (issue #107).
|
|
894
|
+
`style` is merged after this prop, so an explicit `style.margin` still wins.
|
|
895
|
+
|
|
896
|
+
```jsx
|
|
897
|
+
<Lottie options={defaultOptions} margin="10px auto" />
|
|
898
|
+
```
|
|
899
|
+
|
|
680
900
|
**isStopped** *optional* [default: `false`]
|
|
681
901
|
|
|
682
902
|
Stops the animation and resets it to the first frame. Setting it back to `false`
|
|
@@ -726,7 +946,11 @@ eventListeners=[
|
|
|
726
946
|
```
|
|
727
947
|
|
|
728
948
|
**isClickToPauseDisabled** *optional* [default: `false`]
|
|
729
|
-
|
|
949
|
+
|
|
950
|
+
When this prop is left unspecified or is set to `false`, animations are paused
|
|
951
|
+
or resumed when a user clicks or taps them. If you do not want this behaviour,
|
|
952
|
+
set this prop to `true`. See [Click to pause](#click-to-pause) for a custom
|
|
953
|
+
click handler.
|
|
730
954
|
|
|
731
955
|
**ariaRole** *optional* [default: `button`]
|
|
732
956
|
|
|
@@ -743,12 +967,14 @@ Accessible name of the container.
|
|
|
743
967
|
|
|
744
968
|
**style** *optional*
|
|
745
969
|
|
|
746
|
-
Extra inline styles merged onto the container, after the `width`, `height
|
|
747
|
-
layout defaults. Use it to override `overflow
|
|
970
|
+
Extra inline styles merged onto the container, after the `width`, `height`,
|
|
971
|
+
`margin` and layout defaults. Use it to override `overflow`, for example.
|
|
748
972
|
|
|
749
973
|
**tabIndex** *optional* [default: `0`]
|
|
750
974
|
Tab order of the rendered container. Pass `-1` for a purely presentational
|
|
751
|
-
animation that should not receive keyboard focus
|
|
975
|
+
animation that should not receive keyboard focus (issue
|
|
976
|
+
[#130](https://github.com/chenqingspring/react-lottie/issues/130)); combine it
|
|
977
|
+
with `isClickToPauseDisabled` as shown in [Click to pause](#click-to-pause).
|
|
752
978
|
|
|
753
979
|
**as** *optional* [default: `div`]
|
|
754
980
|
|
|
@@ -757,6 +983,50 @@ Element or component rendered as the animation container. Use `as="span"` when
|
|
|
757
983
|
custom component must forward its `ref` to a DOM element. See
|
|
758
984
|
[Render inline inside a paragraph](#render-inline-inside-a-paragraph).
|
|
759
985
|
|
|
986
|
+
## Hooks and alternatives
|
|
987
|
+
|
|
988
|
+
`react-lottie` is deliberately a thin class component over lottie-web. Its
|
|
989
|
+
public API is the imperative instance on a `ref` (`play`, `pause`,
|
|
990
|
+
`goToAndStop`, `goToAndPlay`, `playSegments`), so replacing the class with a
|
|
991
|
+
hooks-only component would break every existing app without changing what is
|
|
992
|
+
rendered. You do not need hooks to drive it declaratively, though: changing
|
|
993
|
+
`options.animationData` or `options.path` reloads the animation, and changes to
|
|
994
|
+
`segments`, `isPaused`, `isStopped`, `speed`, `direction` and `colorFilters`
|
|
995
|
+
are applied to the running instance. A function component can hold the state
|
|
996
|
+
around it (issue #117):
|
|
997
|
+
|
|
998
|
+
```jsx
|
|
999
|
+
import React, { useState } from 'react'
|
|
1000
|
+
import Lottie from 'react-lottie';
|
|
1001
|
+
import animationData from './pinjump.json'
|
|
1002
|
+
|
|
1003
|
+
export default function Player() {
|
|
1004
|
+
const [segment, setSegment] = useState([0, 30]);
|
|
1005
|
+
const options = { animationData, loop: true };
|
|
1006
|
+
|
|
1007
|
+
return (
|
|
1008
|
+
<div>
|
|
1009
|
+
<Lottie options={options} segments={segment} width={240} height={240} />
|
|
1010
|
+
<button onClick={() => setSegment([30, 60])}>next part</button>
|
|
1011
|
+
</div>
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
If you specifically want a hook-first API, use one of these wrappers instead:
|
|
1017
|
+
|
|
1018
|
+
* [react-lottie-player](https://github.com/mifi/react-lottie-player) — the
|
|
1019
|
+
`useLottie` hook, with `path` and `animationData` support (v2.1.0, last
|
|
1020
|
+
published July 2024).
|
|
1021
|
+
* [lottie-react](https://github.com/Gamote/lottie-react) — actively
|
|
1022
|
+
maintained, hooks-based API (v3.1.2).
|
|
1023
|
+
* [@lottiefiles/react-lottie-player](https://github.com/LottieFiles/lottie-react)
|
|
1024
|
+
— LottieFiles' official wrapper, for LottieFiles-specific features
|
|
1025
|
+
(v3.6.0).
|
|
1026
|
+
|
|
1027
|
+
All of them wrap the same lottie-web runtime, so switching mostly changes the
|
|
1028
|
+
component API rather than how the animation is rendered.
|
|
1029
|
+
|
|
760
1030
|
## Related Projects
|
|
761
1031
|
|
|
762
1032
|
* [lottie-web](https://github.com/airbnb/lottie-web) react-lottie is a wrapper of lottie-web
|
package/dist/index.js
CHANGED
|
@@ -100,6 +100,7 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
100
100
|
whether either actually changed. */
|
|
101
101
|
this.animationData = animationData;
|
|
102
102
|
this.colorFilters = colorFilters;
|
|
103
|
+
this.locationHref = options.locationHref;
|
|
103
104
|
var filteredAnimationData = (0, _colorFilters.applyColorFilters)(_normalizeAnimationData(animationData, options.path), colorFilters);
|
|
104
105
|
this.options = {
|
|
105
106
|
container: this.el,
|
|
@@ -117,6 +118,10 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
117
118
|
if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production' && Array.isArray(colorFilters) && colorFilters.length > 0 && !animationData) {
|
|
118
119
|
console.warn('[react-lottie] colorFilters requires options.animationData; ' + 'animations loaded from options.path are not recolored.');
|
|
119
120
|
}
|
|
121
|
+
|
|
122
|
+
/* Must happen before the animation is generated: lottie-web bakes the base
|
|
123
|
+
URL into its mask, matte, gradient and filter references (issue #111). */
|
|
124
|
+
this.setLocationHref(options);
|
|
120
125
|
this.anim = _lottieWeb["default"].loadAnimation(this.options);
|
|
121
126
|
this.registerEvents(eventListeners);
|
|
122
127
|
this.setSpeed();
|
|
@@ -151,10 +156,13 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
151
156
|
var dataChanged = this.animationData !== this.props.options.animationData;
|
|
152
157
|
var pathChanged = this.options.path !== this.props.options.path;
|
|
153
158
|
var colorFiltersChanged = !(0, _colorFilters.colorFiltersAreEqual)(this.colorFilters, this.props.colorFilters);
|
|
159
|
+
/* lottie-web bakes the base URL into each generated `url(#id)` reference,
|
|
160
|
+
so a new href only takes effect when the animation is generated again. */
|
|
161
|
+
var locationHrefChanged = this.locationHref !== this.props.options.locationHref;
|
|
154
162
|
/* The wrapper element is part of lottie-web's configuration, so a new
|
|
155
163
|
element means the animation has to be bound to the new node. */
|
|
156
164
|
var containerChanged = prevProps.as !== this.props.as;
|
|
157
|
-
if (dataChanged || pathChanged || colorFiltersChanged || containerChanged) {
|
|
165
|
+
if (dataChanged || pathChanged || colorFiltersChanged || locationHrefChanged || containerChanged) {
|
|
158
166
|
var currentFrame = this.anim ? this.anim.currentFrame : 0;
|
|
159
167
|
var wasPaused = this.anim ? this.anim.isPaused : true;
|
|
160
168
|
/* lottie-web cannot recolor a loaded animation and cannot move one to
|
|
@@ -165,11 +173,13 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
165
173
|
this.destroy();
|
|
166
174
|
this.animationData = this.props.options.animationData;
|
|
167
175
|
this.colorFilters = this.props.colorFilters;
|
|
176
|
+
this.locationHref = this.props.options.locationHref;
|
|
168
177
|
this.options = _objectSpread(_objectSpread({}, this.options), this.props.options);
|
|
169
178
|
/* `options` is caller-owned and knows nothing about the wrapper, so the
|
|
170
179
|
ref (already pointing at the newly rendered node) wins. */
|
|
171
180
|
this.options.container = this.el;
|
|
172
181
|
this.options.animationData = (0, _colorFilters.applyColorFilters)(_normalizeAnimationData(this.props.options.animationData, this.props.options.path), this.props.colorFilters);
|
|
182
|
+
this.setLocationHref(this.options);
|
|
173
183
|
this.anim = _lottieWeb["default"].loadAnimation(this.options);
|
|
174
184
|
this.registerEvents(this.props.eventListeners);
|
|
175
185
|
|
|
@@ -231,6 +241,22 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
231
241
|
value: function setSubframe() {
|
|
232
242
|
this.anim.setSubframe(this.props.isSubframe);
|
|
233
243
|
}
|
|
244
|
+
|
|
245
|
+
/* lottie-web writes its internal mask, matte, gradient and filter references
|
|
246
|
+
as `url(<locationHref>#id)`. Safari resolves them against the page's base
|
|
247
|
+
URL, so a `<base href>` (or a mismatched asset URL) makes it drop the
|
|
248
|
+
masks; other browsers are more forgiving. lottie-web's documented fix is
|
|
249
|
+
the global `setLocationHref()`, which has to run before the animation is
|
|
250
|
+
generated (issue #111). Passing `options.locationHref` lets callers do
|
|
251
|
+
that without importing lottie-web themselves, which also works when the
|
|
252
|
+
bundler gives them a different copy of the player. */
|
|
253
|
+
}, {
|
|
254
|
+
key: "setLocationHref",
|
|
255
|
+
value: function setLocationHref(options) {
|
|
256
|
+
if (options.locationHref != null) {
|
|
257
|
+
_lottieWeb["default"].setLocationHref(options.locationHref);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
234
260
|
}, {
|
|
235
261
|
key: "play",
|
|
236
262
|
value: function play() {
|
|
@@ -303,6 +329,7 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
303
329
|
var _this$props2 = this.props,
|
|
304
330
|
width = _this$props2.width,
|
|
305
331
|
height = _this$props2.height,
|
|
332
|
+
margin = _this$props2.margin,
|
|
306
333
|
ariaRole = _this$props2.ariaRole,
|
|
307
334
|
ariaLabel = _this$props2.ariaLabel,
|
|
308
335
|
isClickToPauseDisabled = _this$props2.isClickToPauseDisabled,
|
|
@@ -322,7 +349,9 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
|
|
|
322
349
|
width: getSize(width),
|
|
323
350
|
height: getSize(height),
|
|
324
351
|
overflow: 'hidden',
|
|
325
|
-
margin
|
|
352
|
+
/* `margin` is a prop so callers do not have to fight the default through
|
|
353
|
+
`style` on browsers where centring with `0 auto` misbehaves (#107). */
|
|
354
|
+
margin: getSize(margin),
|
|
326
355
|
outline: 'none'
|
|
327
356
|
}, this.props.style);
|
|
328
357
|
var onClickHandler = isClickToPauseDisabled ? function () {
|
|
@@ -357,6 +386,7 @@ Lottie.propTypes = {
|
|
|
357
386
|
})),
|
|
358
387
|
height: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
|
|
359
388
|
width: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
|
|
389
|
+
margin: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
|
|
360
390
|
isStopped: _propTypes["default"].bool,
|
|
361
391
|
isPaused: _propTypes["default"].bool,
|
|
362
392
|
speed: _propTypes["default"].number,
|
|
@@ -383,5 +413,6 @@ Lottie.defaultProps = {
|
|
|
383
413
|
isClickToPauseDisabled: false,
|
|
384
414
|
title: '',
|
|
385
415
|
tabIndex: 0,
|
|
386
|
-
as: 'div'
|
|
416
|
+
as: 'div',
|
|
417
|
+
margin: '0 auto'
|
|
387
418
|
};
|