i am currently trying to get the backgroundImage object of my canvas instance and it does not work. i get what ever properties of the canvas object but not of my current loaded backgroundImage. anyone else figured out that issue? here is what i have
var bgImg = canvas.setBackgroundImage(img.src, canvas.renderAll.bind(canvas), {
width: bgWidth,
height: bgHeight,
originX: 'left',
originY: 'top',
left: 0,
top: bgTop
});
if i then do something like: console.log(bgImg.backgroundImage) i get null as result. for all other properties of the canvas element i get either the object return or the value if i want the width for example - so all other properties do work. what is the reason that the backgroundImage is not working?
any help is very much appreciated.
many thanks,
michael
It's because setBackgroundImage is not finished (asynchronous) when you try to display with the console.log();
html:
<canvas width="320" height="510" id="canvas"></canvas>
<button id="click">Click here !</button>
Javascript:
var canvas = new fabric.Canvas('canvas');
var img = new Image()
img.src = 'http://fabricjs.com/assets/jail_cell_bars.png';
var bgImg = canvas.setBackgroundImage(img.src, canvas.renderAll.bind(canvas), {
width: 320,
height: 510,
originX: 'left',
originY: 'top',
left: 0,
top: 0
});
document.getElementById("click").addEventListener("click", function () {
console.log(bgImg.backgroundImage);
});
In this example, canvas.backgroundImage is displayed in the console when you click on the button : http://jsfiddle.net/LOLKFC/PQe5e/
Related
I'm trying to create a function that pastes an image from the user's clipboard to the canvas as a new fabric.Image(). Any search result I find either describes cloning objects already on the canvas or pasting IText data. This SO question is related to what I'm asking about, but it's 4 years old and the function in the top answer doesn't work:
How to do Copy and paste the image from User system to Canvas using fabric.js
Here's the code I'm currently trying to use. I'm trying to set up a paste function I can call later:
var $wrapper = $('#content'),
canvas = new fabric.Canvas('canvas', {
width: 400,
height: 550
}),
pasteImage = function (e) {
var items=e.originalEvent.clipboardData.items;
e.preventDefault();
e.stopPropagation();
// Fabric.js image function
function canvasImage(url) {
var img = new fabric.Image(url);
img.scale(0.75).center().setCoords();
canvas.add(img).renderAll();
}
//Loop through files
for(var i=0;i<items.length;i++){
var file = items.items[i],
type = file.type;
if (type.indexOf("image")!=-1) {
var imageData = file.getAsFile();
var imageURL=window.webkitURL.createObjectURL(imageData);
canvasImage(imageURL);
}
}
};
$wrapper.on('paste', pasteImage);
Here's a fiddle to see it in action (or inaction, I guess). This will eventually be part of a Photoshop plugin, so thankfully I only need to worry about this working in Chrome.
I couldn't get your paste event handler to trigger, because i'm not sure if div can natively take the past event unless you make it a contenteditable div, which in your use case i doubt you want to do.
I just recently implemented this in an app of my own, but i wasn't using fabric, just native canvas and js.
You're going to have to rework your code, but try changing
$wrapper.on('paste', pasteImage);
to
$(window).on('paste', pasteImage);
Regardless, I tinkered with your current code, and this is what I got to work, albeit it might not have your settings being triggered completely, but it is pasting the image in:
(function() {
var $wrapper = $('#content'),
canvas = new fabric.Canvas('canvas', {
width: 400,
height: 550
}),
txtStyles = {
top: 100,
left: 200,
padding: 6,
fill: '#d6d6d6',
fontFamily: 'sans-serif',
fontSize: '24',
originY: 'center',
originX: 'center',
borderColor: '#d6d6d6',
cornerColor: '#d6d6d6',
cornerSize: 5,
cornerStyle: 'circle',
transparentCorners: false,
lockUniScaling: true
},
imgAttrs = {
left: 200,
top: 200,
originY: 'center',
originX: 'center',
borderColor: '#d6d6d6',
cornerColor: '#d6d6d6',
cornerSize: 5,
cornerStyle: 'circle',
transparentCorners: false,
lockUniScaling: true
},
introTxt = new fabric.Text('Paste images here', txtStyles),
pasteImage = function (e) {
var items=e.originalEvent.clipboardData.items;
e.preventDefault();
e.stopPropagation();
//Loop through files
for(var i=0;i<items.length;i++){
if (items[i].type.indexOf('image')== -1) continue;
var file = items[i],
type = items[i].type;
var imageData = file.getAsFile();
var URLobj = window.URL || window.webkitURL;
var img = new Image();
img.src = URLobj.createObjectURL(imageData);
fabric.Image.fromURL(img.src, function(img){
canvas.add(img);
});
}
},
//Canvas starter text
introCanvas = function() {
canvas.add(introTxt);
};
introCanvas();
$(window).on('paste', pasteImage);
})();
fiddlers: https://jsfiddle.net/c0kw5dbu/3/
I am using fabric.js for image manipulation and it works great, but I need the controls to be always visible even when I click outside the object/image.
By default they are visible only when you click the objec/image, if you click outside of it the controls disappear.
Is it possibile to do so?
Thank you.
Unfortunately, there is no built-in method in FabricJS, to achieve this at the moment.
However, here is a workaround (function) , which will simulate this functionality ...
function showControls(...objs) {
objs.forEach(obj => {
obj.set('active', true);
canvas.renderAll();
canvas.on('mouse:down', function(e) {
obj.set('active', true);
});
})
}
after adding the image object on the canvas, call the above function along with passing the image object as a parameter, that you wish to show controls for.
ᴅᴇᴍᴏ
var canvas = new fabric.Canvas('c');
// add rectangle (for demo purposes only)
var rect = new fabric.Rect({
top: 100,
left: 290,
width: 100,
height: 100,
fill: '#07C',
originX: 'center',
originY: 'center',
transparentCorners: false
});
canvas.add(rect);
// add image (for demo purposes only)
fabric.Image.fromURL('https://i.imgur.com/Q6aZlme.jpg', function(img) {
img.set({
top: 100,
left: 110,
width: 100,
height: 100,
originX: 'center',
originY: 'center',
transparentCorners: false
})
canvas.add(img);
showControls(img); // pass an object that you wish to show controls for
});
// always show controls (multi-object support)
function showControls(...objs) {
objs.forEach(obj => {
obj.set('active', true);
canvas.renderAll();
canvas.on('mouse:down', function(e) {
obj.set('active', true);
});
})
}
canvas{border:1px solid #ccc}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.11/fabric.min.js"></script>
<canvas id="c" width="400" height="200"></canvas>
not perfect, but a start
// fabricjs object - always show controls
//fabric.Object.prototype.render = (function (render) {
fabric.Image.prototype.render = (function (render) {
return function (ctx) {
render.apply(this, arguments)
// show controls
// but most controls are not usable
// until you activate [click] the object
this._renderControls(ctx)
// activate this object
// to make all controls usable
// only one active object per canvas
// when another object is active
// the controls become not usable
if (!this.canvas._activeObject)
this.canvas._activeObject = this
}
//})(fabric.Object.prototype.render)
})(fabric.Image.prototype.render)
// fabricjs object - activate on mouseover
// this is just a quick hack
// to make controls always usable
//fabric.Object.prototype.initialize = (function (initialize) {
fabric.Image.prototype.initialize = (function (initialize) {
return function () {
initialize.apply(this, arguments)
this.on('mouseover',
function(event) {
this.canvas.setActiveObject(this)
this.canvas.renderAll() // TODO cheaper?
})
}
//})(fabric.Object.prototype.initialize)
})(fabric.Image.prototype.initialize)
I'm attempting to add a loaded image into a fabric Group object. Everything looks ok, but the selection controls aren't selectable and I can't drag the object around. The top left control works though and after clicking it everything is fine.
Here is a jsfiddle that demonstrates the behavior.
var canvas = new fabric.Canvas('canvas', {
width: 200,
height: 200
});
var group = new fabric.Group();
canvas.add(group);
fabric.Image.fromURL('https://placehold.it/100x100', function(img) {
group.addWithUpdate(img);
canvas.setActiveObject(group);
canvas.renderAll();
});
Is this a bug or am I doing something wrong?
For some performance reason, fabricjs does not call setCoords automatically after adding objects to a group ( in case of many object added you can call setCoords just once ).
So after doing addWithUpdate, just call group.setCoords();
var canvas = new fabric.Canvas('canvas', {
width: 200,
height: 200
});
var group = new fabric.Group();
canvas.add(group);
fabric.Image.fromURL('https://placehold.it/100x100', function(img) {
group.addWithUpdate(img);
group.setCoords();
canvas.setActiveObject(group);
canvas.renderAll();
});
I came across this post because I was having trouble getting the positioning of images to work properly. I ended up finding that it's easier to just create create an image element using document.createElement and set the src, then feed that into fabric.Image with all the options you need (instead of using fabric.Image.fromURL which was too much of a headache to use), before adding it to the group.
var oImg = document.createElement("img");
oImg.setAttribute('src', 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Cog_font_awesome.svg/512px-Cog_font_awesome.svg.png');
var i = new fabric.Image(oImg, {
originX: 'center',
originY: 'center',
left: left+35,
top: top-30,
scaleX:.05,
scaleY:.05,
});
g = new fabric.Group([r, t, i]); // where r and t are other fabric objects
I am building a new app with fabricjs,
in this I need
User controlled multiple background images in which behave like normal image, user can rotate, drag resize it,
it done some stuff like this for multiple BG,
// 1st img
var img = new Image();
img.onload = function(){
canvas.setBackgroundImage(img.src, canvas.renderAll.bind(canvas), {
originX: 'left',
originY: 'top',
left: 100,
top: 100
});
};
img.src = "site_image/temp/zig3.jpg";
// 2nd img
var img1 = new Image();
img1.onload = function(){
canvas.setBackgroundImage(img1.src, canvas.renderAll.bind(canvas), {
originX: 'left',
originY: 'top',
left: 300,
top: 300
});
};
img1.src = "site_image/temp/zig1.jpg";
But first BG is replaced by second one,
multiple backgrounds controlled by user are possible or not?
One more issue I faced,
I have JSON of fabricjs, which include an image(normal image not background),
when I will show it to user I want that this image will become background of canvas,
Just use an absolute path in that JSON file and use AJAX to change the background image. Also, you can follow this [link][1] for a JSFiddle example.
[1]: https://jsfiddle . net/manish1706/qxnh4j53/
I am trying to set change the backround image for a canvas using fabric.js but running into some instability. The call to add the background works with no trouble but if I then click anywhere on the canvas it goes blank and seems to move to selection mode - although this just seems to be due to an untrapped exception.
I cannot figure out what is causing the behavior. It works fine on this page http://fabricjs.com/customization/ but the following jsfiddle is failing http://jsfiddle.net/YH9yD/20/
var canvas = window._canvas = new fabric.Canvas('c');
canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));
canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 0.5,
backgroundImageStretch: false
});
this.__canvases.push(canvas);
try loading the image before you add to the canvas. if you add an image that hasnt been loaded you will get an exception. This works for us:
var img = new Image();
img.onload = function(){
canvas.setBackgroundImage(img.src, canvas.renderAll.bind(canvas), {
originX: 'left',
originY: 'top',
left: 0,
top: 0
});
};
img.src = "your image source"
regards,
Benick
Try this
canvas.setBackgroundImage('add image source', canvas.renderAll.bind(canvas), {
scaleY: canvas.height ,
scaleX: canvas.width
});
canvas.renderAll();