简体   繁体   中英

Fabric.js image is not visible on canvas until selected

I am creating a canvas which images can be added to based on a user click event. However, when the element is clicked and the image is added, the image is there (mouse hover suggests it is) but not visible on the canvas until the element is clicked a second time.

  var canvas = new fabric.Canvas( "designer" );

  $( ".shape-option" ).click( function() {
     event.stopPropagation();
     var shapeSelected = $( this );
     var shapeId = shapeSelected.attr( "id" );
     var assetObject = new Image();

     assetObject.src = "/images/" + shapeId + ".png";
     shape = new fabric.Image( assetObject );
     shape.set( { top: 0, height: 300, width: 300 } );
     canvas.add( shape );
  } );

Has anyone run into this or a similar issue?

The issue apparently had to do with timing. After testing several variations, the following worked pretty well.

First, I needed to add a call to canvas.renderAll() to render the canvas after the change. However, I found that calling the canvas.renderAll() function needed to be wrapped in a setTimeout allowing the canvas and DOM to register the change before rendering. This fixed the visibility.

Secondly, I found that the selectable area of the object did not match the location of the object itself. Subsequently, I had to call canvas.calcOffset() to insure the coordinates of the object paths were correct after manipulation. My solution is as follows:

$( document ).ready( function() {
    Designer.initialize();
} ); 

var Designer = Designer || {

    canvas: null, 

    initialize: function() {
        Designer.canvas = new fabric.Canvas( "designer" );
        Designer.bindShapeOptionClickEvent();
    },

    bindShapeOptionClickEvent: function() {
        $( ".shape-option" ).click( function() {
            event.stopPropagation();
            var shapeSelected = $( this );
            var shapeId = shapeSelected.attr( "id" );
            var assetObject = new Image();

            assetObject.src = "/images/" + shapeId + ".png";
            shape = new fabric.Image( assetObject );
            shape.set( { top: 0, height: 300, width: 300 } );
            Designer.canvas.add( shape );
            Designer.updateCanvas();
        } );
    },

    updateCanvas: function() {
        setTimeout( function() { Designer.canvas.renderAll(); }, 50 );
        Designer.canvas.calcOffset();
    }
};

you are doing the image load immediately after a src change that trigger a reload, so when you are doing new fabric.Image the element is not ready yet.

So please change the logic in one of those ways:

$( ".shape-option" ).click( function() {
     event.stopPropagation();
     var shapeSelected = $( this );
     var shapeId = shapeSelected.attr( "id" );
     var assetObject = new Image();
     assetObject.onLoad = function() {
          shape = new fabric.Image( assetObject );
          shape.set( { top: 0, height: 300, width: 300 } );
          canvas.add( shape );
     }
     assetObject.src = "/images/" + shapeId + ".png";
  } );

or let fabric handle the async loading:

$( ".shape-option" ).click( function() {
     event.stopPropagation();
     var shapeSelected = $( this );
     var shapeId = shapeSelected.attr( "id" );
     fabric.Image.fromURL('/images/' + shapeId + '.png', function(oImg) {
         img.set( { top: 0, height: 300, width: 300 } );
         canvas.add(img);
     });
} );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM