Search code examples
angularfabricjs

Using Fabric.js with Angular 4


I'm new Angular and Fabric.js. I'm trying to build a UI where users can drag and drop objects onto a canvas and then connect them with lines.

In essence I'm hoping to get the Angular4 drag and drop example from the first link to play well with the Fabric.js canvas found at the second link.

<ul>
    <li><a href="https://www.npmjs.com/package/ng2-drag-drop">Drag and Drop</a></li>
    <li><a href="https://codepen.io/janih/pen/Pqwbpe">Canvas Example</a></li>
</ul>

The drag and drop example works but the Fabric.js canvas renders in Chrome as a square box and nothing more.

Steps I've taken:

In tsconfig.json I've set "allowJs": true

My dnd.component.html looks like:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script type="text/javascript" src="canvas.js"></script>

<style>
  canvas {
    border: 1px solid #ccc;
  }
</style>
<div class="container">
    <div>
        <simple-dnd></simple-dnd>
        <canvas id="c" width="600" height="600"></canvas>
    </div>
</div>

And canvas.js looks like this:

setTimeout(function() {
  $(document).ready(function () {
     var canvas = new fabric.Canvas('c', {selection: false});
     var grid = 50;
     // create grid
     for (var i = 0; i < (600 / grid); i++) {
         canvas.add(new fabric.Line([i * grid, 0, i * grid, 600], {stroke: '#ccc', selectable: false}));
         canvas.add(new fabric.Line([0, i * grid, 600, i * grid], {stroke: '#ccc', selectable: false}))
     }
     // add objects
     var rect = new fabric.Rect({
         left: 100,
         top: 100,
         width: 247,
         height: 309,
         fill: '#9f9',
         originX: 'left',
         originY: 'top',
         centeredRotation: true
     });
     canvas.add(rect);
     var rect2 = new fabric.Rect({
         left: 100,
         top: 100,
         width: 223,
         height: 167,
         fill: '#faa',
         originX: 'left',
         originY: 'top',
         centeredRotation: true
     });
     canvas.add(rect2);
     var rect3 = new fabric.Rect({
         left: 196,
         top: 334,
         width: 150,
         height: 75,
         fill: 'blue',
         originX: 'left',
         originY: 'top',
         centeredRotation: true
     });
     canvas.add(rect3);
     canvas.renderAll();
  });
 }, 0);

Solution

  • I do something similar. Not using exactly the links you provided though. I use fabric js along with canvas and angular4 to drag and drop png-files onto the canvas like this. Component:

    import { Component, OnInit} from '@angular/core';
    import 'fabric';
    declare const fabric: any;
    
    @Component({
      selector: 'app-image-preview',
      templateUrl: './image-preview.component.html',
      styleUrls: ['./image-preview.component.styl']
    })
    export class ImagePreviewComponent implements OnInit {
    
      image: any;
      file:File = null;
      canvas:any;
    
      constructor() { }
    
      ngOnInit() {
        //this.context = this.canvasRef.nativeElement.getContext('2d');
          this.canvas = new fabric.Canvas('canvas', { selection: false });
      }
    
      handleDrop(e) {
        this.file = e.dataTransfer.files[0];
        const reader = new FileReader();
    
        reader.onload = (imgFile) => {
          console.log(imgFile);
          const data = imgFile.target["result"];                    
          fabric.Image.fromURL(data, (img) => {
            let oImg = img.set({
              left: 0,
              top: 0,
              angle: 0
            }).scale(1);
          this.canvas.add(oImg).renderAll();
          var a = this.canvas.setActiveObject(oImg);
          var dataURL = this.canvas.toDataURL({format: 'png', quality: 0.8});
          });
        };
        reader.readAsDataURL(this.file);
        return false;
      }
    }
    

    HTML template:

    <div
      (dragover)="false"
      (dragend)="false"
      (drop)="handleDrop($event)">
      <canvas id="canvas" class="canvas" width="500" height="500">
      </canvas>
    </div>