react-lottie 2.5.0 → 2.5.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 CHANGED
@@ -2,6 +2,17 @@
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.5.1](https://github.com/chenqingspring/react-lottie/compare/v2.5.0...v2.5.1) (2026-11-13)
6
+
7
+ ### Bug Fixes
8
+
9
+ * regenerate the animation when `options.renderer` changes, so a mounted component can switch between the `svg`, `canvas` and `html` engines and keeps its current frame and play/pause state; dropping the key falls back to `svg` (a change used to be silently ignored)
10
+
11
+ ### Documentation
12
+
13
+ * document switching `options.renderer` on a mounted component, and that a light `lottie-web` build registers one renderer only
14
+ * Storybook demo `lottie-renderer` with a live `svg` / `canvas` toggle next to both engines on their own component
15
+
5
16
  ## [2.5.0](https://github.com/chenqingspring/react-lottie/compare/v2.4.2...v2.5.0) (2026-11-10)
6
17
 
7
18
  ### Features
package/README.md CHANGED
@@ -472,7 +472,8 @@ In rough order of impact:
472
472
  3. **Compare the renderers.** `svg` (the default) is usually fastest for a few
473
473
  large shapes and stays crisp at any size. `canvas` avoids updating hundreds
474
474
  of DOM nodes and often wins for animations with many small shapes. Measure
475
- both on the target device.
475
+ both on the target device; a mounted component can switch between them
476
+ (see [Switch renderers](#switch-renderers-svg-canvas-html)).
476
477
  4. **Stop off-screen animations.** lottie-web drives every playing animation
477
478
  from the same `requestAnimationFrame` loop, so an animation scrolled out of
478
479
  view still costs a frame. Pause it with `isPaused`, or with `pause()` on a
@@ -573,6 +574,29 @@ const [mode, setMode] = useState('xMidYMid meet');
573
574
 
574
575
  The Storybook story `lottie-renderer-settings` demonstrates the same toggle.
575
576
 
577
+ ### Switch renderers (svg, canvas, html)
578
+
579
+ `renderer` selects the engine lottie-web uses to draw the animation and belongs
580
+ inside `options`. It defaults to `svg`; `canvas` and `html` are the other
581
+ choices.
582
+
583
+ ```jsx
584
+ const [renderer, setRenderer] = useState('svg');
585
+
586
+ <Lottie options={{ animationData, loop: true, autoplay: true, renderer }} height={200} width={200} />
587
+ <button onClick={() => setRenderer(renderer === 'svg' ? 'canvas' : 'svg')}>
588
+ switch renderer
589
+ </button>
590
+ ```
591
+
592
+ Changing `options.renderer` on a mounted component regenerates the animation
593
+ with the new engine and keeps the current frame and play/pause state, so the
594
+ toggle does not restart it. Dropping the key falls back to `svg` again. This
595
+ needs the full `lottie-web` player: a [light build](#shrinking-the-lottie-web-bundle)
596
+ registers a single renderer, so switching to another one fails to start.
597
+
598
+ The Storybook story `lottie-renderer` demonstrates the toggle.
599
+
576
600
  ### Masks are missing in Safari
577
601
 
578
602
  Safari resolves the `url(#…)` references that lottie-web generates for masks,
package/dist/index.js CHANGED
@@ -48,6 +48,12 @@ var rendererSettingsAreEqual = function rendererSettingsAreEqual(a, b) {
48
48
  });
49
49
  };
50
50
 
51
+ /* lottie-web falls back to the SVG renderer when `options.renderer` is absent,
52
+ so compare the value it actually ends up with. */
53
+ var rendererOf = function rendererOf(options) {
54
+ return options && options.renderer ? options.renderer : 'svg';
55
+ };
56
+
51
57
  /* lottie-web crashes deep inside its renderer with "Cannot read property
52
58
  'length' of undefined" when the data is not a plain animation object. Accept
53
59
  the shapes users actually pass (a namespace import, a frozen ESM object) and
@@ -117,6 +123,7 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
117
123
  this.colorFilters = colorFilters;
118
124
  this.locationHref = options.locationHref;
119
125
  this.rendererSettings = rendererSettings;
126
+ this.renderer = rendererOf(options);
120
127
  var filteredAnimationData = (0, _colorFilters.applyColorFilters)(_normalizeAnimationData(animationData, options.path), colorFilters);
121
128
  this.options = {
122
129
  container: this.el,
@@ -179,10 +186,14 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
179
186
  are read by lottie-web when it generates the renderer, so a change has to
180
187
  regenerate the animation too (issue #98). */
181
188
  var rendererSettingsChanged = !rendererSettingsAreEqual(this.rendererSettings, this.props.options.rendererSettings);
189
+ /* `renderer` selects the engine that generates the animation (`svg`,
190
+ `canvas` or `html`), so it can only change by loading again. A change
191
+ used to be ignored, which left the animation on the old engine. */
192
+ var rendererChanged = this.renderer !== rendererOf(this.props.options);
182
193
  /* The wrapper element is part of lottie-web's configuration, so a new
183
194
  element means the animation has to be bound to the new node. */
184
195
  var containerChanged = prevProps.as !== this.props.as;
185
- if (dataChanged || pathChanged || colorFiltersChanged || locationHrefChanged || rendererSettingsChanged || containerChanged) {
196
+ if (dataChanged || pathChanged || colorFiltersChanged || locationHrefChanged || rendererSettingsChanged || rendererChanged || containerChanged) {
186
197
  var currentFrame = this.anim ? this.anim.currentFrame : 0;
187
198
  var wasPaused = this.anim ? this.anim.isPaused : true;
188
199
  /* lottie-web cannot recolor a loaded animation and cannot move one to
@@ -195,13 +206,15 @@ var Lottie = exports["default"] = /*#__PURE__*/function (_React$Component) {
195
206
  this.colorFilters = this.props.colorFilters;
196
207
  this.locationHref = this.props.options.locationHref;
197
208
  this.rendererSettings = this.props.options.rendererSettings;
209
+ this.renderer = rendererOf(this.props.options);
198
210
  this.options = _objectSpread(_objectSpread({}, this.options), this.props.options);
199
211
  /* `options` is caller-owned and knows nothing about the wrapper, so the
200
212
  ref (already pointing at the newly rendered node) wins. */
201
213
  this.options.container = this.el;
202
214
  /* Spreading does not delete a key the caller dropped, so a removed
203
- rendererSettings would otherwise keep its old value. */
215
+ rendererSettings or renderer would otherwise keep its old value. */
204
216
  this.options.rendererSettings = this.props.options.rendererSettings;
217
+ this.options.renderer = this.renderer;
205
218
  this.options.animationData = (0, _colorFilters.applyColorFilters)(_normalizeAnimationData(this.props.options.animationData, this.props.options.path), this.props.colorFilters);
206
219
  this.setLocationHref(this.options);
207
220
  this.anim = _lottieWeb["default"].loadAnimation(this.options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-lottie",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "funding": "https://opencollective.com/react-lottie",
5
5
  "description": "lottie animation view for React",
6
6
  "repository": {