user9159750
user9159750

Reputation:

Load from JSON with dynamic patterns, patternSourceCanvas is not defined error return by the serialize JSON data

I am trying to save Fabric.js canvas and reload it using loadFromJson. But I am getting error patternSourceCanvas is not defined. I thought I should make it global so I removed var.

How to set the global variable in Fabric JS and use var patternSourceCanvas? When I use the code below, then everything is working fine and the JSON is loaded easily.

var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg

fabric.util.loadImage(t, function(t) {
    var svg_width  = i.width;
    console.log('svg widh' + i.width + 'svg height' + i.height);
    console.log('img width t'+  t.width + ' img height' + t.height);
    if(svg_width >= 300){
        if (i.isSameColor && i.isSameColor() || !i.paths) {
            i.setPatternFill({
                source: t, repeat: 'repeat', offsetX:200 , offsetY : -110 // working
            }), e.fabric.renderAll();
            console.log('in if image 300 up  ', t);
        } else if (i.paths){
            for (var r = 0; r < i.paths.length; r++) 
                i.paths[r].setPatternFill({
                    source: t, repeat: 'repeat' , offsetX: -100 , offsetY:-110 
                }), e.fabric.renderAll();
            console.log('in image elseeee 300 up     ', t);
        }
    }
})

But when I fill some other new shape with the new patternSourceCanvas variable then it's not working. Kindly help me with dynamic patterns.

var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg

fabric.Image.fromURL(t, function (img)  {
    img.scaleToHeight(200);
    var patternSourceCanvas = new fabric.StaticCanvas();

    patternSourceCanvas.add(img);
    patternSourceCanvas.renderAll();

    var pattern = new fabric.Pattern({
    source: function() {
        patternSourceCanvas.setDimensions({
            width: img.getScaledWidth() ,
            height: img.getScaledHeight()
        });
        patternSourceCanvas.renderAll();
            return patternSourceCanvas.getElement();
        },
        repeat: r
    });
    console.log('pattern', pattern);
    //p.set('fill', pattern);
    canvas.renderAll();
    if (i.isSameColor && i.isSameColor() || !i.paths) {

        i.setPatternFill(pattern);
    } else if(i.paths) {
        for (var r = 0; r < i.paths.length; r++) {
            i.paths[r].setPatternFill(pattern);
        }
    }
    e.fabric.renderAll();
});

Upvotes: 0

Views: 372

Answers (1)

Durga
Durga

Reputation: 15614

You need to put patternSourceCanvas to global scope/ scope where loadFromJSON can access patternSourceCanvas. Else you can use cors enabled image directly.

DEMO

var imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/2/22/Wikimapia_logotype.svg';
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
  width: 200,
  height: 200,
  strokeWidth: 2,
  stroke: '#000'
})
canvas.add(rect);

fabric.Image.fromURL(imageUrl, function(img) {
  img.scaleToHeight(200);
  var patternSourceCanvas = new fabric.StaticCanvas();
  patternSourceCanvas.add(img);
  patternSourceCanvas.setDimensions({
    width: img.getScaledWidth(),
    height: img.getScaledHeight()
  });
  patternSourceCanvas.renderAll();
  var pattern = new fabric.Pattern({
      source: patternSourceCanvas.getElement()
    },
    function(patternObj) {
      rect.fill = patternObj;
      rect.dirty = true;
      canvas.renderAll();
    });
}, {
  crossOrigin: 'annonymous'
});

function loadfromjson() {
  var json = canvas.toJSON();
  canvas.clear();
  setTimeout(function() {
    canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
  }, 1000)
}
canvas{
  border:2px solid #000;
}
<canvas id="canvas" width="300" height="300"></canvas><br>
<button onclick="loadfromjson()">loadfromjson </button>
<script src='https://rawgit.com/kangax/fabric.js/master/dist/fabric.js'></script>

Upvotes: 1

Related Questions