diff --git a/.changeset/breezy-fireants-tap.md b/.changeset/breezy-fireants-tap.md new file mode 100644 index 00000000..63cc5945 --- /dev/null +++ b/.changeset/breezy-fireants-tap.md @@ -0,0 +1,7 @@ +--- +'@dotlottie/react-player': patch +'@dotlottie/common': patch +'@dotlottie/player-component': patch +--- + +fix: loopComplete event does not fire after first cycle if direction is -1 diff --git a/packages/common/src/dotlottie-player.ts b/packages/common/src/dotlottie-player.ts index cfa5c4e2..f6ce31b4 100644 --- a/packages/common/src/dotlottie-player.ts +++ b/packages/common/src/dotlottie-player.ts @@ -1596,16 +1596,6 @@ export class DotLottieCommonPlayer { if (this.direction === -1) { this._container?.dispatchEvent(new Event(PlayerEvents.Complete)); if (!this.loop) this.setCurrentState(PlayerState.Completed); - - // Fix: First loopComplete is not fired by lottie-web when direction is -1 - if (this.currentState === PlayerState.Playing && this._loop && this._lottie.playCount === 0) { - this._lottie.triggerEvent('loopComplete', { - currentLoop: this._lottie.playCount, - direction: this.direction, - totalLoops: typeof this.loop === 'number' ? this.loop : Infinity, - type: 'loopComplete', - }); - } } } @@ -1851,7 +1841,13 @@ export class DotLottieCommonPlayer { })); if (autoplay && !hover) { - this.play(); + if (loop === false && direction === -1) { + // Trigger manual play since. Autoplay doesn't work in this scenario. + // See logic within play() function: `if (this._lottie.playDirection === -1 && this._lottie.currentFrame === 0) ` + this.play(); + } else { + this.setCurrentState(PlayerState.Playing); + } } this._updateTestData(); diff --git a/packages/react-player/cypress/component/player.cy.tsx b/packages/react-player/cypress/component/player.cy.tsx index c0981b36..e9fccfb1 100644 --- a/packages/react-player/cypress/component/player.cy.tsx +++ b/packages/react-player/cypress/component/player.cy.tsx @@ -3,7 +3,7 @@ */ import { PlayerState } from '@dotlottie/common'; -import React, { useRef } from 'react'; +import React, { useRef, useState } from 'react'; import { DotLottieRefProps } from '../../dist'; import { Controls } from '../../src/controls'; @@ -90,6 +90,48 @@ describe('Player', () => { cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); }); + it('should fire initial `loopComplete` when direction is `-1`', () => { + function Wrapper(): JSX.Element { + const lottieRef = useRef(); + const [initialLoopComplete, setIntialLoopComplete] = useState(false); + + return ( + <> + { + lottieRef.current = ref; + const lottie = ref.getAnimationInstance(); + ref.addEventListener('loopComplete', () => { + // Start of second loop + if (lottie.playCount === -2) { + setIntialLoopComplete(true); + } + }); + }} + > + + + + + + + ); + } + + cy.mount(); + + cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); + cy.get('[data-testid="initialLoopComplete"]').should('have.value', 'true'); + }); + it('should be able to load valid .lottie urls with additional query params', () => { cy.mount(