【问题标题】:FabricJS canvas drawImage not displaying imageFabricJS画布drawImage不显示图像
【发布时间】:2018-12-25 09:29:17
【问题描述】:

尝试创建一个自定义类,该类将在 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 导入。我已经让它以其他方式显示,但更喜欢让自定义类处理它而不是事件处理程序。

【问题讨论】:

    标签: javascript html css canvas fabricjs


    【解决方案1】:

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

    演示

    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)
    }
    canvas{
      border:2px solid #000;
    }
    <script src='https://rawgit.com/kangax/fabric.js/master/dist/fabric.js'></script>
    <canvas id="canvas" width="300" height="300"></canvas>
    <button onclick="loadfromjson()">loadfromjson </button>

    【讨论】:

      【解决方案2】:

      我相信有一些缺失值,例如 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);
      

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-11
        • 1970-01-01
        • 2022-01-26
        • 2021-06-13
        • 2013-11-01
        • 2012-05-01
        • 2014-08-16
        • 2014-12-16
        相关资源
        最近更新 更多