Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Control z-index in Fabric.js

Tags:

In fabricjs, I want to create a scene in which the object under the mouse rises to the top of the scene in z-index, then once the mouse leaves that object, it goes back to the z-index where it came from. One cannot set object.zindex (which would be nice). Instead, I'm using a placeholder object which is put into the object list at the old position, and then the old object is put back in the position where it was in the list using canvas.insertAt. However this is not working.

See http://jsfiddle.net/rFSEV/ for the status of this.

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();
like image 503
Ian Avatar asked Jan 03 '13 00:01

Ian


3 Answers

Since fabric.js version 1.1.4 a new method for zIndex manipulation is available:

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

I think this is helpful for your use case. I've updated your jsfiddle - i hope this is what you want:
jsfiddle

like image 68
Kienz Avatar answered Oct 20 '22 18:10

Kienz


Also make sure you change z-index AFTER adding object to canvas.

So code will looks like:

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

Otherwise fabricjs don`t care about z-indexes you setup.

like image 29
Frantisek Avatar answered Oct 20 '22 19:10

Frantisek


After I added a line object, I was make the line appear under the object using:

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

Other options are

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

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

like image 25
Ravi Ram Avatar answered Oct 20 '22 20:10

Ravi Ram