在 Fabric.js 中分层画布对象

Posted

技术标签:

【中文标题】在 Fabric.js 中分层画布对象【英文标题】:Layering canvas objects in Fabric.js 【发布时间】:2013-02-08 13:29:03 【问题描述】:

有没有办法通过官方 API 在 Fabric.js 画布上分层对象?现在我发现这样做的唯一方法是手动遍历 canvas._objects 并重新排序它们,以便它们以特定顺序绘制。有没有更好的方法来做到这一点,并且不会(可能)破坏对象?

【问题讨论】:

【参考方案1】:

[编辑] 我在下面更正了我的信息(我的错,我最初考虑的是 KineticJs api)。

FabricJS 有这些改变对象 z-index 的 API 方法:

canvas.sendBackwards(myObject)
canvas.sendToBack(myObject)
canvas.bringForward(myObject)
canvas.bringToFront(myObject)

在幕后,FabricJs 通过从 getObjects() 数组中删除对象并将其拼接回所需位置来更改 z-index。它有一个很好的优化,可以检查相交的对象。

bringForward: function (object) 
       var objects = this.getObjects(),
           idx = objects.indexOf(object),
           nextIntersectingIdx = idx;


       // if object is not on top of stack (last item in an array)
       if (idx !== objects.length-1) 

         // traverse up the stack looking for the nearest intersecting object
         for (var i = idx + 1, l = this._objects.length; i < l; ++i) 

           var isIntersecting = object.intersectsWithObject(objects[i]) ||
                                object.isContainedWithinObject(this._objects[i]) ||
                                this._objects[i].isContainedWithinObject(object);

           if (isIntersecting) 
             nextIntersectingIdx = i;
             break;
           
         
         removeFromArray(objects, object);
         objects.splice(nextIntersectingIdx, 0, object);
       
       this.renderAll();
     ,

【讨论】:

谢谢!这为我省去了很多麻烦。 fabricjs 是否有内置的对象堆栈索引系统...然后我可以做类似var idx = some_object.get_zIndex() 可以得到z-index:canvas.getObjects().indexOf(some_object)。有四个命令可用于更改堆叠顺序:some_object.sendBackwards()、some_object.sendToBack()、some_object.bringForward() 和 some_object.bringToFront()。 啊,天哪,当然……如果它是一条蛇,它会咬我……谢谢。 @simmisimmi。您可以使用这些画布方法来影响对象相对于其他对象的 z-index:bringToFront(object) bringFoward(object) sendToBack(object) sendBackwards(object)。 sendBackwards 和 BringForward 都接受您要相对于索引的第二个对象。【参考方案2】:

第一步:你可以使用preserveObjectStacking: true

第 2 步:然后使用 sendtoback,sendtofront....fabricjs 选项,如下所示

Answered over here

【讨论】:

【参考方案3】:

如果您想为所有对象设置特定的顺序,而不是向前/向后移动一个对象,迭代调用将/发送到前/后是很慢的。

您可以使用bringToFront 的代码作为加快此用例速度的灵感:https://github.com/kangax/fabric.js/blob/586e61dd282b22c1d50e15c0361875707e526fd8/src/static_canvas.class.js#L1468

然后这样做:

fabric.Canvas.prototype.orderObjects = function(compare) 
    this._objects.sort(compare);
    this.renderAll();

其中 compare 定义了排序,例如:

function compare(x,y) 
    return x.getWidth() * x.getHeight() < y.getWidth() * y.getHeight();


some_canvas.orderObjects(compare)

如果您希望将较小的物体放在前面。

【讨论】:

【参考方案4】:

我就是这样做的。我为每个织物对象添加了一个 zIndex 属性,然后在将它们添加到画布后调用了一个排序函数:

const CIRCLE_INDEX = 1
let object = new fabric.Circle(
    left: 10,
    top: 10,
    radius: 5
    ...other properties
    zIndex: CIRCLE_INDEX
);

然后在添加对象后调用这样的函数

const sortObjects = () => 
    canvas._objects.sort((a, b) => (a.zIndex > b.zIndex) ? 1 : -1);
    canvas.renderAll();

【讨论】:

以上是关于在 Fabric.js 中分层画布对象的主要内容,如果未能解决你的问题,请参考以下文章

缩放 fabric.js 画布对象

Fabric.js橡皮擦问题画布

在 html5 中的 fabric.js 画布上一次删除多个对象

Fabric.js 将画布(或对象组)剪辑到多边形

Fabric.js:如何取消选择画布上的一个或多个对象?

防止 Fabric js 对象超出画布边界