2

I'm trying to add paths in a group by id. But it seems to either reversing the positions of the paths or the z-index - like [red,blue,green] goes [green,blue,red]. How do i do this the correct way?

var id_no;
var objList=[];
if (!id_no) { id_no=1; }

canvas.on('path:created',function(e) {
    e.path.id=id_no;
    objList.push(id_no);
    id_no++;
});

$( "#path-group" ).on( "click", function() {
    var group = new fabric.Group();
    canvas.forEachObject(function(o) {
        if (o.id > 0) {
            group.addWithUpdate(o);
            canvas.remove(o);
        }
    });
    canvas.setActiveObject(group);
    canvas.add(group);
  });
Flemming
  • 694
  • 7
  • 22
  • can you turn this in to a code snippet that will run and demonstrate the problem? thanks! – StefanHayden Sep 25 '16 at 13:20
  • I made a fiddle, but it's giving me another problem that i didn't experience in my project: the canvas.remove(o); is making troubles - console:"TypeError: o is undefined" . https://jsfiddle.net/FlemmingH/z392zjov/ – Flemming Sep 25 '16 at 17:44

1 Answers1

2

I think you are just running in to the problem of looping over an array while removing things from that array. When you do that the indexes start changing as you loop over the array and the results is some weird behavior.

So the main part of the solution below id to just get a list of objects that are not just a reference to the internal fabric list of objects which would change if you removed things from it.

window.canvas;

$(function () {

    canvas = window._canvas = new fabric.Canvas('canvas');
    canvas.backgroundColor = '#efefef';
    canvas.isDrawingMode= true;
    canvas.freeDrawingBrush.color = "purple";
    canvas.freeDrawingBrush.width = 10;
    canvas.renderAll();

document.getElementById('colorpicker').addEventListener('click', function (e) {
        canvas.freeDrawingBrush.color = e.target.value;
    });


var id_no;
var objList=[];
if (!id_no) { id_no=0; }

canvas.on('path:created',function(e) {
   id_no++;
    e.path.id=id_no;
    objList.push(id_no);
    $("#log").append(id_no+'  ');
});

document.getElementById('path-group').addEventListener('click', function (e) {
    $("#log").append( ' -> ');
    var allObjects = canvas.getObjects().slice();
  
    var someObjects = allObjects.filter(o => {
      return o.id  >= id_no-1
    })
    
    someObjects.forEach(o => {
     canvas.remove(o);
    });
    var group = new fabric.Group(someObjects);
     
   
    canvas.add(group);
    canvas.setActiveObject(group);
 
    canvas.renderAll();
    canvas.isDrawingMode= false;
    });

  });
.canvas-wrapper {
    margin-botom: 30px;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="400" height="400" class="canvas"></canvas>

<!--
<select name="colors" id="colorpick">
  <option value="#FFFF00">Yellow</option>
  <option value="#000000">Black</option>
  <option value="#FF0000">Red</option>
</select>
-->

<div id= "colorpicker">
<button id= "yellow" value= "#FFFF00">yellow</button>
<button id= "black" value= "#000000">black</button>
</div>
<button id="path-group">Group</button>
<p>Event Log: </p>
<div id="log"></div>
StefanHayden
  • 3,569
  • 1
  • 31
  • 38
  • Ok that definitely did the trick with grouping correctly. So i make a copy of the objects i wan't to group, but i'm not sure on how to make a copy filtered by 'id'? I guess i need to make a loop for that and push the items in an array? – Flemming Sep 25 '16 at 21:10
  • 1
    there is a filter function bult in to javascript that also returns a new array and not a function: `allObjects.filter(function(object) { return 5 === object.id; })` <- this would give you a new array of all IDs that matched 5. you can change the expression to be anything you want. – StefanHayden Sep 26 '16 at 00:48
  • I tried it but it still group's everything on the canvas: https://jsfiddle.net/FlemmingH/uytuzqws/ – Flemming Sep 26 '16 at 08:10
  • I've updated my answer to only group the last 2 paths added to the canvas. Remember that filter does not effect the array you are operating on and instead just returns a new array. – StefanHayden Sep 26 '16 at 11:00
  • Genieus! This works just great! Thank's StefanHayden :-) – Flemming Sep 26 '16 at 12:28