This site uses cookies to analyse traffic, remember your preferences, and optimise your experience. Learn more, read the privacy policy page.


How to run PIXI in Angular application

How to run PIXI in Angular application

Run PIXI without performance problems.

Pixi.js version used: 4.8.6

Angular detects any change due to Zone.js. If within the new component we add setTimeout,setInterval or requestAnimationFrame then Angular will detect the function’s body call and trigger the change detection mechanism, which is the basis for the framework.

PIXI has its own Ticker inside which is responsible for canvas updates. It is based of course on the requestAnimationFrame.

If we normally start PIXI in a component, we will have a problem because the ticker will trigger the change detection mechanism every moment, which will cause problems for weaker devices or larger projects.

Wrong


import { OnInit, Component, ElementRef } from '@angular/core';
import { Application } from 'pixi.js';

@Component({
  selector: 'app-pixi',
  template: ''
})
export class PIXIComponent implements OnInit {
  public app: Application;

  constructor(private elementRef: ElementRef) {}

  ngOnInit(): void {
    this.app = new Application({});
    this.elementRef.nativeElement.appendChild(this.app.view);
  }
}

The best solution to this problem is to run PIXI outside of Angular zone.
Angular has a special service for these purposes NgZone and the runOutsideAngular method.

Good


import { OnInit, Component, ElementRef, NgZone } from '@angular/core';
import { Application } from 'pixi.js';

@Component({
  selector: 'app-pixi',
  template: ''
})
export class PIXIComponent implements OnInit {
  public app: Application;

  constructor(private elementRef: ElementRef, private ngZone: NgZone) {}

  ngOnInit(): void {
    this.ngZone.runOutsideAngular(() => {
      this.app = new Application({});
    });
    this.elementRef.nativeElement.appendChild(this.app.view);
  }
}

Now the internal requestAnimationFrame will not be noticed by angular when the application is running.

Component example with change in canvas resolution and PIXI destruction:

import { OnInit, Component, ElementRef, Input, HostListener, NgZone, OnDestroy } from '@angular/core';
import { Application, ApplicationOptions } from 'pixi.js';

@Component({
  selector: 'app-pixi',
  template: ''
})
export class PIXIComponent implements OnInit, OnDestroy {
  public app: Application;

  @Input()
  public devicePixelRatio = window.devicePixelRatio || 1;

  @Input()
  public applicationOptions: ApplicationOptions = {};

  constructor(private elementRef: ElementRef, private ngZone: NgZone) {}

  init() {
    this.ngZone.runOutsideAngular(() => {
      this.app = new Application(this.applicationOptions);
    });
    this.elementRef.nativeElement.appendChild(this.app.view);
    this.resize();
  }

  ngOnInit(): void {
    this.init();
  }

  @HostListener('window:resize')
  public resize() {
    const width = this.elementRef.nativeElement.offsetWidth;
    const height = this.elementRef.nativeElement.offsetHeight;
    const viewportScale = 1 / this.devicePixelRatio;
    this.app.renderer.resize(width * this.devicePixelRatio, height * this.devicePixelRatio);
    this.app.view.style.transform = `scale(${viewportScale})`;
    this.app.view.style.transformOrigin = `top left`;
  }

  destroy() {
    this.app.destroy();
  }

  ngOnDestroy(): void {
    this.destroy();
  }

}
Word count: 376
Related posts: