Search code examples
javascripttypescriptcanvashtml5-canvasfabricjs

create a circle object and push them in array


I need to create circles in canvas using fabric. Every click, there is a circle created. However, if the new circle created it will replace old circle. This my stackblitz demo.

HTML

<canvas #canvas id="canvas" width="900" height="400" >
  <p>Your browser doesn't support canvas!</p>
</canvas>

TS

    this.canvas = new fabric.Canvas('canvas');
    var circle = new fabric.Circle({
    radius: 20,
    fill: '#eef',
    originX: 'center',
    originY: 'center'
});
    var text = new fabric.Text(`${data.data.name}`, {
    fontSize: 30,
    originX: 'center',
    originY: 'center'
});
    this.group = new fabric.Group([circle, text], {
    left: event.e.offsetX,
    top: event.e.offsetY,
    angle: 0
});
console.log(this.group);
this.canvas.add(this.group);

this.canvas.setActiveObject(this.canvas.item[0]);
this.canvas.renderAll();

Solution

  • The problem is that you're repeatedly creating the Canvas object, which is likely resulting in the canvas element being drawn over multiple times in separate instances. That is, every new instance will only ever contain the most recent circle and will draw over the previous instance. What you want to do is create the instance once and then reference that instance each time moving forward.

    In your code snippet above, it could look something like this:

    // Ensures that the instance is only created once!
    if(!this.canvas) {
        this.canvas = new fabric.Canvas('canvas');
    }
    
    var circle = new fabric.Circle({
        radius: 20,
        fill: '#eef',
        originX: 'center',
        originY: 'center'
    });
    
    var text = new fabric.Text(`${data.data.name}`, {
        fontSize: 30,
        originX: 'center',
        originY: 'center'
    });
    
    this.group = new fabric.Group([circle, text], {
        left: event.e.offsetX,
        top: event.e.offsetY,
        angle: 0
    });
    
    console.log(this.group);
    this.canvas.add(this.group);
    
    this.canvas.setActiveObject(this.canvas.item[0]);
    this.canvas.renderAll();
    

    I've even added relevant changes to your stackblitz project in a fork to help illustrate how this could be accomplished.