SnorreDan
SnorreDan

Reputation: 2900

Performance problems when using Fabric.JS with Angular 2

I am using Fabric.JS to drag elements around in a Canvas in my Angular 2 application. When I open my application on a phone there is a considerable lag when dragging the items around. The lag is not there for the first few seconds, but it gets worse and worse the longer I am dragging the items around.

I decided to do a test using Fabric.JS without Angular 2, and found out that there is no lag there when not using Angular 2.

In the code samples below I am adding three square objects to the Canvas. The lag is barely noticeable with only these three objects, but it gets realy bad if I add many and more complex objects.

My lagging Angular 2 component:

import {Component, OnInit, ViewChild, ElementRef} from '@angular/core';
import 'fabric';
declare let fabric;

@Component({
  selector: 'app-fabric-canvas',
  template: `
    <canvas #canvas width="800" height="800"></canvas>
  `
})
export class FabricCanvasComponent implements OnInit {

  @ViewChild('canvas') canvasRef:ElementRef;
  private canvas: any;
  private square1;
  private square2;
  private square3;

  ngOnInit() {
    this.canvas = new fabric.Canvas(this.canvasRef.nativeElement, { });

    this.square1 = new fabric.Rect({
      width: 50,
      height:50,
      left: 0,
      top: 0,
      fill:'red'
    });

    this.square2 = new fabric.Rect({
      width: 50,
      height:50,
      left: 0,
      top: 0,
      fill:'blue'
    });

    this.square3 = new fabric.Rect({
      width: 50,
      height:50,
      left: 0,
      top: 0,
      fill:'green'
    });

    this.canvas.add(this.square1);
    this.canvas.add(this.square2);
    this.canvas.add(this.square3);
  }
}

My test that is not using Angular 2 and not lagging:

<canvas id="canvas" width="800" height="800"></canvas>

<script>
    var canvas = new fabric.Canvas('canvas');

    var square1 = new fabric.Rect({
        width: 50,
        height:50,
        left: 0,
        top: 0,
        fill:'red'
    });

    var square2 = new fabric.Rect({
        width: 50,
        height:50,
        left: 0,
        top: 0,
        fill:'blue'
    });

    var square3 = new fabric.Rect({
        width: 50,
        height:50,
        left: 0,
        top: 0,
        fill:'green'
    });

    canvas.add(square1);
    canvas.add(square2);
    canvas.add(square3);

</script>

The question is: Why am i experiencing this lag only when using Fabric.JS with Angular 2? Is there something wrong with the way I am importing or using Fabric.JS in my Angular 2 component?

Upvotes: 1

Views: 1757

Answers (2)

Alex
Alex

Reputation: 43

The issue comes from the fact that Zone.js was not supporting EventListenerOptions (passive, etc). Support added in v. 0.8.7: https://github.com/angular/zone.js/blob/master/CHANGELOG.md#087-2017-04-21

Upvotes: 1

Bram De Backer
Bram De Backer

Reputation: 184

I had exactly the same problem (only with touch). I made a freshly new Angular 2 project, added Fabric and dragging got slower with each touch.

I spent hours and hours searching for a solution. Angular ChangeDetectionStrategies didn't help, nor did NgZone. Eventually I found a fix in removing two lines from the Fabric source code. I submitted an issue on their GitHub here: https://github.com/kangax/fabric.js/issues/3776

Removing the following two lines fixed the lag for me:
- addListener(this.upperCanvasEl, 'touchmove', this._onMouseMove, { passive: false });
from the _onMouseUp()-function
- addListener(fabric.document, 'touchmove', this._onMouseMove, { passive: false });
from the _onMouseDown()-function.

I'm not sure if removing these is the way to go, but you can use it as a solution while the people behind Fabric are working on a legit fix.

Upvotes: 2

Related Questions