更改其属性后重新渲染子类织物对象

问题描述 投票:0回答:2

我已经对织物进行了子分类。矩形“类”。它有一些属性,如类型、名称和区域。

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

    initialize: function(options) {
      options || (options = { });
  
      this.callSuper('initialize', options);

      // type is either one of HALL, BEDROOM, TOILET, etc.
      this.set('type', options.type || '');

      // name is user defined and also a default name is generated if the name has not been specified
      // the name acts as a unique identifier
      this.set('name', options.name || '');

      // area is in sq. meters
      this.set('area', options.area || 0);
    },
  
    toObject: function() {
      return fabric.util.object.extend(this.callSuper('toObject'), {
        type: this.get('type'),
        name: this.get('name'),
        area: this.get('area')
      });
    },
    
    _render: function(ctx) {
      this.callSuper('_render', ctx);

      ctx.font = '1.3em Lato';
      ctx.fillStyle = '#383838';
      ctx.fillText("Type: "+this.type, -this.width/2+15, -this.height/2 + 20);
      ctx.fillText("Name: "+this.name, -this.width/2+15, -this.height/2 + 40);
      ctx.fillText("Area: "+this.area+" sq. m.", -this.width/2+15, -this.height/2 + 60);
    }
  });

双击此矩形时会显示提示,用户可以在其中更改名称和区域属性。如果用户单击保存,将触发以下代码。它会更改属性并再次呈现所有内容。

function saveRoomInfo(){
        if(SELECTED_ITEM == null){return;}
        // get the data from the form and put it into the object
        
        var roomInfoForm_name = document.getElementById('roomName');
        var newName = roomInfoForm_name.value;

        var roomInfoForm_area = document.getElementById('roomArea');
        var newArea = roomInfoForm_area.value;

        SELECTED_ITEM.set('name',newName);
        SELECTED_ITEM.set('area',newArea);
        
        fabricCanvas.renderAll();
        
    }

这里的问题是,更改是在对象中进行的(通过调试器确认),但更改没有在用户界面(矩形对象)中进行。

另一个问题,重新渲染所有内容是否是一种好习惯。我可以有选择地重新渲染一个对象吗?我可以删除旧对象并渲染一个具有不同属性的新对象,但这也需要更改其他数据结构。

javascript html fabricjs
2个回答
2
投票

在较新版本的 fabricjs 中,它不会渲染所有对象,您需要设置

dirty : true
或将属性放在
cacheProperties
中,这会影响缓存画布以渲染缓存。并且不要使用
type
属性,因为它用于在从 JSON 加载时搜索相应的类。

演示

fabric.RoomRect = fabric.util.createClass(fabric.Rect, {
  type: 'roomRect',

  initialize: function(options) {
    options || (options = {});

    this.callSuper('initialize', options);
    // type is either one of HALL, BEDROOM, TOILET, etc.
    this.roomRectType = options.roomRectType || '';
    // name is user defined and also a default name is generated if the name has not been specified
    // the name acts as a unique identifier
    this.name = options.name || '';
    // area is in sq. meters
    this.area = options.area || '';
  },

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

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

    ctx.font = '1.3em Lato';
    ctx.fillStyle = '#383838';
    ctx.fillText("Type: " + this.roomRectType, -this.width / 2 + 15, -this.height / 2 + 20);
    ctx.fillText("Name: " + this.name, -this.width / 2 + 15, -this.height / 2 + 40);
    ctx.fillText("Area: " + this.area + " sq. m.", -this.width / 2 + 15, -this.height / 2 + 60);
  }
});

var canvas = new fabric.Canvas('c');
var roomrect = new fabric.RoomRect({
  left: 10,
  top: 10,
  width: 100,
  height: 100,
  fill: '',
  stroke: 'red'
});
canvas.add(roomrect);
setTimeout(function() {
  roomrect.set({
    roomRectType: 'room',
    name: 'test',
    area: 100,
    dirty: true
  });
  canvas.requestRenderAll();
}, 2000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.2/fabric.js"></script>
<canvas width=300 height=300 id='c'></canvas>


0
投票

我试着让 Fabric 上的点的半径动态化。这样我就可以借助 html-input-slider 使点变小或变大。

我发现要实时重新渲染这些点。

  • 我们需要获取织物对象。
  • 根据我们的要求操纵它的字段。 (不要忘记更改字段 "dirty":false --> "dirty":true 以使重新渲染实时发生)
  • 再次设置织物对象。

    const currentCtoppingPoints = fabricCanvas.getObjects().map((pointObject) => {
      pointObject.radius = event.target.value;
      pointObject.dirty = true;
      return pointObject;
    });
    
    fabricCanvas.remove(...fabricCanvas.getObjects());

    currentCtoppingPoints.forEach((pointObject) => {
      fabricCanvas.add(pointObject);
    });

© www.soinside.com 2019 - 2024. All rights reserved.