Multiple background images in fabricjs - javascript

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/

Related

Set background image for Fabric Canvas dynamically

I want to add draw shapes on a Image, so decided to use Fabric JS. I am able to get all shapes and objects working well. Now How do I background set exactly to Image. The Image is dynamic, I want to draw on top of that image, and basically store the annotations of objects for backend processing.
Existing solution using Canvas
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 903;
canvas.height = 657;
var background = new Image();
background.src = "http://www.samskirrow.com/background.png";
// Make sure the image is loaded first otherwise nothing will draw.
background.onload = function(){
ctx.drawImage(background,0,0);
}
Reference - https://stackoverflow.com/a/14013068/2094670
I like this solution.
Live Demo
My Current Fabric JS Code
// Initialize a simple canvas
var canvas = new fabric.Canvas("c", {
hoverCursor: 'pointer',
selection: true,
selectionBorderColor: 'green',
backgroundColor: null
});
// Define the URL where your background image is located
var imageUrl = "../dog.jpg";
// Define
canvas.setBackgroundImage(imageUrl, canvas.renderAll.bind(canvas), {
// Optionally add an opacity lvl to the image
backgroundImageOpacity: 0.5,
// should the image be resized to fit the container?
backgroundImageStretch: false
});
Html
<canvas id="c"></canvas>
Problem.
The image of dog is full hd image, however I see only portion of it. How to do render the background image to its actual height and width using Fabric Canvas ? Since Images are comming dynamically, I might not know exact height and width to hardcode it.
Here's the way to set canvas size base on image size via fabric.js.
It's done initiating the Fabric canvas inside the onload callback, that way we are able to get the image width and height, then set them into the setDimesions method.
img.onload = function () {
...
canvas.setDimensions({ width: img.width, height: img.height });
};
var imageUrl = "http://i.imgur.com/yf6d9SX.jpg";
var background = new Image();
background.src = imageUrl;
// wait for the image to load, then set Fabric Canvas on the callback that runs after image finishes loading
background.onload = function () {
var canvas = new fabric.Canvas("c", {
hoverCursor: "pointer",
selection: true,
selectionBorderColor: "green",
backgroundColor: null,
});
// set canvas width and height based on image size
canvas.setDimensions({ width: background.width, height: background.height });
canvas.setBackgroundImage(imageUrl, canvas.renderAll.bind(canvas), {
// Optionally add an opacity lvl to the image
backgroundImageOpacity: 0.5,
// should the image be resized to fit the container?
backgroundImageStretch: false,
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
<canvas id="c"></canvas>

Is it possible to make a dynamic mask/crop system via fabric.js that behaves like canva.com?

edit 2016, Oct 24
I've an idea about this feature by using 'pattern' which seems to be a good idea.
I tried to prove my thoughts with this pen, its still buggy but at least we can set the image(pattern) position and keep the original image when double click.
I'am not very good at javascript, So if you are interest in this please help to make this more useable, any discussions/thoughts or code correction is welcome.
http://codepen.io/wushan/pen/LRrQEL?editors=1010
// Create Canvas
var canvas = this.__canvas = new fabric.CanvasEx('c', {
preserveObjectStacking: true
});
fabric.Object.prototype.transparentCorners = false;
// Global Settings
var url = "http://fabricjs.com/assets/pug.jpg";
//Make the Pattern by url
function createMaskedImage(url) {
//Load Image
fabric.Image.fromURL(url, function(img) {
img.scaleToWidth(300);
//Make a Pattern
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
var pattern = new fabric.Pattern({
source: function() {
patternSourceCanvas.setDimensions({
width: img.getWidth(),
height: img.getHeight()
});
return patternSourceCanvas.getElement();
},
repeat: 'no-repeat'
});
console.log(pattern.offsetX)
console.log(pattern.offsetY)
console.log(img.getWidth()) // 縮小後 (*scale)
console.log(img.width) // 原尺寸
//Mask (can be any shape ex: Polygon, Circles....)
var rect = new fabric.Rect({
width: 200,
height: 200,
left: 150,
top: 100,
fill: pattern
})
//Bind Double Click Event from fabric.ext
//https://github.com/mazong1123/fabric.ext
rect.on('object:dblclick', function (options) {
//Pass pattern out
enterEditMode(rect, img);
});
canvas.add(rect);
canvas.setActiveObject(rect);
});
}
function enterEditMode(mask, image) {
image.left = mask.left;
image.top = mask.top;
// New Image
// Fake Crop Area (fixed)
var rect = new fabric.Rect({
width: mask.width,
height: mask.height,
left: mask.left,
top: mask.top,
fill: '#000000',
opacity: 0.8,
selectable: false
})
canvas.remove(mask);
canvas.add(image);
image.on('object:dblclick', function (options) {
//Flatten
flatten(rect, image);
});
canvas.add(rect);
// console.log(JSON.stringify(canvas));
}
function flatten(mask, image) {
//Make a Pattern
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(image);
var pattern = new fabric.Pattern({
source: function() {
patternSourceCanvas.setDimensions({
width: image.getWidth(),
height: image.getHeight()
});
return patternSourceCanvas.getElement();
},
repeat: 'no-repeat'
});
//Offsets
pattern.offsetX = image.left - mask.left - image.left;
pattern.offsetY = image.top - mask.top - image.top;
var rect = new fabric.Rect({
width: mask.width,
height: mask.height,
left: mask.left,
top: mask.top,
fill: pattern
})
//Bind Double Click Event from fabric.ext
//https://github.com/mazong1123/fabric.ext
rect.on('object:dblclick', function (options) {
//Pass pattern out
enterEditMode(rect, image);
});
canvas.remove(mask);
canvas.remove(image);
canvas.add(rect);
canvas.setActiveObject(rect);
canvas.renderAll();
}
//Button Events
//Create
document.getElementById('createMaskedImage').addEventListener('click', function () {
createMaskedImage(url);
});
Test this :
click 'create'
double click on the image object
move/scale the image
double click the image to flatten the obejct.
Know issue:
when cutting the image without scale, the image position looks correct but there is a wired transparent space.
It generates a lot duplicate objects on the scene...
Original Post
I've been working with fabric.js for a few month, haven't seen any example or discussions about a mask/crop system which is behaves like canva.com ( which is way easy to understand for users. )
the object looks like this:
when double clicked on a group/mask, it shows the original image with an unselectable mask, you can move/scale the image whatever you need and click 'OK' to made the change without modifying the original image.
I'd like to know if there is any possible solutions about making this in fabricjs, or maybe some thoughts about this issue is welcome.
Thank you a lot !

FabricJS adding Image to Group causes odd control behavior

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

Add multiple element to canvas with fabric js

Sorry for my bad English.
I want to learn the use of fabric.js.
For the basic commands I haven't had any problem. But I now have this problem.
I have two button in the index.html file :
<tr>
<td><button id="caricarettangolo" onMouseDown="caricarettangolo(), caricatutto()" type="button"><img src="immagini/prodotti/rettangolo.svg" /></button></td></tr>
<tr>
<td><button type="button" onMouseDown="caricastella()"><img src="immagini/prodotti/stella.svg" /></button></td></tr>
</tr>
and external js file with this code
function caricacerchio() {
var canvas = new fabric.Canvas('canvas');
var circle = new fabric.Circle({
radius: 20, fill: 'green', left: 100, top: 100
});
canvas.getObjects();
canvas.add(circle);
canvas.selection = false;
canvas.renderAll();
canvas.calcOffset();
};
function caricarettangolo() {
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
width: 50,
height: 50,
left: 50,
top: 50,
fill: 'rgb(255,0,0)'
});
canvas.getObjects();
canvas.add(rect);
canvas.selection = true;
canvas.renderAll();
canvas.calcOffset();
};
But I don't have the solution for seeing two elements.
I see the first element, next, if i push another button, this completely clears the canvas and adds the new element, but clears the first element. If I click in the canvas square, return the first created element. Why? As I can see when I have two different buttons two different element? Thanks.
You're rendering on a new canvas every time you press the button:
var canvas = new fabric.Canvas('canvas');
You want to render the canvas outside of your functions
window.canvas = new fabric.Canvas('canvas');
then use the buttons to add them.
You can see an example here: http://jsfiddle.net/33MME/2/

Setting a background image in fabric.js throws an exception when clicked

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();

Categories

Resources