Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FabricJS canvas is "stuck" after adding elements

I'm creating an application using fabric.js, and experiencing really strange behavior. I'm adding both images and text instances, using the regular fabric.Canvas (not fabric.StaticCanvas), and am unable to move or resize these items after addition. I've only added a couple of each type. The basic functionality is wrapped in a callback tied to a click event on some button, but the core fabric functionality looks something like this (simplified, but almost everything is the same as far as fabric related code):

<canvas id="myCanvas" height=600 width=800></canvas>
<input id="addStuff" type="button" value="Add!" />
....
var canvas = new fabric.Canvas('myCanvas');
canvas.renderOnAddition = true;

$(function(){
  $('#addStuff').on('click', function(e) {

      var text   = new fabric.Text("Hello, world", {
        top        : 100,
        left       : 100,
        fontSize   : 12,
        fontFamily : 'Delicious_500'
      });
      text.hasControls = false;

      canvas.add(text);

      fabric.Image.fromURL('./img/pic.png', function(img) {
        var imgX = img.set({
          top: 200,
          left: 100,
        });

        canvas.add(imgX);
      });

      canvas.renderAll();
  });
});

The above code renders the elements well, but they cannot be resized or moved around, and act static. The strange thing is that if I open and close my chrome dev-panel (using F12 or [Ctrl/CMD]+SHIFT+I twice), the canvas regains functionality and everything works again. I have some serverside stuff happening as well (this is only a mock sample of what I'm doing), but I have no idea how to further trace this down to this odd behavior. I'm using the very latest code (built from github repo). Thoughts?

like image 976
sa125 Avatar asked Jun 19 '12 12:06

sa125


2 Answers

It's possible that canvas internal offset is not updated properly. Something on the page could change dimensions/position, making canvas positioned at a different location than the one it was during initialization. Try calling canvas.calcOffset() after renderAll() call, or after adding those objects.

The reason calcOffset is not called in renderAll is for performance reasons. renderAll is a redraw of an entire canvas. It happens every time something changes on canvas and canvas needs to be redrawn. As you can imagine, it gets called quite often (sometimes dozens of times per second), and it would be pretty wasteful to calculate new offset every time redraw happens.

Consider also that in most cases canvas position does not change throughout page life. It probably happens pretty rarely. Mainly during page load.

In highly-dynamic environment — where canvas changes position often — you can solve offset "problem" by explicitly calling calcOffset().

like image 91
kangax Avatar answered Jan 03 '23 22:01

kangax


I had the same problem, in adition to kangax solution, in a VERY extreme environment, you can force it to recalculate the offset anytime the render occurs, with an event.

canvas.on('after:render', function(){ this.calcOffset(); });

like image 36
David Francos Cuartero Avatar answered Jan 04 '23 00:01

David Francos Cuartero