1

Hi I want to have Layers sort control like on photoshop using FabricJS

enter image description here

I have this solution but it's not working well when you have more than 3 objects on canvas:

$("#containerLayers").sortable({
  change: function(event, ui){
    $( "#containerLayers li" ).each(function(index,list){
        if(objectArray[$(list).attr('id')]){
            canvas.moveTo(objectArray[$(list).attr('id')],index);
        }
    });
    canvas.renderAll();
  }
});

Here is other parts of code: https://jsfiddle.net/peLcju2h/16/

does anyone have a better solution than this?

Edin Puzic
  • 998
  • 2
  • 19
  • 39

2 Answers2

2

Best solution for Layer ordering using FabricJS is this one:

$("#containerLayers").sortable({
    update: function(event, ui){

        var items = $(this).children();

        items.each(function(i,item){
            canvas.sendToBack(objectArray[item.id]);
        });
        canvas.renderAll();
    }
});

Instead of using canvas.moveTo() just use canvas.sendToBack() and it will work perfect

Here is link and you can see that ordering is working good https://jsfiddle.net/peLcju2h/24/

Edin Puzic
  • 998
  • 2
  • 19
  • 39
0

First of all, you have some important refactorings to make in your code, mainly because of the fact that a lot of its snipets are duplicated.

I did it already, and the final working code is here: https://jsfiddle.net/peLcju2h/18/


Let's see some considerations:

  • All the Canvas object creations had the same code, so wrap it into a function;
  • You were adding objs to your array through push() function, which is not wrong, but it messed up with your UI sortable handling. That's because every time you change li's position, only the canvas and HTML are updated, but not the array itself.

    You could use a reordering function for this, but it wouldn't fit the goal here once element positions don't have a predefined order or changing logic.

    Instead, I decided to go with an auxiliary array, which is gonna be populated every time the items are sorted.

  • Push the items via [] operator into the array, using the object id as the key;

  • In the end, notice that I put a promise to guarantee the new objectArray will be rendered only after the canvas work has been done.

Note: JSFiddle only works with HTTPS external links, so make sure you import them correctly in future attempts, even if you're doing this via CSS @import.

Community
  • 1
  • 1
diogo
  • 3,769
  • 1
  • 24
  • 30
  • It has same problem when you have more than 3 elements. – Edin Puzic Dec 25 '16 at 16:35
  • @EdinPuzic you have to be more specific when describing a "problem". There's a whole implementation that makes a lot of things and, for me, is working fine. Please, be aware of this for future questions, because people take (sometimes) a lot of time trying to help. – diogo Dec 25 '16 at 16:46