FabricJS canvas drawImage不显示图像

时间:2018-07-17 15:40:56

标签: javascript html css canvas fabricjs

尝试创建一个自定义类,该类将在Fabric矩形的左上角显示图像。

扩展结构类并调用ctx.drawImage不会显示任何内容。

var CustomRect = fabric.util.createClass(fabric.Rect, {

  type: 'labeledRect',

  initialize: function(options) {
    options || (options = { });
    const image = new Image(); 
    image.src = signBtn; 

    this.callSuper('initialize', options);
    this.set('label', options.label || '');
    this.set('image', image);
  },

  toObject: function() {
    return fabric.util.object.extend(this.callSuper('toObject'), {
      label: this.get('label')
    });
  },

  _render: function(ctx) {
    this.callSuper('_render', ctx);

    ctx.font = '20px Helvetica';
    ctx.fillStyle = '#333';
    ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
    ctx.drawImage(this.image, this.left+10, this.top-5, 15, 15);
  }
});

fillText工作正常,并且标签显示正确。

尝试了几种不同的方法,认为未加载图像。它作为SVG导入。我已经将其显示为其他方式,但更喜欢让自定义类来处理此事件,而不是事件处理程序。

2 个答案:

答案 0 :(得分:1)

您需要在加载后设置图像。您可以使用image.onload事件回调,也可以使用fabric.util.loadImage

演示

PathPrefix
myDomain.demo:7479/neo4j/myNeo/browser
fabric.CustomRect = fabric.util.createClass(fabric.Rect, {

  type: 'customRect',

  initialize: function(options) {
    options || (options = { });
    var that = this;
    this.imageLoaded = false;
    fabric.util.loadImage(options.signBtn,function(img){
      that.set('image', img);
      that.imageLoaded = true;
      that.dirty = true;
      //if canvas is global
      canvas.renderAll();
    },{
      crossOrigin : 'annonymous'
    });

    this.callSuper('initialize', options);
    this.set('label', options.label || '');
    
  },

  toObject: function() {
    return fabric.util.object.extend(this.callSuper('toObject'), {
      label: this.label,
      image : this.image
    });
  },

  _render: function(ctx) {
    this.callSuper('_render', ctx);

    ctx.font = '20px Helvetica';
    ctx.fillStyle = '#333';
    ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
    this.imageLoaded && ctx.drawImage(this.image, 10, -5, 15, 15);
  }
});
  fabric.CustomRect.fromObject = function(object, callback) {
    return fabric.Object._fromObject('CustomRect', object, callback);
  };

var url = 'https://upload.wikimedia.org/wikipedia/en/8/80/Wikipedia-logo-v2.svg';
var canvas = new fabric.Canvas('canvas');

var rect = new fabric.CustomRect({
 signBtn: url,
 left : 10,
 top : 10,
 width : 200,
 height: 200,
 fill: 'green',
 label : 'test'
});
canvas.add(rect);
function loadfromjson() {
  var json = canvas.toJSON();
  canvas.clear();
  setTimeout(function() {
    canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
  }, 1000)
}

答案 1 :(得分:1)

我相信还有一些缺少的值,例如this.widththis.height

除此之外,您还必须等到图像加载后才能绘制图像。您可以执行以下操作:

var CustomRect = fabric.util.createClass(fabric.Rect, {

  type: 'labeledRect',

  initialize: function(options) {
    options || (options = { });
    const image = new Image(); 
    image.src = 'https://i.stack.imgur.com/CYp8Y.jpg'; 

    this.callSuper('initialize', options);

    image.onload = (function() {
        this.width = image.width;
        this.height = image.height;
        this.image_loaded = true;
      }).bind(this);


    this.set('label', options.label || '');
    this.set('image', image);
  },

  toObject: function() {
    return fabric.util.object.extend(this.callSuper('toObject'), {
      label: this.get('label')
    });
  },

  _render: function(ctx) {

    if (this.image_loaded) {
        this.callSuper('_render', ctx);
        console.log(-this.width / 2, -this.height / 2);
        ctx.font = '20px Helvetica';
        ctx.fillStyle = '#333';
        ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
        ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
      }
  }
});

请注意这两个更改:

image.onload = (function() {
        this.width = image.width;
        this.height = image.height;
        this.image_loaded = true;
      }).bind(this);

加载图像后,我在image_loaded方法中将initialize设置为true。然后,在_render方法中,检查图像是否已加载,然后绘制图像。

if(this.loaded){
     //............
     ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
 }

这是一个小提琴:https://jsfiddle.net/nimeshka/enL61g0w/55/

您可能需要单击画布以触发render事件。否则,您将不会在输出框中看到该矩形。 (我没有添加) 希望对您有所帮助:)