I'm using this script:
var canvas = new fabric.Canvas('game_canvas', { selection: false });
fabric.Image.fromURL('images/bg.jpg', function(img) {
img.set('left', 1024/2).set('top', 600/2).set('zindex', 0);
canvas.add(img);
});
fabric.Image.fromURL('images/panel-2-bg-l-r.png', function(img) {
img.set('left', 262/2).set('top', (390/2)+110).set('zindex', 1);
canvas.add(img);
});
fabric.Image.fromURL('images/player-board.png', function(img) {
img.set('left', 254/2).set('top', (122/2)).set('zindex', 2);
canvas.add(img);
});
fabric.Image.fromURL('images/player-board-top-red.png', function(img) {
img.set('left', 203/2).set('top', (109/2)).set('zindex', 3);
canvas.add(img).bringToFront(img);
});
3rd image draw is working properly and showing one on top of the other. But if I add 4th one it's hiding behind 3rd. If I specify zindex of the image it's still under 3rd only.
What is wrong with this? Am I doing something wrong here? Please help.
Thanks
Peter
There are couple of issues here.
1) You can't change zindex of images by setting their zindex property. Fabric images simply don't have such property and changing it doesn't change z index of images on canvas. This makes all those .set('zindex', 0)
, .set('zindex', 1)
, etc. pretty much a no-op.
2) bringToFront
works as expected here, bringing last image all the way to the top of the drawing stack. But the problem is that "images/player-board-top-red.png" image which you're loading last is not guaranteed to be the last one added. Those 4 requests are asynchronous; they are coming in any order, and so callbacks are executed in any order as well. In my test, for example, the last image comes second, callback executes, image is brought to the front, but is then "overwritten" by following 2 callbacks.
How to make last image render on top? Well, we can simply check that all images are loaded before attempting to bring last one to the top:
var img4;
// ...
function checkAllLoaded() {
if (canvas.getObjects().length === 4) {
canvas.bringToFront(img4);
}
}
// ...
fabric.Image.fromURL('images/1.png', function(img) {
img.set('left', 0).set('top', 0);
canvas.add(img);
checkAllLoaded(img);
});
// load other images, making sure to include `checkAllLoaded` in callback
fabric.Image.fromURL('images/4.png', function(img) {
img4 = img.set('left', 0).set('top', 0);
canvas.add(img);
checkAllLoaded(img);
});
By the way, don't forget that you can pass an object to set
method like so:
img.set({ left: ..., top: ... });
And since set
is chainable and returns reference to an instance, you can even pass it to add
like so:
canvas.add(img.set({ left: ..., top: ... }));
Hope this helps.