I am trying to stretch the background image so it can fit the canvas size. But its not working.
I have followed this question and based on comment i have implemented the stretching code.
Strech the background image to canvas size with Fabric.js
http://fabricjs.com/docs/fabric.Canvas.html#setBackgroundImage
Code
$(function () {
var canvas1 = new fabric.Canvas('canvas1');
//Default
var canvas = canvas1;
//Change background using Image
document.getElementById('bg_image').addEventListener('change', function (e) {
canvas.setBackgroundColor('', canvas.renderAll.bind(canvas));
canvas.setBackgroundImage(0, canvas.renderAll.bind(canvas));
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
img.set({
width: canvas.getWidth(),
height: canvas.getHeight(),
originX: 'left',
originY: 'top'
});
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));
/*canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
width: canvas.getWidth(),
height: canvas.getHeight(),
originX: 'left',
originY: 'top',
crossOrigin: 'anonymous'
});*/
});
};
reader.readAsDataURL(file);
});
});
It seems that it is not working with latest beta version, however its working with 1.7.19 version but not with 2.0.0-beta.7
JSFiddle:
version 2.0.0-beta.7: http://jsfiddle.net/dhavalsisodiya/8vLo882n/3
varsion 1.7.19: http://jsfiddle.net/dhavalsisodiya/8vLo882n/4/
The solution given by #spankajd is almost there but still not 100% accurate (as you'll see the background image doesn't completely fit to the canvas).
The proper solution to this problem is indeed to use the scaleX and scaleY property (which takes a number as scaling factor), as mentioned by #asturur on your submitted issue.
However, in that case you won't need to set the width and height property of the image. Also, a better (and correct) way of setting those image properties is to pass them as options (argument) to the setBackgroundImage() method (this may resolve some performance issues), as such :
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
scaleX: canvas.width / img.width,
scaleY: canvas.height / img.height
});
... instead of setting them for the image object separately.
that being said, here is a complete working example :
$(function() {
var canvas1 = new fabric.Canvas('canvas1');
//Default
var canvas = canvas1;
canvas.backgroundColor = '#34AD39';
canvas.renderAll();
//Change background using Image
document.getElementById('bg_image').addEventListener('change', function(e) {
canvas.setBackgroundColor('', canvas.renderAll.bind(canvas));
canvas.setBackgroundImage(0, canvas.renderAll.bind(canvas));
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function(f) {
var data = f.target.result;
fabric.Image.fromURL(data, function(img) {
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
scaleX: canvas.width / img.width,
scaleY: canvas.height / img.height
});
});
};
reader.readAsDataURL(file);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-beta.7/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="margin-top:20px;">
<label class="control-label">Add Background Image</label>
<input type="file" id="bg_image" />
</div>
<canvas id="canvas1" width="600" height="400" style="border:1px solid #000"></canvas>
Hi please update following code.
img.set({
width: canvas.getWidth(),
height: canvas.getHeight(),
originX: 'left',
scaleX : canvas.getWidth()/img.width, //new update
scaleY: canvas.getHeight()/img.height, //new update
originY: 'top'
});
http://jsfiddle.net/8vLo882n/6/
Related
I need to build a frame for my image in Fabric JS. This frame should be built dynamically to fit any size of the image.
To do this I use two images:
http://i.imgur.com/3VqKv1O.png - image for side
http://i.imgur.com/w41HYN3.png - image for corner
I've developed an algorithm, which does it and it works! That's great.
But I have a problem with the positioning of pieces of the frame.
As you can see in my example, there is strange space between pieces and they placed not on the same level by Y axis. I'm very surprised because these pieces have the same height and they have correct values for left and top.
Anybody knows what can be a reason of this problem?
Thanks in advance
JS Fiddle https://jsfiddle.net/Eugene_Ilyin/gzjxhLtm/9/
var sideObj = new fabric.Rect(),
frameSideTopImage = new fabric.Image(new Image(), {type: 'image'}),
frameCornerTLImage = new fabric.Image(new Image(), {type: 'image'}),
imageSize = 172,// Size of the image (width = height).
leftOffset = 100,
topOffset = 100;
// Load image for corner.
fabric.util.loadImage('http://i.imgur.com/w41HYN3.png', function (img) {
// Set image and options for top left corner.
frameCornerTLImage.setElement(img);
frameCornerTLImage.setOptions({
strokeWidth: 0,
left: leftOffset,
top: topOffset
});
// Load image for side.
fabric.util.loadImage('http://i.imgur.com/3VqKv1O.png', function (img) {
frameSideTopImage.setElement(img);
// Create canvas for pattern.
var canvasForFill = new fabric.StaticCanvas(fabric.util.createCanvasElement(), {enableRetinaScaling: false});
canvasForFill.add(frameSideTopImage);
// Configure top side for the frame.
sideObj.setOptions({
strokeWidth: 0,
objectCaching: false,
originX: 'left',
originY: 'top',
left: imageSize + 100,
top: 100,
width: 800,
height: imageSize,
fill: new fabric.Pattern({
source: function () {
canvasForFill.setDimensions({
width: imageSize,
height: imageSize
});
return canvasForFill.getElement();
},
repeat: 'repeat-x'
})
});
var canvas = new fabric.Canvas('c');
var frame = new fabric.Group([sideObj, frameCornerTLImage], {
strokeWidth: 0,
width: 800 * 3,
height: imageSize * 3,
scaleX: 1/3,
scaleY: 1/3,
}
);
canvas.add(frame);
canvas.renderAll();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.7/fabric.js"></script>
<body>
<canvas id="c" width="1000" height="1000"></canvas>
</body>
var sideObj = new fabric.Rect(),
frameSideTopImage = new fabric.Image(new Image(), {type: 'image'}),
frameCornerTLImage = new fabric.Image(new Image(), {type: 'image'}),
imageSize = 172,// Size of the image (width = height).
leftOffset = 100,
topOffset = 100;
// Load image for corner.
fabric.util.loadImage('http://i.imgur.com/w41HYN3.png', function (img) {
// Set image and options for top left corner.
frameCornerTLImage.setElement(img);
frameCornerTLImage.setOptions({
left: leftOffset,
top: topOffset
});
// Load image for side.
fabric.util.loadImage('http://i.imgur.com/3VqKv1O.png', function (img) {
frameSideTopImage.setElement(img);
// Create canvas for pattern.
var canvasForFill = new fabric.StaticCanvas(fabric.util.createCanvasElement(), {enableRetinaScaling: false});
canvasForFill.add(frameSideTopImage);
// Configure top side for the frame.
sideObj.setOptions({
objectCaching: false,
originX: 'left',
originY: 'top',
left: imageSize + 100,
top: 100,
width: 800,
strokeWidth:0,
height: imageSize,
fill: new fabric.Pattern({
source: function () {
canvasForFill.setDimensions({
width: imageSize,
height: imageSize
});
return canvasForFill.getElement();
},
repeat: 'repeat-x'
})
});
var canvas = new fabric.Canvas('c');
canvas.add(sideObj);
canvas.add(frameCornerTLImage);
canvas.renderAll();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.7/fabric.js"></script>
<body>
<canvas id="c" width="1000" height="1000"></canvas>
</body>
set strokeWidth:0 , strokeWidth is by default 1, so it creates a border of width 1 .
The following code will set background color and image to the canvas but I cant able to resize the uploaded image.
var canvas = new fabric.Canvas('canvas');
//To set canvas background color
canvas.setBackgroundColor('rgba(255,255,255,255)',canvas.renderAll.bind(canvas);
//To upload background image
var imageLoader = document.getElementById('upload-bgfile');
imageLoader.addEventListener('change', handleImage, false);
function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event){
var img = new Image();
img.onload = function(){
canvas.setBackgroundImage(img.src, canvas.renderAll.bind(canvas), {
originX: 'center',
originY: 'center',
left: 300,
top: 100,
});
};
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
canvas.renderAll();
you should refer code below,
canvas.setBackgroundColor({source: 'http://fabricjs.com/assets/escheresque_ste.png'}, canvas.renderAll.bind(canvas));
for more: http://jsfiddle.net/fabricjs/hXzvk/
Is it possible to mask two images using fabric js?
For example: I have a colored shape(heart). I have another images and I want to mask it over heart such that that new image is only displayed as heart. I can move the second uploaded image around and resize to get the desired area in that heart.
Both images are user uploaded images and not one of those rectangles or square which are created using fabric and drag and resize image like in the jsfiddle example here.
http://jsfiddle.net/Jagi/efmbrm4v/1/
var canvas = new fabric.Canvas('myCanvas');
var clippingRect = new fabric.Rect({
left: 0,
top: 0,
width: 100,
height: 100,
fill: 'transparent',
opacity: 1
});
canvas.add(clippingRect);
function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) {
var img = new Image();
img.onload = function () {
var instanceWidth, instanceHeight;
instanceWidth = img.width;
instanceHeight = img.height;
var imgInstance = new fabric.Image(img, {
width: instanceWidth,
height: instanceHeight,
top: (canvas.getHeight() / 2 - instanceHeight / 2),
left: (canvas.getWidth() / 2 - instanceWidth / 2),
originX: 'left',
originY: 'top'
});
canvas.add(imgInstance);
imgInstance.clipTo = function (ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.rect(
100, 100,
200, 200
);
ctx.restore();
};
canvas.renderAll();
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
I need exactly this but with two custom images(user uploaded images).
Maybe this pseudo example will give you pointer how to add mask with a path, not just a rectangle.
//adding main image and mask
fabric.Image.fromURL(IMAGE_URL_HERE, function(pic) {
canvas.add(pic);
//positioning image, if needed
pic.centerH().setCoords();
//adding path, may be a heart or any other in your case
var path = new fabric.Path('M1.398,84.129c3.305,20.461,9.73,50.635,13.591,67.385c2.354,10.212,12.549,23.734,18.51,30.02c4.923,5.191,27.513,23.343,38.34,27.589c18.604,7.295,33.984,4.187,46.012-8.306c12.028-12.493,25.595-34.78,27.954-43.994c2.587-10.105,5.065-26.842,4.313-37.243c-1.036-14.316-14.224-69.332-16.806-79.55c-4.48-17.735-26.246-48.821-80.609-37.668C-1.66,13.514-1.879,63.844,1.398,84.129z');
//positioning path, if needed
path.set({
originX: 'center',
originY: 'center',
});
//masking img with path
pic.set({
clipTo: function(ctx) {
path.render(ctx);
}
});
canvas.renderAll();
});
Full demo (for slightly another case though) here: http://jsfiddle.net/mqL55m0f/2/
I'm creating an Image Collage application in HTML5 canvas using Fabric.js. I want that user can drag and drop file to 'File Drag and Drop Area' and also he can 'Choose File' from his local disk. Please help me in implementing this.
I'm using this code to add multiple images. Now, I want to add images from my Local Disk onto Canvas.
//Image 1
fabric.Image.fromURL('/3.jpg', function (img) {
var oImg = img.set({ left: 300, top: 300, angle: -15 }).scale(0.9);
canvas.add(oImg).renderAll();
canvas.setActiveObject(oImg);
});
//Image 2
fabric.Image.fromURL('/bokeh.jpg', function (img) {
var oImg = img.set({ left: 300, top: 300, angle: -15 }).scale(0.9);
canvas.add(oImg).renderAll();
canvas.setActiveObject(oImg);
});
Hey I have the solution for drag and drop and choose file but not in one answer actually I have two different separate solutions
Drag and Drop:
http://jsfiddle.net/rodrigopandini/gj7HT/
Choose file:
<input type="file" id="imgLoader">
<canvas id="c" width="300" height="300"></canvas>
<script src="https://raw.github.com/kangax/fabric.js/master/dist/all.js"> </script>
<script type="text/javascript>
canvas = new fabric.Canvas('c');
document.getElementById('imgLoader').onchange = function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) { console.log('fdsf');
var imgObj = new Image();
imgObj.src = event.target.result;
imgObj.onload = function () {
// start fabricJS stuff
var image = new fabric.Image(imgObj);
image.set({
left: 250,
top: 250,
angle: 20,
padding: 10,
cornersize: 10
});
//image.scale(getRandomNum(0.1, 0.25)).setCoords();
canvas.add(image);
// end fabricJS stuff
}
}
reader.readAsDataURL(e.target.files[0]);
}
</script>
U can try it these codes in one script.
I have a simple fabric.canvas element which has a background and I have set its width and height equal to that of the above image.
and then added the cap image. the problem is that the resize controls are displaced. I have made this clear in the image too.
This is how I am adding the canvas to the page
$('#canvas_container').empty();
canvas_el = document.createElement('canvas');
canvas_el.id = "canvas";
$('#canvas_container').append(canvas_el);
canvas = new fabric.Canvas('canvas');
var img = new Image();
img.onload = function() {
canvas.setWidth(this.width);
canvas.setHeight(this.height);
canvas.renderAll()
}
img.src =$(this).attr('picUrl');
canvas.setBackgroundImage($(this).attr('picUrl'),function(){
canvas.renderAll();
});
And this is how I am adding the image
fabric.Image.fromURL('img/hat.png', function(img) {
oImg = img.set({ left: 50, top: 50, angle: 0 })
canvas.add(oImg);
canvas.renderAll();
});
I have got the answer on twitter.
I added a canvas.calcOffset() right after changing the width and height of the canvas and also adding the image.
It worked.
Try with oImg.setCoords() after canvas.add(oImg);