在 Fabric.js 中控制 z-index

Posted

技术标签:

【中文标题】在 Fabric.js 中控制 z-index【英文标题】:Control z-index in Fabric.js 【发布时间】:2012-12-17 08:39:18 【问题描述】:

在fabricjs中,我想创建一个场景,其中鼠标下的对象在z-index中上升到场景的顶部,然后一旦鼠标离开该对象,它就会回到它所在的z-index从。一个人不能设置 object.zindex (这会很好)。相反,我使用了一个占位符对象,该对象被放入对象列表中的旧位置,然后使用 canvas.insertAt 将旧对象放回它在列表中的位置。但是这不起作用。

查看http://jsfiddle.net/rFSEV/了解此状态。

var canvasS = new fabric.Canvas('canvasS',  renderOnAddition: false, hoverCursor: 'pointer', selection: false );
var bars = ; //storage for bars (bar number indexed by group object)
var selectedBar = null; //selected bar (group object)
var placeholder = new fabric.Text("XXXXX",  fontSize: 12 );

//pass null or a bar
function selectBar(bar) 
    if (selectedBar) 
        //remove the old topmost bar and put it back in the right zindex
        //PROBLEM: It doesn't go back; it stays at the same zindex
        selectedBar.remove();
        canvasS.insertAt(selectedBar, selectedBar.XZIndex, true);
        selectedBar = null;
        
    if (bar) 
        //put a placeholder object ("XXX" for now) in the position
        //where the bar was, and put the bar in the top position
        //so it shows topmost
        selectedBar = bar;
        canvasS.insertAt(placeholder, selectedBar.XZIndex, true);
        canvasS.add(bar);
        canvasS.renderAll();
        
    

canvasS.on(
     'mouse:move': function(e) 
        //hook up dynamic zorder
        if (!e.target) return;
        if (bars[e.target])
            selectBar(e.target);
        else
            selectBar(null);
        ,
    );

var objcount = canvasS.getObjects().length;

//create bars
for (var i = 0; i < 20; ++i) 
    var rect = new fabric.Rect(
      left: 0,
      top: 0,
      rx: 3,
      ry: 3,
      stroke: 'red',
      width: 200,
      height: 25
    );
    rect.setGradientFill(
      x1: 0,
      y1: 0,
      x2: 0,
      y2: rect.height,
      colorStops: 
        0: '#080',
        1: '#fff'
      
    );    
    var text = new fabric.Text("Bar number " + (i+1), 
        fontSize: 12
    );
    var group = new fabric.Group([ rect, text ], 
      left: i + 101,
      top: i * 4 + 26
    );
    group.hasControls = group.hasBorders = false;

    //our properties (not part of fabric)
    group.XBar = rect;
    group.XZIndex = objcount++;

    canvasS.add(group);
    bars[group] = i;
    
canvasS.renderAll();

【问题讨论】:

Fabric 中有 4 种方法来控制 z-index:bringForward(上一级)、bringToFront(一直上)、sendBackwards(下一级)和 sendToBack(一直下)。它们都可以直接在对象上或在画布上调用(传递所需的对象)。 这是很好的信息,但你是说 insertAt 对 z-index 没有任何影响? (那么 insertAt 的目的是什么?)。此外,如果这 4 个方法是唯一的选择,我们将不得不调用 sendBackwards N 次:例如,要将其从 z-index 105 移动到 55,我们必须在循环中调用它 50 次,这显然会重绘每个时间。这非常复杂。 insertAt 应该也可以。这意味着将对象插入正确的位置。但是,它用于在画布上添加新对象。要更改现有对象的 z-index,您可以使用这 4 种方法或直接修改 canvas._objects 数组。 z-index 与该数组中对象的索引相同(首先呈现 0,然后是 1,然后是 2,依此类推) 【参考方案1】:

从 fabric.js 版本 1.1.4 开始,一种新的 zIndex 操作方法可用:

canvas.moveTo(object, index);
object.moveTo(index);

我认为这对您的用例很有帮助。我已经更新了你的 jsfiddle - 我希望这是你想要的:jsfiddle

【讨论】:

另见github.com/kangax/fabric.js/issues/135获取当前zIndex。 还有:bringToFrontsendToBackbringForwardsendBackwards 在画布 Group() 对象上似乎无法正常工作【参考方案2】:

还要确保在将对象添加到画布后更改 z-index。

所以代码看起来像:

canvas.add(object);
canvas.moveTo(object, index);

否则,fabricjs 不关心您设置的 z-index。

【讨论】:

【参考方案3】:

添加线条对象后,我使用以下方法使线条出现在对象下方:

canvas.add(line);
canvas.sendToBack(line);

其他选项是

canvas.sendBackwards canvas.sendToBack canvas.bringForward canvas.bringToFront

见:https://github.com/fabricjs/fabric.js/issues/135

【讨论】:

【参考方案4】:

您可以修改您的_chooseObjectsToRender 方法,使其末尾有以下更改,您将能够实现css风格的zIndexing。

objsToRender = objsToRender.sort(function(a, b) 
  var sortValue = 0, az = a.zIndex || 0, bz = b.zIndex || 0;

  if (az < bz) 
    sortValue = -1;
  
  else if (az > bz) 
    sortValue = 1;
  

  return sortValue;
);

https://github.com/fabricjs/fabric.js/pull/5088/files

【讨论】:

【参考方案5】:

您可以使用这两个函数来获取织物对象的z-index并修改对象的z-index,因为没有特定的方法可以通过对象索引来修改z-index:

fabric.Object.prototype.getZIndex = function() 
    return this.canvas.getObjects().indexOf(this);


fabric.Canvas.prototype.moveToLayer = function(object,position) 
    while(object.getZIndex() > position) 
        this.sendBackwards(object);
    

【讨论】:

以上是关于在 Fabric.js 中控制 z-index的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Fabric.js 上获取鼠标坐标?

如何为 Fabric.js 启用响应式设计

Fabric js:移动时没有组成员更新

Fabric.js 橡皮擦问题画布

node.js loadFromDatalessJSON 上的 fabric.js 在组中移动对象

在 Fabric.js 中分层画布对象