Snehalk
Snehalk

Reputation: 61

Reference Error : patternSourceCanvas is not defined fabric js loadFromJSON

I am applying pattern to SVG, and using toJSON save data in database. When I am trying to load that on canvas using loadFromJSON its throwing error pattern source is undefined.

Here is my code I am using to set pattern.

fabric.Image.fromURL(url,function(img){
            img.scaleToWidth(width);
            if (angle > 0) img.set('angle', angle);
            var patternSourceCanvas = new fabric.StaticCanvas();
            patternSourceCanvas.add(img);
            patternSourceCanvas.renderAll();
            var pattern = new fabric.Pattern({
                source: function() {
                    patternSourceCanvas.setDimensions({
                        width:img.getWidth() + padding,
                        height:img.getHeight() + padding
                    });
                    patternSourceCanvas.renderAll();
                    return patternSourceCanvas.getElement();
                },
                repeat: isrepeat,
                src: url,
            });

            if(left_offset > 0) { pattern.offsetX = (left_offset); } else{ pattern.offsetX = 0;}
            if(top_offset > 0) { pattern.offsetY = (top_offset); } else { pattern.offsetY = 0;}
            var applyPatternto = 0;
            if(activeView != 1){ applyPatternto = $("#sel_applyPatternto").val(); }
            currentElement.paths[applyPatternto].setFill(pattern);
            canvas.renderAll();
        });

to load save JSON and load from JSON I am using following,

var frontJson  = JSON.stringify(canvas.toJSON());

while loading from JSON I also add delay to check same issue,

canvas.loadFromJSON(frontJson);
    setTimeout(function(){
        canvas.renderAll.bind(canvas);  
 },3000);

Upvotes: 0

Views: 966

Answers (2)

user9159750
user9159750

Reputation:

Use below code for convert the Image source into the base 64 format and store in database and reopen the same.

JavaScript:

//override toObject of fabric.Pattern
var toFixed = fabric.util.toFixed;
fabric.Pattern.prototype.toObject = function(propertiesToInclude) {
  var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,
    source, object;
  if (typeof this.source === "function") {
    source = String(this.source);
  } else if (typeof this.source.src === "string") {
    source = this.source.src;
  } else if (typeof this.source === "object" && this.source.toDataURL) {
    source = this.source.toDataURL();
  }
  object = {
    type: "pattern",
    source: source,
    repeat: this.repeat,
    crossOrigin: this.crossOrigin,
    offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),
    offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),
    patternTransform: this.patternTransform ? this.patternTransform.concat() : null
  };
  fabric.util.populateWithProperties(this, object, propertiesToInclude);
  return object;
};



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) {
  //alert('t' + img);
  console.log('img', img);
  img.scaleToHeight(200);
  var patternSourceCanvas = new fabric.StaticCanvas();
  patternSourceCanvas.add(img);
  patternSourceCanvas.setDimensions({
    width: img.getWidth(),
    height: img.getHeight()
  });
  patternSourceCanvas.renderAll();
  var pattern = new fabric.Pattern({
    source: patternSourceCanvas.getElement()
  });
  rect.fill = pattern;
  canvas.renderAll();
}, {
  crossOrigin: 'annonymous'
});

$('#loadjson').on('click', function() {
  var json = canvas.toJSON();
  console.log('json', json['objects']);
  canvas.clear();
  setTimeout(function() {
    canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
  }, 3000)
})

css:

canvas{
  border:2px solid #000;
}

Html:

<canvas id="canvas" width="300" height="300"></canvas><br>
<button  id="loadjson">loadfromjson </button>
<script src='https://www.multicastr.com/imageeditor/assets/js/fabric.unmin.js'></script>
<script src="https://www.multicastr.com/user/js/jquery.min.js"></script>

Upvotes: 0

AndreaBogazzi
AndreaBogazzi

Reputation: 14741

Is scope problem.

You can't reload a function from JSON that has references outside of itself.

When the function gets rebuilded there is no patternSourceCanvas defined for it to run.

source: function() {
  patternSourceCanvas.setDimensions({
    width:img.getWidth() + padding,
    height:img.getHeight() + padding
  });
  patternSourceCanvas.renderAll();
  return patternSourceCanvas.getElement();
},

in this context patternSourceCanvas is undefined.

Even if you provide the patternSourceCanvas internally that would be helpless since the img will not be painted on it.

If you need to build a pattern with a function you have to be sure that those vars are available in the global namespace at render time.

is also unclear where padding comes from, it may be affected from the same problem.

Upvotes: 2

Related Questions