Add multiple element to canvas with fabric js - javascript

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/

Related

the image first loading using function is hide when again the function happen

JavaScript for drag&drop and resizing. Now when I click a button I can load a image in a canvas and it is draggable. But when I click second time the first image is vanish, and new one is coming I want both images. This is the code I'am using:
<html>
<head>
<script src="fabric.min.js"></script>
</head>
<body>
<canvas id="c"></canvas>
<img src="icon_03.jpg" id="my-image">
<button onclick="myFunction()">click</button>
<script>
function myFunction() {
var canvas = new fabric.Canvas('c');
var imgElement = document.getElementById('my-image');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 30,
opacity: 0.85
});
canvas.add(imgInstance);
};
</script>
</body>
</html>
I think the problem is, that you are creating a canvas object in your function, so there is always a new canvas, which is empty created and drawn over the existing one.
I updated your fiddle, so that whenever you click on the button, a new image is added to the canvas: http://jsfiddle.net/z4fty1de/7/
this is my code:
var canvas = new fabric.Canvas('c');
$('#image').click(myFunction);
function myFunction() {
var imgElement = document.getElementById('my-image');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 30,
opacity: 0.85
});
canvas.add(imgInstance);
};
I hope I could help you. :)

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

Multiple background images in fabricjs

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/

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