chenqingspring / ng-lottie

Render After Effects animations on Angular based on lottie-web
MIT License
340 stars 100 forks source link

Does ng-lottie destroy the animation after the component is destroyed? #41

Open nikhilmathew opened 6 years ago

nikhilmathew commented 6 years ago

there is a destroy method in the lottie-web library but it is not called anywhere in ng lottie

robsman commented 5 years ago

According to my debugging, it doesn't. I ended up attaching a directive of my own that invokes destroy() upon the directive's ngOnDestroy.

Snowbases commented 4 years ago

@robsman how did your code do it?

steffinchen commented 4 years ago

@SnowBases Not OP, but I've had to do the same today, so I hope this helps: You can use ng-lottie's animCreated property to pass it a function that is called by ng-lottie after it has initialized the animation with a reference to the lottie animation object. Use this to store a reference to the animation object in your component, and call animation.destroy() in ngOnDestroy.

Template: <lottie-animation-view (animCreated)="handleAnimation($event)" [options]="options" />

Component:

 ...
  private animation: any;

  handleAnimation(animation) {
    this.animation = animation;
  }

  ngOnDestroy() {
    if (this.animation) {
       this.animation.destroy();
    }
}
...

It would be nice if ng-lottie would do that by itself automatically. I might add a pull request for this in the near future (should be a straight-forward change).

robsman commented 4 years ago

@SnowBases I basically did the same as @steffinchen, but wrapped it into a directive for reuse. Each of our lotties then reads like this: <lottie-animation-view tiLottieCleanup ...

import {Directive, OnInit, OnDestroy, ViewContainerRef, EventEmitter, Input} from '@angular/core';

/**
 * Lifecycle directive that properly destroys lottie animations upon destruction of lottie-animation-view components
 */
@Directive({selector: '[tiLottieCleanup]'})
export class LottieCleanupDirective implements OnInit, OnDestroy {

  lottieAnimations = [];

  @Input()
  lottieName: string = '';

  constructor(private vcRef: ViewContainerRef) {}

  ngOnInit() {
    if (this.vcRef['_data'] && this.vcRef['_data'].componentView) {
      const component = this.vcRef['_data'].componentView.component;
      if (component && component.animCreated instanceof EventEmitter) {
        component.animCreated.subscribe((lottieAnimation) => {
          this.lottieAnimations.push(lottieAnimation);
        });
      }
    }
  }

  ngOnDestroy() {
    console.log(`About to destroy ${this.lottieAnimations.length} lottie animation(s) ...`);

    for (const lottieAnimation of this.lottieAnimations) {
      try {
        lottieAnimation.destroy();
      } catch (err) {
        console.log('Failed destroying lottie animation', err);
      }
    }
    this.lottieAnimations.length = 0;
  }
}