@aarsteinmedia/dotlottie-player 2.4.4 → 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/dist/cjs/index.js CHANGED
@@ -323,7 +323,7 @@ const addExt = (ext, str)=>{
323
323
  return `${prefix ?? `:${s4()}`}-${s4()}`;
324
324
  };
325
325
 
326
- var name="@aarsteinmedia/dotlottie-player";var version="2.4.4";var description="Web Component for playing Lottie animations in your web app. Previously @johanaarstein/dotlottie-player";var exports$1={".":{"import":"./dist/esm/index.js",node:"./dist/esm/index.js",require:"./dist/cjs/index.js",types:"./dist/index.d.ts"}};var main="./dist/esm/index.js";var unpkg="./dist/index.js";var module$1="./dist/esm/index.js";var types="./dist/index.d.ts";var type="module";var homepage="https://www.aarstein.media/en/dotlottie-player";var repository={url:"https://github.com/aarsteinmedia/dotlottie-player.git",type:"git"};var bugs="https://github.com/aarsteinmedia/dotlottie-player/issues";var author={name:"Johan Martin Aarstein",email:"johan@aarstein.media",url:"https://www.aarstein.media",organization:"Aarstein Media"};var license="GPL-2.0-or-later";var scripts={build:"rimraf ./dist && rollup -c","build:types":"rimraf ./types && tsc","build:cem":"npx cem analyze --config 'cem.config.mjs'",prod:"pnpm build:types && pnpm build && pnpm build:cem",dev:"rollup -c -w --environment NODE_ENV:development",lint:"tsc && eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"};var dependencies={fflate:"^0.8.2",lit:"^2.8.0","lottie-web":"^5.12.2"};var peerDependencies={"@types/react":">= 16.0.0"};var devDependencies={"@custom-elements-manifest/analyzer":"^0.6.9","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-replace":"^5.0.5","@swc/core":"^1.4.2","@types/node":"^20.11.24","@typescript-eslint/eslint-plugin":"^5.62.0","@typescript-eslint/parser":"^5.62.0",autoprefixer:"^10.4.18","esbuild-sass-plugin":"^2.16.1",eslint:"^8.57.0","eslint-plugin-lit":"^1.11.0","postcss-flexbugs-fixes":"^5.0.2",rimraf:"^5.0.5",rollup:"^3.29.4","rollup-plugin-dts":"^6.1.0","rollup-plugin-html-literals":"^1.1.8","rollup-plugin-livereload":"^2.0.5","rollup-plugin-postcss":"^4.0.2","rollup-plugin-postcss-lit":"^2.1.0","rollup-plugin-serve":"^1.1.1","rollup-plugin-summary":"^2.0.0","rollup-plugin-swc3":"^0.9.1",sass:"^1.71.1","ts-lit-plugin":"^1.2.1",typescript:"^5.3.3"};var customElements="dist/custom-elements.json";var files=["dist","README.md"];var keywords=["lottie","dotlottie","animation","web component","component","lit-element","svg","vector","player"];var publishConfig={access:"public"};var engines={node:">= 8.17.0"};var funding={type:"paypal",url:"https://www.paypal.com/donate/?hosted_button_id=E7C7DMN8KSQ6A"};var pkg = {name:name,version:version,description:description,exports:exports$1,main:main,unpkg:unpkg,module:module$1,types:types,type:type,homepage:homepage,repository:repository,bugs:bugs,author:author,license:license,scripts:scripts,dependencies:dependencies,peerDependencies:peerDependencies,devDependencies:devDependencies,customElements:customElements,files:files,keywords:keywords,publishConfig:publishConfig,engines:engines,funding:funding};
326
+ var name="@aarsteinmedia/dotlottie-player";var version="2.5.1";var description="Web Component for playing Lottie animations in your web app. Previously @johanaarstein/dotlottie-player";var exports$1={".":{"import":"./dist/esm/index.js",node:"./dist/esm/index.js",require:"./dist/cjs/index.js",types:"./dist/index.d.ts"}};var main="./dist/esm/index.js";var unpkg="./dist/index.js";var module$1="./dist/esm/index.js";var types="./dist/index.d.ts";var type="module";var homepage="https://www.aarstein.media/en/dotlottie-player";var repository={url:"https://github.com/aarsteinmedia/dotlottie-player.git",type:"git"};var bugs="https://github.com/aarsteinmedia/dotlottie-player/issues";var author={name:"Johan Martin Aarstein",email:"johan@aarstein.media",url:"https://www.aarstein.media",organization:"Aarstein Media"};var license="GPL-2.0-or-later";var scripts={build:"rimraf ./dist && rollup -c","build:types":"rimraf ./types && tsc","build:cem":"npx cem analyze --config 'cem.config.mjs'",prod:"pnpm build:types && pnpm build && pnpm build:cem",dev:"rollup -c -w --environment NODE_ENV:development",lint:"tsc && eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"};var dependencies={fflate:"^0.8.2",lit:"^2.8.0","lottie-web":"^5.12.2"};var peerDependencies={"@types/react":">= 16.0.0"};var devDependencies={"@custom-elements-manifest/analyzer":"^0.6.9","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-replace":"^5.0.5","@swc/core":"^1.4.8","@types/node":"^20.11.28","@typescript-eslint/eslint-plugin":"^5.62.0","@typescript-eslint/parser":"^5.62.0",autoprefixer:"^10.4.18","esbuild-sass-plugin":"^2.16.1",eslint:"^8.57.0","eslint-plugin-lit":"^1.11.0","postcss-flexbugs-fixes":"^5.0.2",rimraf:"^5.0.5",rollup:"^3.29.4","rollup-plugin-dts":"^6.1.0","rollup-plugin-html-literals":"^1.1.8","rollup-plugin-livereload":"^2.0.5","rollup-plugin-postcss":"^4.0.2","rollup-plugin-postcss-lit":"^2.1.0","rollup-plugin-serve":"^1.1.1","rollup-plugin-summary":"^2.0.0","rollup-plugin-swc3":"^0.9.1",sass:"^1.72.0","ts-lit-plugin":"^1.2.1",typescript:"^5.4.2"};var customElements="dist/custom-elements.json";var files=["dist","README.md"];var keywords=["lottie","dotlottie","animation","web component","component","lit-element","svg","vector","player"];var publishConfig={access:"public"};var engines={node:">= 8.17.0"};var funding={type:"paypal",url:"https://www.paypal.com/donate/?hosted_button_id=E7C7DMN8KSQ6A"};var pkg = {name:name,version:version,description:description,exports:exports$1,main:main,unpkg:unpkg,module:module$1,types:types,type:type,homepage:homepage,repository:repository,bugs:bugs,author:author,license:license,scripts:scripts,dependencies:dependencies,peerDependencies:peerDependencies,devDependencies:devDependencies,customElements:customElements,files:files,keywords:keywords,publishConfig:publishConfig,engines:engines,funding:funding};
327
327
 
328
328
  var css_248z = lit.css`*{box-sizing:border-box}:host{--lottie-player-toolbar-height:35px;--lottie-player-toolbar-background-color:#FFF;--lottie-player-toolbar-icon-color:#000;--lottie-player-toolbar-icon-hover-color:#000;--lottie-player-toolbar-icon-active-color:#4285f4;--lottie-player-seeker-track-color:rgba(0, 0, 0, 0.2);--lottie-player-seeker-thumb-color:#4285f4;--lottie-player-seeker-display:block;display:block;width:100%;height:100%}@media (prefers-color-scheme:dark){:host{--lottie-player-toolbar-background-color:#000;--lottie-player-toolbar-icon-color:#FFF;--lottie-player-toolbar-icon-hover-color:#FFF;--lottie-player-seeker-track-color:rgba(255, 255, 255, 0.6)}}.main{display:flex;flex-direction:column;height:100%;width:100%;margin:0;padding:0}.animation{width:100%;height:100%;display:flex}[data-controls=true] .animation{height:calc(100% - 35px)}.animation-container{position:relative}.popover{position:absolute;right:5px;bottom:40px;background-color:var(--lottie-player-toolbar-background-color);border-radius:5px;padding:10px 15px;border:solid 2px var(--lottie-player-toolbar-icon-color);animation:fadeIn .2s ease-in-out}.popover::before{content:"";right:10px;border:7px solid transparent;border-top-color:transparent;margin-right:-7px;height:0;width:0;position:absolute;pointer-events:none;top:100%;border-top-color:var(--lottie-player-toolbar-icon-color)}.toolbar{display:flex;align-items:center;justify-items:center;background:var(--lottie-player-toolbar-background-color);margin:0;height:35px;padding:5px;border-radius:5px;gap:5px}.toolbar.has-error{pointer-events:none;opacity:.5}.toolbar button{cursor:pointer;fill:var(--lottie-player-toolbar-icon-color);color:var(--lottie-player-toolbar-icon-color);display:flex;background:0 0;border:0;padding:0;outline:0;height:100%;margin:0;align-items:center;gap:5px;opacity:.9}.toolbar button:hover{opacity:1}.toolbar button[data-active=true]{opacity:1;fill:var(--lottie-player-toolbar-icon-active-color)}.toolbar button:disabled{opacity:.5}.toolbar button:focus{outline:0}.toolbar button svg{pointer-events:none}.toolbar button svg>*{fill:inherit}.toolbar button.disabled svg{display:none}.progress-container{position:relative;width:100%}.progress-container.simple{margin-right:12px}.seeker{-webkit-appearance:none;-moz-appearance:none;appearance:none;outline:0}.seeker::-webkit-slider-runnable-track,.seeker::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;outline:0}progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;outline:0}.seeker{width:100%;height:20px;border-radius:3px;border:0;cursor:pointer;background-color:transparent;display:var(--lottie-player-seeker-display);color:var(--lottie-player-seeker-thumb-color);margin:0;padding:7.5px 0;position:relative;z-index:1}progress{position:absolute;width:100%;height:5px;border-radius:3px;border:0;top:0;left:0;margin:7.5px 0;background-color:var(--lottie-player-seeker-track-color);pointer-events:none}::-moz-progress-bar{background-color:var(--lottie-player-seeker-thumb-color)}::-webkit-progress-inner-element{border-radius:3px;overflow:hidden}::-webkit-slider-runnable-track{background-color:transparent}::-webkit-progress-value{background-color:var(--lottie-player-seeker-thumb-color)}.seeker::-webkit-slider-thumb{height:15px;width:15px;border-radius:50%;border:0;background-color:var(--lottie-player-seeker-thumb-color);cursor:pointer;-webkit-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;transform:scale(0)}.seeker:focus::-webkit-slider-thumb,.seeker:hover::-webkit-slider-thumb{transform:scale(1)}.seeker::-moz-range-progress{background-color:var(--lottie-player-seeker-thumb-color);height:5px;border-radius:3px}.seeker::-moz-range-thumb{height:15px;width:15px;border-radius:50%;background-color:var(--lottie-player-seeker-thumb-color);border:0;cursor:pointer;-moz-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;transform:scale(0)}.seeker:focus::-moz-range-thumb,.seeker:hover::-moz-range-thumb{transform:scale(1)}.seeker::-ms-track{width:100%;height:5px;cursor:pointer;background:0 0;border-color:transparent;color:transparent}.seeker::-ms-fill-upper{background:var(--lottie-player-seeker-track-color);border-radius:3px}.seeker::-ms-fill-lower{background-color:var(--lottie-player-seeker-thumb-color);border-radius:3px}.seeker::-ms-thumb{border:0;height:15px;width:15px;border-radius:50%;background:var(--lottie-player-seeker-thumb-color);cursor:pointer;-ms-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;transform:scale(0)}.seeker:hover::-ms-thumb{transform:scale(1)}.seeker:focus::-ms-thumb{transform:scale(1)}.seeker:focus::-ms-fill-lower,.seeker:focus::-ms-fill-upper{background:var(--lottie-player-seeker-track-color)}.error{display:flex;margin:auto;justify-content:center;height:100%;align-items:center}.error svg{width:100%;height:auto}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}`;
329
329
 
@@ -335,7 +335,7 @@ function _ts_decorate(decorators, target, key, desc) {
335
335
  }
336
336
  class DotLottiePlayer extends lit.LitElement {
337
337
  _getOptions() {
338
- const preserveAspectRatio = this.preserveAspectRatio ?? (this.objectfit && aspectRatio(this.objectfit)), currentAnimationSettings = this.multiAnimationSettings?.[this._currentAnimation], currentAnimationManifest = this._manifest.animations?.[this._currentAnimation], loop = currentAnimationSettings?.loop !== undefined ? !!currentAnimationSettings.loop : this.loop !== undefined ? !!this.loop : currentAnimationManifest.loop !== undefined && !!currentAnimationManifest.loop, autoplay = currentAnimationSettings?.autoplay !== undefined ? !!currentAnimationSettings.autoplay : this.autoplay !== undefined ? !!this.autoplay : currentAnimationManifest.autoplay !== undefined && !!currentAnimationManifest.autoplay, initialSegment = !this.segment || this.segment.some((val)=>val < 0) ? undefined : this.segment.every((val)=>val > 0) ? [
338
+ const preserveAspectRatio = this.preserveAspectRatio ?? (this.objectfit && aspectRatio(this.objectfit)), currentAnimationSettings = this.multiAnimationSettings?.[this._currentAnimation], currentAnimationManifest = this._manifest.animations?.[this._currentAnimation], loop = currentAnimationSettings?.loop !== undefined ? !!currentAnimationSettings.loop : this.loop !== undefined ? !!this.loop : currentAnimationManifest.loop !== undefined && !!currentAnimationManifest.loop, autoplay = !this.animateOnScroll && (currentAnimationSettings?.autoplay !== undefined ? !!currentAnimationSettings.autoplay : this.autoplay !== undefined ? !!this.autoplay : currentAnimationManifest.autoplay !== undefined && !!currentAnimationManifest.autoplay), initialSegment = !this.segment || this.segment.some((val)=>val < 0) ? undefined : this.segment.every((val)=>val > 0) ? [
339
339
  this.segment[0] - 1,
340
340
  this.segment[1] - 1
341
341
  ] : this.segment, options = {
@@ -373,6 +373,27 @@ class DotLottiePlayer extends lit.LitElement {
373
373
  }
374
374
  return options;
375
375
  }
376
+ _addIntersectionObserver() {
377
+ if (this._intersectionObserver || !('IntersectionObserver' in window)) {
378
+ return;
379
+ }
380
+ this._intersectionObserver = new IntersectionObserver((entries)=>{
381
+ for (const entry of entries){
382
+ if (!entry.isIntersecting || document.hidden) {
383
+ if (this.currentState === exports.PlayerState.Playing) {
384
+ this._freeze();
385
+ }
386
+ this._playerState.visible = false;
387
+ continue;
388
+ }
389
+ if (!this.animateOnScroll && this.currentState === exports.PlayerState.Frozen) {
390
+ this.play();
391
+ }
392
+ this._playerState.visible = true;
393
+ }
394
+ });
395
+ this._intersectionObserver.observe(this.container);
396
+ }
376
397
  async load(src) {
377
398
  if (!this.shadowRoot) return;
378
399
  try {
@@ -387,7 +408,7 @@ class DotLottiePlayer extends lit.LitElement {
387
408
  animations: [
388
409
  {
389
410
  id: useId(),
390
- autoplay: this.autoplay,
411
+ autoplay: !this.animateOnScroll && this.autoplay,
391
412
  loop: this.loop,
392
413
  direction: this.direction,
393
414
  mode: this.mode,
@@ -396,6 +417,7 @@ class DotLottiePlayer extends lit.LitElement {
396
417
  ]
397
418
  };
398
419
  if (this._lottieInstance) this._lottieInstance.destroy();
420
+ this.currentState = this.autoplay && !this.animateOnScroll ? exports.PlayerState.Playing : exports.PlayerState.Stopped;
399
421
  this._lottieInstance = Lottie.loadAnimation({
400
422
  ...this._getOptions(),
401
423
  animationData: animations[this._currentAnimation]
@@ -411,22 +433,14 @@ class DotLottiePlayer extends lit.LitElement {
411
433
  this.setSpeed(speed);
412
434
  this.setDirection(direction);
413
435
  this.setSubframe(!!this.subframe);
414
- if (this.autoplay) {
436
+ if (this.autoplay || this.animateOnScroll) {
415
437
  if (this.direction === -1) this.seek('99%');
416
- if ('IntersectionObserver' in window) {
417
- this._intersectionObserver = new IntersectionObserver((entries)=>{
418
- for (const entry of entries){
419
- if (entry.isIntersecting && !document.hidden) {
420
- this.play();
421
- continue;
422
- }
423
- this._freeze();
424
- }
425
- });
426
- this._intersectionObserver.observe(this.container);
427
- return;
438
+ if (!('IntersectionObserver' in window)) {
439
+ !this.animateOnScroll && this.play();
440
+ this._playerState.visible = true;
428
441
  }
429
- this.play();
442
+ this._addIntersectionObserver();
443
+ return;
430
444
  }
431
445
  }
432
446
  getManifest() {
@@ -444,6 +458,20 @@ class DotLottiePlayer extends lit.LitElement {
444
458
  this.container.addEventListener('mouseenter', this._mouseEnter);
445
459
  this.container.addEventListener('mouseleave', this._mouseLeave);
446
460
  }
461
+ addEventListener('focus', this._handleWindowBlur, {
462
+ passive: true,
463
+ capture: true
464
+ });
465
+ addEventListener('blur', this._handleWindowBlur, {
466
+ passive: true,
467
+ capture: true
468
+ });
469
+ if (this.animateOnScroll) {
470
+ addEventListener('scroll', this._handleScroll, {
471
+ passive: true,
472
+ capture: true
473
+ });
474
+ }
447
475
  }
448
476
  _removeEventListeners() {
449
477
  if (!this._lottieInstance || !this.container) return;
@@ -455,6 +483,9 @@ class DotLottiePlayer extends lit.LitElement {
455
483
  this._lottieInstance.removeEventListener('data_failed', this._dataFailed);
456
484
  this.container.removeEventListener('mouseenter', this._mouseEnter);
457
485
  this.container.removeEventListener('mouseleave', this._mouseLeave);
486
+ removeEventListener('focus', this._handleWindowBlur, true);
487
+ removeEventListener('blur', this._handleWindowBlur, true);
488
+ removeEventListener('scroll', this._handleScroll, true);
458
489
  }
459
490
  _loopComplete() {
460
491
  if (!this._lottieInstance) {
@@ -475,12 +506,12 @@ class DotLottiePlayer extends lit.LitElement {
475
506
  this._lottieInstance.goToAndStop(playDirection === -1 ? firstFrame : totalFrames * 0.99, true);
476
507
  this._lottieInstance.setDirection(playDirection * -1);
477
508
  return setTimeout(()=>{
478
- this._lottieInstance?.play();
509
+ !this.animateOnScroll && this._lottieInstance?.play();
479
510
  }, this.intermission);
480
511
  }
481
512
  this._lottieInstance.goToAndStop(playDirection === -1 ? totalFrames * 0.99 : firstFrame, true);
482
513
  return setTimeout(()=>{
483
- this._lottieInstance?.play();
514
+ !this.animateOnScroll && this._lottieInstance?.play();
484
515
  }, this.intermission);
485
516
  }
486
517
  _enterFrame() {
@@ -524,6 +555,14 @@ class DotLottiePlayer extends lit.LitElement {
524
555
  this.currentState = exports.PlayerState.Error;
525
556
  this.dispatchEvent(new CustomEvent(exports.PlayerEvents.Error));
526
557
  }
558
+ _handleWindowBlur({ type }) {
559
+ if (this.currentState === exports.PlayerState.Playing && type === 'blur') {
560
+ this._freeze();
561
+ }
562
+ if (this.currentState === exports.PlayerState.Frozen && type === 'focus') {
563
+ this.play();
564
+ }
565
+ }
527
566
  _mouseEnter() {
528
567
  if (this.hover && this.currentState !== exports.PlayerState.Playing) {
529
568
  this.play();
@@ -543,6 +582,28 @@ class DotLottiePlayer extends lit.LitElement {
543
582
  this.play();
544
583
  }
545
584
  }
585
+ _handleScroll() {
586
+ if (!this.animateOnScroll || !this._lottieInstance) {
587
+ return;
588
+ }
589
+ if (this._playerState.visible) {
590
+ const adjustedScroll = this._playerState.scrollY > innerHeight ? scrollY - this._playerState.scrollY : scrollY, clampedScroll = Math.min(Math.max(adjustedScroll / 2, 1), this._lottieInstance.totalFrames * 2), roundedScroll = Math.round(clampedScroll / 2);
591
+ requestAnimationFrame(()=>{
592
+ if (roundedScroll < (this._lottieInstance?.totalFrames ?? 0)) {
593
+ this.currentState = exports.PlayerState.Playing;
594
+ this._lottieInstance?.goToAndStop(roundedScroll, true);
595
+ } else {
596
+ this.currentState = exports.PlayerState.Paused;
597
+ }
598
+ });
599
+ }
600
+ if (this._playerState.scrollTimeout) {
601
+ clearTimeout(this._playerState.scrollTimeout);
602
+ }
603
+ this._playerState.scrollTimeout = setTimeout(()=>{
604
+ this.currentState = exports.PlayerState.Paused;
605
+ }, 400);
606
+ }
546
607
  _handleSeekChange({ target }) {
547
608
  if (!(target instanceof HTMLInputElement) || !this._lottieInstance || isNaN(Number(target.value))) return;
548
609
  this.seek(Math.floor(Number(target.value) / 100 * this._lottieInstance.totalFrames));
@@ -792,6 +853,11 @@ class DotLottiePlayer extends lit.LitElement {
792
853
  this._addEventListeners();
793
854
  this.dispatchEvent(new CustomEvent(isPrevious ? exports.PlayerEvents.Previous : exports.PlayerEvents.Next));
794
855
  if (this.multiAnimationSettings?.[this._currentAnimation]?.autoplay ?? this.autoplay) {
856
+ if (this.animateOnScroll) {
857
+ this._lottieInstance?.goToAndStop(0, true);
858
+ this.currentState = exports.PlayerState.Paused;
859
+ return;
860
+ }
795
861
  this._lottieInstance?.goToAndPlay(0, true);
796
862
  this.currentState = exports.PlayerState.Playing;
797
863
  return;
@@ -840,19 +906,9 @@ class DotLottiePlayer extends lit.LitElement {
840
906
  }
841
907
  }
842
908
  async firstUpdated() {
843
- if ('IntersectionObserver' in window) {
844
- this._intersectionObserver = new IntersectionObserver((entries)=>{
845
- for (const entry of entries){
846
- if (entry.isIntersecting && !document.hidden && this.currentState === exports.PlayerState.Frozen) {
847
- this.play();
848
- continue;
849
- }
850
- if (this.currentState === exports.PlayerState.Playing) {
851
- this._freeze();
852
- }
853
- }
854
- });
855
- this._intersectionObserver?.observe(this.container);
909
+ this._addIntersectionObserver();
910
+ if (this.container) {
911
+ this._playerState.scrollY = Math.round(this.container.getBoundingClientRect().top + document.documentElement.scrollTop);
856
912
  }
857
913
  if (this.src) {
858
914
  await this.load(this.src);
@@ -877,6 +933,7 @@ class DotLottiePlayer extends lit.LitElement {
877
933
  }
878
934
  constructor(){
879
935
  super();
936
+ this.animateOnScroll = false;
880
937
  this.background = 'transparent';
881
938
  this.controls = false;
882
939
  this.currentState = exports.PlayerState.Loading;
@@ -901,7 +958,10 @@ class DotLottiePlayer extends lit.LitElement {
901
958
  this._playerState = {
902
959
  prev: exports.PlayerState.Loading,
903
960
  count: 0,
904
- loaded: false
961
+ loaded: false,
962
+ visible: false,
963
+ scrollY: 0,
964
+ scrollTimeout: null
905
965
  };
906
966
  this._handleSettingsClick = ({ target })=>{
907
967
  this._toggleSettings();
@@ -914,7 +974,9 @@ class DotLottiePlayer extends lit.LitElement {
914
974
  this._dataFailed = this._dataFailed.bind(this);
915
975
  this._DOMLoaded = this._DOMLoaded.bind(this);
916
976
  this._enterFrame = this._enterFrame.bind(this);
977
+ this._handleScroll = this._handleScroll.bind(this);
917
978
  this._handleSeekChange = this._handleSeekChange.bind(this);
979
+ this._handleWindowBlur = this._handleWindowBlur.bind(this);
918
980
  this._loopComplete = this._loopComplete.bind(this);
919
981
  this._mouseEnter = this._mouseEnter.bind(this);
920
982
  this._mouseLeave = this._mouseLeave.bind(this);
@@ -924,6 +986,11 @@ class DotLottiePlayer extends lit.LitElement {
924
986
  this.destroy = this.destroy.bind(this);
925
987
  }
926
988
  }
989
+ _ts_decorate([
990
+ decorators_js.property({
991
+ type: Boolean
992
+ })
993
+ ], DotLottiePlayer.prototype, "animateOnScroll", void 0);
927
994
  _ts_decorate([
928
995
  decorators_js.property({
929
996
  type: Boolean,
@@ -50,6 +50,16 @@
50
50
  "description": "dotLottie Player Web Component",
51
51
  "name": "DotLottiePlayer",
52
52
  "members": [
53
+ {
54
+ "kind": "field",
55
+ "name": "animateOnScroll",
56
+ "type": {
57
+ "text": "AnimateOnScroll | undefined"
58
+ },
59
+ "default": "false",
60
+ "description": "Whether to trigger next frame with scroll",
61
+ "attribute": "animateOnScroll"
62
+ },
53
63
  {
54
64
  "kind": "field",
55
65
  "name": "autoplay",
@@ -353,10 +363,10 @@
353
363
  "kind": "field",
354
364
  "name": "_playerState",
355
365
  "type": {
356
- "text": "object"
366
+ "text": "{\n prev: PlayerState\n count: number\n loaded: boolean\n visible: boolean\n scrollY: number\n scrollTimeout: NodeJS.Timeout | null\n }"
357
367
  },
358
368
  "privacy": "private",
359
- "default": "{\n prev: PlayerState.Loading,\n count: 0,\n loaded: false,\n }"
369
+ "default": "{\n prev: PlayerState.Loading,\n count: 0,\n loaded: false,\n visible: false,\n scrollY: 0,\n scrollTimeout: null\n }"
360
370
  },
361
371
  {
362
372
  "kind": "method",
@@ -369,6 +379,12 @@
369
379
  }
370
380
  }
371
381
  },
382
+ {
383
+ "kind": "method",
384
+ "name": "_addIntersectionObserver",
385
+ "privacy": "private",
386
+ "description": "Add IntersectionObserver"
387
+ },
372
388
  {
373
389
  "kind": "method",
374
390
  "name": "load",
@@ -432,6 +448,19 @@
432
448
  "name": "_dataFailed",
433
449
  "privacy": "private"
434
450
  },
451
+ {
452
+ "kind": "method",
453
+ "name": "_handleWindowBlur",
454
+ "privacy": "private",
455
+ "parameters": [
456
+ {
457
+ "name": "{ type }",
458
+ "type": {
459
+ "text": "FocusEvent"
460
+ }
461
+ }
462
+ ]
463
+ },
435
464
  {
436
465
  "kind": "method",
437
466
  "name": "_mouseEnter",
@@ -450,6 +479,12 @@
450
479
  "privacy": "private",
451
480
  "description": "Handle visibility change events"
452
481
  },
482
+ {
483
+ "kind": "method",
484
+ "name": "_handleScroll",
485
+ "privacy": "private",
486
+ "description": "Handle scroll"
487
+ },
453
488
  {
454
489
  "kind": "method",
455
490
  "name": "_handleSeekChange",
@@ -758,6 +793,15 @@
758
793
  }
759
794
  ],
760
795
  "attributes": [
796
+ {
797
+ "name": "animateOnScroll",
798
+ "type": {
799
+ "text": "AnimateOnScroll | undefined"
800
+ },
801
+ "default": "false",
802
+ "description": "Whether to trigger next frame with scroll",
803
+ "fieldName": "animateOnScroll"
804
+ },
761
805
  {
762
806
  "name": "autoplay",
763
807
  "type": {
package/dist/esm/index.js CHANGED
@@ -321,7 +321,7 @@ const addExt = (ext, str)=>{
321
321
  return `${prefix ?? `:${s4()}`}-${s4()}`;
322
322
  };
323
323
 
324
- var name="@aarsteinmedia/dotlottie-player";var version="2.4.4";var description="Web Component for playing Lottie animations in your web app. Previously @johanaarstein/dotlottie-player";var exports={".":{"import":"./dist/esm/index.js",node:"./dist/esm/index.js",require:"./dist/cjs/index.js",types:"./dist/index.d.ts"}};var main="./dist/esm/index.js";var unpkg="./dist/index.js";var module="./dist/esm/index.js";var types="./dist/index.d.ts";var type="module";var homepage="https://www.aarstein.media/en/dotlottie-player";var repository={url:"https://github.com/aarsteinmedia/dotlottie-player.git",type:"git"};var bugs="https://github.com/aarsteinmedia/dotlottie-player/issues";var author={name:"Johan Martin Aarstein",email:"johan@aarstein.media",url:"https://www.aarstein.media",organization:"Aarstein Media"};var license="GPL-2.0-or-later";var scripts={build:"rimraf ./dist && rollup -c","build:types":"rimraf ./types && tsc","build:cem":"npx cem analyze --config 'cem.config.mjs'",prod:"pnpm build:types && pnpm build && pnpm build:cem",dev:"rollup -c -w --environment NODE_ENV:development",lint:"tsc && eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"};var dependencies={fflate:"^0.8.2",lit:"^2.8.0","lottie-web":"^5.12.2"};var peerDependencies={"@types/react":">= 16.0.0"};var devDependencies={"@custom-elements-manifest/analyzer":"^0.6.9","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-replace":"^5.0.5","@swc/core":"^1.4.2","@types/node":"^20.11.24","@typescript-eslint/eslint-plugin":"^5.62.0","@typescript-eslint/parser":"^5.62.0",autoprefixer:"^10.4.18","esbuild-sass-plugin":"^2.16.1",eslint:"^8.57.0","eslint-plugin-lit":"^1.11.0","postcss-flexbugs-fixes":"^5.0.2",rimraf:"^5.0.5",rollup:"^3.29.4","rollup-plugin-dts":"^6.1.0","rollup-plugin-html-literals":"^1.1.8","rollup-plugin-livereload":"^2.0.5","rollup-plugin-postcss":"^4.0.2","rollup-plugin-postcss-lit":"^2.1.0","rollup-plugin-serve":"^1.1.1","rollup-plugin-summary":"^2.0.0","rollup-plugin-swc3":"^0.9.1",sass:"^1.71.1","ts-lit-plugin":"^1.2.1",typescript:"^5.3.3"};var customElements="dist/custom-elements.json";var files=["dist","README.md"];var keywords=["lottie","dotlottie","animation","web component","component","lit-element","svg","vector","player"];var publishConfig={access:"public"};var engines={node:">= 8.17.0"};var funding={type:"paypal",url:"https://www.paypal.com/donate/?hosted_button_id=E7C7DMN8KSQ6A"};var pkg = {name:name,version:version,description:description,exports:exports,main:main,unpkg:unpkg,module:module,types:types,type:type,homepage:homepage,repository:repository,bugs:bugs,author:author,license:license,scripts:scripts,dependencies:dependencies,peerDependencies:peerDependencies,devDependencies:devDependencies,customElements:customElements,files:files,keywords:keywords,publishConfig:publishConfig,engines:engines,funding:funding};
324
+ var name="@aarsteinmedia/dotlottie-player";var version="2.5.1";var description="Web Component for playing Lottie animations in your web app. Previously @johanaarstein/dotlottie-player";var exports={".":{"import":"./dist/esm/index.js",node:"./dist/esm/index.js",require:"./dist/cjs/index.js",types:"./dist/index.d.ts"}};var main="./dist/esm/index.js";var unpkg="./dist/index.js";var module="./dist/esm/index.js";var types="./dist/index.d.ts";var type="module";var homepage="https://www.aarstein.media/en/dotlottie-player";var repository={url:"https://github.com/aarsteinmedia/dotlottie-player.git",type:"git"};var bugs="https://github.com/aarsteinmedia/dotlottie-player/issues";var author={name:"Johan Martin Aarstein",email:"johan@aarstein.media",url:"https://www.aarstein.media",organization:"Aarstein Media"};var license="GPL-2.0-or-later";var scripts={build:"rimraf ./dist && rollup -c","build:types":"rimraf ./types && tsc","build:cem":"npx cem analyze --config 'cem.config.mjs'",prod:"pnpm build:types && pnpm build && pnpm build:cem",dev:"rollup -c -w --environment NODE_ENV:development",lint:"tsc && eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix"};var dependencies={fflate:"^0.8.2",lit:"^2.8.0","lottie-web":"^5.12.2"};var peerDependencies={"@types/react":">= 16.0.0"};var devDependencies={"@custom-elements-manifest/analyzer":"^0.6.9","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-replace":"^5.0.5","@swc/core":"^1.4.8","@types/node":"^20.11.28","@typescript-eslint/eslint-plugin":"^5.62.0","@typescript-eslint/parser":"^5.62.0",autoprefixer:"^10.4.18","esbuild-sass-plugin":"^2.16.1",eslint:"^8.57.0","eslint-plugin-lit":"^1.11.0","postcss-flexbugs-fixes":"^5.0.2",rimraf:"^5.0.5",rollup:"^3.29.4","rollup-plugin-dts":"^6.1.0","rollup-plugin-html-literals":"^1.1.8","rollup-plugin-livereload":"^2.0.5","rollup-plugin-postcss":"^4.0.2","rollup-plugin-postcss-lit":"^2.1.0","rollup-plugin-serve":"^1.1.1","rollup-plugin-summary":"^2.0.0","rollup-plugin-swc3":"^0.9.1",sass:"^1.72.0","ts-lit-plugin":"^1.2.1",typescript:"^5.4.2"};var customElements="dist/custom-elements.json";var files=["dist","README.md"];var keywords=["lottie","dotlottie","animation","web component","component","lit-element","svg","vector","player"];var publishConfig={access:"public"};var engines={node:">= 8.17.0"};var funding={type:"paypal",url:"https://www.paypal.com/donate/?hosted_button_id=E7C7DMN8KSQ6A"};var pkg = {name:name,version:version,description:description,exports:exports,main:main,unpkg:unpkg,module:module,types:types,type:type,homepage:homepage,repository:repository,bugs:bugs,author:author,license:license,scripts:scripts,dependencies:dependencies,peerDependencies:peerDependencies,devDependencies:devDependencies,customElements:customElements,files:files,keywords:keywords,publishConfig:publishConfig,engines:engines,funding:funding};
325
325
 
326
326
  var css_248z = css`*{box-sizing:border-box}:host{--lottie-player-toolbar-height:35px;--lottie-player-toolbar-background-color:#FFF;--lottie-player-toolbar-icon-color:#000;--lottie-player-toolbar-icon-hover-color:#000;--lottie-player-toolbar-icon-active-color:#4285f4;--lottie-player-seeker-track-color:rgba(0, 0, 0, 0.2);--lottie-player-seeker-thumb-color:#4285f4;--lottie-player-seeker-display:block;display:block;width:100%;height:100%}@media (prefers-color-scheme:dark){:host{--lottie-player-toolbar-background-color:#000;--lottie-player-toolbar-icon-color:#FFF;--lottie-player-toolbar-icon-hover-color:#FFF;--lottie-player-seeker-track-color:rgba(255, 255, 255, 0.6)}}.main{display:flex;flex-direction:column;height:100%;width:100%;margin:0;padding:0}.animation{width:100%;height:100%;display:flex}[data-controls=true] .animation{height:calc(100% - 35px)}.animation-container{position:relative}.popover{position:absolute;right:5px;bottom:40px;background-color:var(--lottie-player-toolbar-background-color);border-radius:5px;padding:10px 15px;border:solid 2px var(--lottie-player-toolbar-icon-color);animation:fadeIn .2s ease-in-out}.popover::before{content:"";right:10px;border:7px solid transparent;border-top-color:transparent;margin-right:-7px;height:0;width:0;position:absolute;pointer-events:none;top:100%;border-top-color:var(--lottie-player-toolbar-icon-color)}.toolbar{display:flex;align-items:center;justify-items:center;background:var(--lottie-player-toolbar-background-color);margin:0;height:35px;padding:5px;border-radius:5px;gap:5px}.toolbar.has-error{pointer-events:none;opacity:.5}.toolbar button{cursor:pointer;fill:var(--lottie-player-toolbar-icon-color);color:var(--lottie-player-toolbar-icon-color);display:flex;background:0 0;border:0;padding:0;outline:0;height:100%;margin:0;align-items:center;gap:5px;opacity:.9}.toolbar button:hover{opacity:1}.toolbar button[data-active=true]{opacity:1;fill:var(--lottie-player-toolbar-icon-active-color)}.toolbar button:disabled{opacity:.5}.toolbar button:focus{outline:0}.toolbar button svg{pointer-events:none}.toolbar button svg>*{fill:inherit}.toolbar button.disabled svg{display:none}.progress-container{position:relative;width:100%}.progress-container.simple{margin-right:12px}.seeker{-webkit-appearance:none;-moz-appearance:none;appearance:none;outline:0}.seeker::-webkit-slider-runnable-track,.seeker::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;outline:0}progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;outline:0}.seeker{width:100%;height:20px;border-radius:3px;border:0;cursor:pointer;background-color:transparent;display:var(--lottie-player-seeker-display);color:var(--lottie-player-seeker-thumb-color);margin:0;padding:7.5px 0;position:relative;z-index:1}progress{position:absolute;width:100%;height:5px;border-radius:3px;border:0;top:0;left:0;margin:7.5px 0;background-color:var(--lottie-player-seeker-track-color);pointer-events:none}::-moz-progress-bar{background-color:var(--lottie-player-seeker-thumb-color)}::-webkit-progress-inner-element{border-radius:3px;overflow:hidden}::-webkit-slider-runnable-track{background-color:transparent}::-webkit-progress-value{background-color:var(--lottie-player-seeker-thumb-color)}.seeker::-webkit-slider-thumb{height:15px;width:15px;border-radius:50%;border:0;background-color:var(--lottie-player-seeker-thumb-color);cursor:pointer;-webkit-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;transform:scale(0)}.seeker:focus::-webkit-slider-thumb,.seeker:hover::-webkit-slider-thumb{transform:scale(1)}.seeker::-moz-range-progress{background-color:var(--lottie-player-seeker-thumb-color);height:5px;border-radius:3px}.seeker::-moz-range-thumb{height:15px;width:15px;border-radius:50%;background-color:var(--lottie-player-seeker-thumb-color);border:0;cursor:pointer;-moz-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;transform:scale(0)}.seeker:focus::-moz-range-thumb,.seeker:hover::-moz-range-thumb{transform:scale(1)}.seeker::-ms-track{width:100%;height:5px;cursor:pointer;background:0 0;border-color:transparent;color:transparent}.seeker::-ms-fill-upper{background:var(--lottie-player-seeker-track-color);border-radius:3px}.seeker::-ms-fill-lower{background-color:var(--lottie-player-seeker-thumb-color);border-radius:3px}.seeker::-ms-thumb{border:0;height:15px;width:15px;border-radius:50%;background:var(--lottie-player-seeker-thumb-color);cursor:pointer;-ms-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;transform:scale(0)}.seeker:hover::-ms-thumb{transform:scale(1)}.seeker:focus::-ms-thumb{transform:scale(1)}.seeker:focus::-ms-fill-lower,.seeker:focus::-ms-fill-upper{background:var(--lottie-player-seeker-track-color)}.error{display:flex;margin:auto;justify-content:center;height:100%;align-items:center}.error svg{width:100%;height:auto}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}`;
327
327
 
@@ -333,7 +333,7 @@ function _ts_decorate(decorators, target, key, desc) {
333
333
  }
334
334
  class DotLottiePlayer extends LitElement {
335
335
  _getOptions() {
336
- const preserveAspectRatio = this.preserveAspectRatio ?? (this.objectfit && aspectRatio(this.objectfit)), currentAnimationSettings = this.multiAnimationSettings?.[this._currentAnimation], currentAnimationManifest = this._manifest.animations?.[this._currentAnimation], loop = currentAnimationSettings?.loop !== undefined ? !!currentAnimationSettings.loop : this.loop !== undefined ? !!this.loop : currentAnimationManifest.loop !== undefined && !!currentAnimationManifest.loop, autoplay = currentAnimationSettings?.autoplay !== undefined ? !!currentAnimationSettings.autoplay : this.autoplay !== undefined ? !!this.autoplay : currentAnimationManifest.autoplay !== undefined && !!currentAnimationManifest.autoplay, initialSegment = !this.segment || this.segment.some((val)=>val < 0) ? undefined : this.segment.every((val)=>val > 0) ? [
336
+ const preserveAspectRatio = this.preserveAspectRatio ?? (this.objectfit && aspectRatio(this.objectfit)), currentAnimationSettings = this.multiAnimationSettings?.[this._currentAnimation], currentAnimationManifest = this._manifest.animations?.[this._currentAnimation], loop = currentAnimationSettings?.loop !== undefined ? !!currentAnimationSettings.loop : this.loop !== undefined ? !!this.loop : currentAnimationManifest.loop !== undefined && !!currentAnimationManifest.loop, autoplay = !this.animateOnScroll && (currentAnimationSettings?.autoplay !== undefined ? !!currentAnimationSettings.autoplay : this.autoplay !== undefined ? !!this.autoplay : currentAnimationManifest.autoplay !== undefined && !!currentAnimationManifest.autoplay), initialSegment = !this.segment || this.segment.some((val)=>val < 0) ? undefined : this.segment.every((val)=>val > 0) ? [
337
337
  this.segment[0] - 1,
338
338
  this.segment[1] - 1
339
339
  ] : this.segment, options = {
@@ -371,6 +371,27 @@ class DotLottiePlayer extends LitElement {
371
371
  }
372
372
  return options;
373
373
  }
374
+ _addIntersectionObserver() {
375
+ if (this._intersectionObserver || !('IntersectionObserver' in window)) {
376
+ return;
377
+ }
378
+ this._intersectionObserver = new IntersectionObserver((entries)=>{
379
+ for (const entry of entries){
380
+ if (!entry.isIntersecting || document.hidden) {
381
+ if (this.currentState === PlayerState.Playing) {
382
+ this._freeze();
383
+ }
384
+ this._playerState.visible = false;
385
+ continue;
386
+ }
387
+ if (!this.animateOnScroll && this.currentState === PlayerState.Frozen) {
388
+ this.play();
389
+ }
390
+ this._playerState.visible = true;
391
+ }
392
+ });
393
+ this._intersectionObserver.observe(this.container);
394
+ }
374
395
  async load(src) {
375
396
  if (!this.shadowRoot) return;
376
397
  try {
@@ -385,7 +406,7 @@ class DotLottiePlayer extends LitElement {
385
406
  animations: [
386
407
  {
387
408
  id: useId(),
388
- autoplay: this.autoplay,
409
+ autoplay: !this.animateOnScroll && this.autoplay,
389
410
  loop: this.loop,
390
411
  direction: this.direction,
391
412
  mode: this.mode,
@@ -394,6 +415,7 @@ class DotLottiePlayer extends LitElement {
394
415
  ]
395
416
  };
396
417
  if (this._lottieInstance) this._lottieInstance.destroy();
418
+ this.currentState = this.autoplay && !this.animateOnScroll ? PlayerState.Playing : PlayerState.Stopped;
397
419
  this._lottieInstance = Lottie.loadAnimation({
398
420
  ...this._getOptions(),
399
421
  animationData: animations[this._currentAnimation]
@@ -409,22 +431,14 @@ class DotLottiePlayer extends LitElement {
409
431
  this.setSpeed(speed);
410
432
  this.setDirection(direction);
411
433
  this.setSubframe(!!this.subframe);
412
- if (this.autoplay) {
434
+ if (this.autoplay || this.animateOnScroll) {
413
435
  if (this.direction === -1) this.seek('99%');
414
- if ('IntersectionObserver' in window) {
415
- this._intersectionObserver = new IntersectionObserver((entries)=>{
416
- for (const entry of entries){
417
- if (entry.isIntersecting && !document.hidden) {
418
- this.play();
419
- continue;
420
- }
421
- this._freeze();
422
- }
423
- });
424
- this._intersectionObserver.observe(this.container);
425
- return;
436
+ if (!('IntersectionObserver' in window)) {
437
+ !this.animateOnScroll && this.play();
438
+ this._playerState.visible = true;
426
439
  }
427
- this.play();
440
+ this._addIntersectionObserver();
441
+ return;
428
442
  }
429
443
  }
430
444
  getManifest() {
@@ -442,6 +456,20 @@ class DotLottiePlayer extends LitElement {
442
456
  this.container.addEventListener('mouseenter', this._mouseEnter);
443
457
  this.container.addEventListener('mouseleave', this._mouseLeave);
444
458
  }
459
+ addEventListener('focus', this._handleWindowBlur, {
460
+ passive: true,
461
+ capture: true
462
+ });
463
+ addEventListener('blur', this._handleWindowBlur, {
464
+ passive: true,
465
+ capture: true
466
+ });
467
+ if (this.animateOnScroll) {
468
+ addEventListener('scroll', this._handleScroll, {
469
+ passive: true,
470
+ capture: true
471
+ });
472
+ }
445
473
  }
446
474
  _removeEventListeners() {
447
475
  if (!this._lottieInstance || !this.container) return;
@@ -453,6 +481,9 @@ class DotLottiePlayer extends LitElement {
453
481
  this._lottieInstance.removeEventListener('data_failed', this._dataFailed);
454
482
  this.container.removeEventListener('mouseenter', this._mouseEnter);
455
483
  this.container.removeEventListener('mouseleave', this._mouseLeave);
484
+ removeEventListener('focus', this._handleWindowBlur, true);
485
+ removeEventListener('blur', this._handleWindowBlur, true);
486
+ removeEventListener('scroll', this._handleScroll, true);
456
487
  }
457
488
  _loopComplete() {
458
489
  if (!this._lottieInstance) {
@@ -473,12 +504,12 @@ class DotLottiePlayer extends LitElement {
473
504
  this._lottieInstance.goToAndStop(playDirection === -1 ? firstFrame : totalFrames * 0.99, true);
474
505
  this._lottieInstance.setDirection(playDirection * -1);
475
506
  return setTimeout(()=>{
476
- this._lottieInstance?.play();
507
+ !this.animateOnScroll && this._lottieInstance?.play();
477
508
  }, this.intermission);
478
509
  }
479
510
  this._lottieInstance.goToAndStop(playDirection === -1 ? totalFrames * 0.99 : firstFrame, true);
480
511
  return setTimeout(()=>{
481
- this._lottieInstance?.play();
512
+ !this.animateOnScroll && this._lottieInstance?.play();
482
513
  }, this.intermission);
483
514
  }
484
515
  _enterFrame() {
@@ -522,6 +553,14 @@ class DotLottiePlayer extends LitElement {
522
553
  this.currentState = PlayerState.Error;
523
554
  this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
524
555
  }
556
+ _handleWindowBlur({ type }) {
557
+ if (this.currentState === PlayerState.Playing && type === 'blur') {
558
+ this._freeze();
559
+ }
560
+ if (this.currentState === PlayerState.Frozen && type === 'focus') {
561
+ this.play();
562
+ }
563
+ }
525
564
  _mouseEnter() {
526
565
  if (this.hover && this.currentState !== PlayerState.Playing) {
527
566
  this.play();
@@ -541,6 +580,28 @@ class DotLottiePlayer extends LitElement {
541
580
  this.play();
542
581
  }
543
582
  }
583
+ _handleScroll() {
584
+ if (!this.animateOnScroll || !this._lottieInstance) {
585
+ return;
586
+ }
587
+ if (this._playerState.visible) {
588
+ const adjustedScroll = this._playerState.scrollY > innerHeight ? scrollY - this._playerState.scrollY : scrollY, clampedScroll = Math.min(Math.max(adjustedScroll / 2, 1), this._lottieInstance.totalFrames * 2), roundedScroll = Math.round(clampedScroll / 2);
589
+ requestAnimationFrame(()=>{
590
+ if (roundedScroll < (this._lottieInstance?.totalFrames ?? 0)) {
591
+ this.currentState = PlayerState.Playing;
592
+ this._lottieInstance?.goToAndStop(roundedScroll, true);
593
+ } else {
594
+ this.currentState = PlayerState.Paused;
595
+ }
596
+ });
597
+ }
598
+ if (this._playerState.scrollTimeout) {
599
+ clearTimeout(this._playerState.scrollTimeout);
600
+ }
601
+ this._playerState.scrollTimeout = setTimeout(()=>{
602
+ this.currentState = PlayerState.Paused;
603
+ }, 400);
604
+ }
544
605
  _handleSeekChange({ target }) {
545
606
  if (!(target instanceof HTMLInputElement) || !this._lottieInstance || isNaN(Number(target.value))) return;
546
607
  this.seek(Math.floor(Number(target.value) / 100 * this._lottieInstance.totalFrames));
@@ -790,6 +851,11 @@ class DotLottiePlayer extends LitElement {
790
851
  this._addEventListeners();
791
852
  this.dispatchEvent(new CustomEvent(isPrevious ? PlayerEvents.Previous : PlayerEvents.Next));
792
853
  if (this.multiAnimationSettings?.[this._currentAnimation]?.autoplay ?? this.autoplay) {
854
+ if (this.animateOnScroll) {
855
+ this._lottieInstance?.goToAndStop(0, true);
856
+ this.currentState = PlayerState.Paused;
857
+ return;
858
+ }
793
859
  this._lottieInstance?.goToAndPlay(0, true);
794
860
  this.currentState = PlayerState.Playing;
795
861
  return;
@@ -838,19 +904,9 @@ class DotLottiePlayer extends LitElement {
838
904
  }
839
905
  }
840
906
  async firstUpdated() {
841
- if ('IntersectionObserver' in window) {
842
- this._intersectionObserver = new IntersectionObserver((entries)=>{
843
- for (const entry of entries){
844
- if (entry.isIntersecting && !document.hidden && this.currentState === PlayerState.Frozen) {
845
- this.play();
846
- continue;
847
- }
848
- if (this.currentState === PlayerState.Playing) {
849
- this._freeze();
850
- }
851
- }
852
- });
853
- this._intersectionObserver?.observe(this.container);
907
+ this._addIntersectionObserver();
908
+ if (this.container) {
909
+ this._playerState.scrollY = Math.round(this.container.getBoundingClientRect().top + document.documentElement.scrollTop);
854
910
  }
855
911
  if (this.src) {
856
912
  await this.load(this.src);
@@ -875,6 +931,7 @@ class DotLottiePlayer extends LitElement {
875
931
  }
876
932
  constructor(){
877
933
  super();
934
+ this.animateOnScroll = false;
878
935
  this.background = 'transparent';
879
936
  this.controls = false;
880
937
  this.currentState = PlayerState.Loading;
@@ -899,7 +956,10 @@ class DotLottiePlayer extends LitElement {
899
956
  this._playerState = {
900
957
  prev: PlayerState.Loading,
901
958
  count: 0,
902
- loaded: false
959
+ loaded: false,
960
+ visible: false,
961
+ scrollY: 0,
962
+ scrollTimeout: null
903
963
  };
904
964
  this._handleSettingsClick = ({ target })=>{
905
965
  this._toggleSettings();
@@ -912,7 +972,9 @@ class DotLottiePlayer extends LitElement {
912
972
  this._dataFailed = this._dataFailed.bind(this);
913
973
  this._DOMLoaded = this._DOMLoaded.bind(this);
914
974
  this._enterFrame = this._enterFrame.bind(this);
975
+ this._handleScroll = this._handleScroll.bind(this);
915
976
  this._handleSeekChange = this._handleSeekChange.bind(this);
977
+ this._handleWindowBlur = this._handleWindowBlur.bind(this);
916
978
  this._loopComplete = this._loopComplete.bind(this);
917
979
  this._mouseEnter = this._mouseEnter.bind(this);
918
980
  this._mouseLeave = this._mouseLeave.bind(this);
@@ -922,6 +984,11 @@ class DotLottiePlayer extends LitElement {
922
984
  this.destroy = this.destroy.bind(this);
923
985
  }
924
986
  }
987
+ _ts_decorate([
988
+ property({
989
+ type: Boolean
990
+ })
991
+ ], DotLottiePlayer.prototype, "animateOnScroll", void 0);
925
992
  _ts_decorate([
926
993
  property({
927
994
  type: Boolean,