Using Meteor and React, I am building an application that has a fabric canvas in the middle, a 'components panel' on the left (a library of objects to add to the canvas), and a 'layers panel' on the right (similar to Photoshop, where each object on the canvas is represented as a layer with specific controls like color, opacity etc.).
So far I have managed to display the Layers Panel by using a Meteor session variable that contains an array for the objects on the canvas.
So each time I add, remove, adjust or make any functional change to any object on the canvas, I manually make the adjustment for the object within the session variable array as well.
This has worked well so far but I now want to implement grouping functionality. While it is easy to do this with fabric.js alone, I am having trouble representing the exact state of the groups on the layers panel. It needs to be displayed in a tree format where nested groups and items are within/under other objects.
I also still need to have the layers panel sortable as well.
Using fabric, we can group a set of objects, group another set of objects, and then group the two sets of objects together. This gets quite complicated and is quickly becoming a nightmare to maintain using the method I described above.
So now I am thinking, it would be much easier to just have the layers panel look at the object data directly from the canvas (reactively). This way, I don't need to maintain a second array and manually match every change that occurs. I could then use something like React Sortable Tree.
So in an attempt to make this happen, I am trying to store a copy of canvas.getObjects() into a Meteor session variable after any change occurs on the canvas.
canvas.on({
'after:render': function() {
var canvasObjects = [];
var objects = canvas.getObjects();
objects.forEach(object=>{
canvasObjects.push(object);
});
Session.set('canvasObjects', canvasObjects);
}
});
I am getting the following error though...
TypeError: callback is not a function
at modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:261816
at onLoaded (modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:244313)
at modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:244337
at modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:257179
at onLoaded (modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:244357)
at modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:244379
at Array.forEach (<anonymous>)
at Object.enlivenPatterns (modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:244370)
at Function.fabric.Object._fromObject (modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:257171)
at Function.fabric.Path.fromObject (modules.js?hash=d9804d9fae07a146610fc3c3c610d3e79bf33006:261457)
If I replace this line...
Session.set('canvasObjects', canvasObjects);
with this line...
console.log(canvasObjects);
I see the array printed in the console.
Why is it able to log the array but unable to store it into the session variable?
Is this even a good idea? I feel like it will be bad for performance. Would there be any other way to keep the canvas state and the layers panel in sync with all the properties that I want (visibility, opacity, fill, lock, index, group hierarchy etc.).
Thanks in advance.
