Recreate Fabric.js canvas and export as an image? - javascript

I have a canvas where the user can create a design using images in another div that they click, sending it to the Fabric.js canvas where it gets moved around and so on. Since the canvas's size is width="270"and height="519", smaller than what the finished product is, I need to recreate it with a canvas that has the size width="1001"and height="1920" and then screenshot it so that I get it all in 1 single image. How do I do this?
This is what my code looks like so far:
HTML
<div id="CanvasContainer">
<canvas id="Canvas" width="270" height="519"></canvas>
</div>
CSS
#CanvasContainer {
width: 270px;
height: 519px;
margin-left: 15px;
}
#Canvas {
overflow: hidden;
}
JAVASCRIPT
//Defining Canvas and object array
var canvas = new fabric.Canvas('Canvas');
//When clicked
$(document).ready(function () {
$("#Backgrounds img").click(function () {
var getId = $(this).attr("id");
//adding all clicked images
var imgElement = document.getElementById(getId);
var imgInstance = new fabric.Image(imgElement, {
left: 135,
top: 259,
width: 270,
height: 519
});
//Corner color for clicked images
imgInstance.set({
borderColor: 'white',
cornerColor: 'black',
transparentCorners: false,
cornerSize: 12
});
canvas.add(imgInstance);
});
});

Fabric has a built in function to convert to data urls. You can use the download property of a link to make the link a download link. Finally you can use the DOM click() function to emulate clicking the download link. The end result is:
function download(url,name){
// make the link. set the href and download. emulate dom click
$('<a>').attr({href:url,download:name})[0].click();
}
function downloadFabric(canvas,name){
// convert the canvas to a data url and download it.
download(canvas.toDataURL(),name+'.png');
}
now when you want to download the canvas call
downloadFabric(canvas,'<file name>');

Related

How to call a specific image from an array to a parameter in Vanilla JavaScript?

I am trying to make a point and click adventure game in HTML Canvas for Games for Change.
I wanted to make my background images responsive/change resolution to the canvas size so I got some code from this link: Simulation background-size: cover in canvas.
I have multiple images for backgrounds of different scenes. So I put them all inside an array. However, I have this error where it says "Image is not defined" for the function call.
How do I call 1 of those background images to display on the canvas with the user1693593's function call?
I am going to take this call to make a scene with buttons and text.
CSS:
#gameCanvas {
width: 960px;
height: 640px;
border: 5px solid rgba(52,52,52,1.00);
background-color: rgba(241,213,179,1.00);
}
JS
/**Array of Images**/
var imgArray = {
image00: 'gameImages/titleScreen.png',
image01: 'gameImages/titleScreen1.png',
image02: 'gameImages/titleScreenBW.png',
image03: 'gameImages/startScreen.png',
image04: 'gameImages/startScreenBW.png',
image05: 'gameImages/forestTrail.png',
image06: 'gameImages/forestTrailBW.png',
image07: 'gameImages/jewleryOnLog.png',
image08: 'gameImages/jewleryOnLogBW.png',
image09: 'gameImages/sunlitWaterFall.png',
image10: 'gameImages/sunlitWaterFalBW.png',
image11: 'gameImages/sunlitWaterFall.png',
image12: 'gameImages/sunsetStarySky.png',
image13: 'gameImages/sunsetStarySkyBW.pn',
image14: 'gameImages/campSunset.png',
image15: 'gameImages/campSunsetBW.png',
image16: 'gameImages/LoveHeart.png',
image17: 'gameImages/LoveHeartBW.png',
image18: 'gameImages/nightSky2BW.png',
image19: 'gameImages/nightSky2.png',
image20: 'gameImages/nightSkyAnimate.gif'
};
drawImageProp(ctx, image, 0, 0, width, height);
Update on Array Edit
/**Array of Images**/
var imgArray = [
"gameImages/titleScreen.png",
"gameImages/titleScreen1.png",
"gameImages/titleScreenBW.png",
"gameImages/startScreen.png",
"gameImages/startScreenBW.png",
"gameImages/forestTrail.png",
"gameImages/forestTrailBW.png",
"gameImages/jewleryOnLog.png",
"gameImages/jewleryOnLogBW.png",
"gameImages/sunlitWaterFall.png",
"gameImages/sunlitWaterFalBW.png",
"gameImages/sunlitWaterFall.png",
"gameImages/sunsetStarySky.png",
"gameImages/sunsetStarySkyBW.pn",
"gameImages/campSunset.png",
"gameImages/campSunsetBW.png",
"gameImages/LoveHeart.png",
"gameImages/LoveHeartBW.png",
"gameImages/nightSky2BW.png",
"gameImages/nightSky2.png",
"gameImages/nightSkyAnimate.gif"
];

Fabric JS Events On Canvas Objects

I'm loading a base 64 image into a canvas using the fabric.js API. What I need to be able to do is determine when an object on the canvas gets resized. I can't find any documentation on eventing on objects on a canvas. Is there a way to listen to events on these objects? Listening to resize on canvas or window is not working:
$("canvas").on("resize", function () {
console.log("Resize occurred"); //not called
});
What you are looking for here is not a resize event on the canvas, which will not trigger unless you resize the canvas element itself is, but a resize event on an object rendered on the canvas. Since you are using fabricjs to render your image you can listen to fabricjs events to get your desired result. Overview of all fabricjs events you can find here. In your case object:scaled would be the event to listen to. The following runnable code snippet illustrates an example:
const canvas = new fabric.Canvas('canvas', {
selection: false
});
const imageElement = document.getElementById('image');
const img = new fabric.Image(imageElement, {
left: 20,
top: 20,
scaleX: 1,
scaleY: 1
});
canvas.add(img);
canvas.on('object:scaled', (options) => {
console.log(
"Object was scaled, current scaleX:",
options.target.scaleX,
" and scaleY: ",
options.target.scaleX)
});
canvas {
border: 1px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.min.js"></script>
<canvas id="canvas" width="300" height="200"></canvas>
<img style="display: none" id="image" src="https://images.unsplash.com/photo-1507146426996-ef05306b995a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=200&q=80" />

Getting current cursor position on the clicked object in Fabric.js

I am developing a Web application that involves HTML canvas feature. I am using Fabric.JS - http://fabricjs.com/ to render objects on it. In Fabric.Js, I can implement event listeners to the object as in this link- http://fabricjs.com/.
I am now adding an image object to the canvas and implement the mouse event listener to that image object. When the image object on the canvas is clicked, I would like to retrieve the position (x, y) of the image clicked. But it is always returning zero.
I am adding image object to the canvas like this:
var imgInstance = new fabric.Image(js_left_temp_img, {
left: 0,
top: 0
});
imgInstance.scale(0.1)
imgInstance.selectable = false;
imgInstance.set('selectable', false)
$canvas.add(imgInstance);
Then I set up the event listener to the image object like this and try to retrieve the clicked position of image object like this.
imgInstance.on('mousedown', function(e){
//alert('Image clicked')
console.log(e.target.left + " - " + e.target.top)
});
When I click on the image, it fires the event, but the left and top values are always returning zero. How can I retrieve the current clicked left and top or x and y position of the image in the event listener?
Use object.getLocalPointer()
DEMO
var canvas = new fabric.Canvas('canvas'),imgInstance;
canvas.on('object:selected', function(e) {
});
fabric.Image.fromURL('http://fabricjs.com/assets/pug.jpg', function(img) {
img.set({
left: 0,
top: 0,
scaleX: 0.3,
scaleY: 0.3
});
canvas.add(img);
img.on('mousedown',function(options){
var pointer = this.getLocalPointer(options.e);
console.log(pointer);
})
});
canvas{
border:2px solid #000;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id='canvas' width=500 height=400>

Change loaded source color

I've a rect created on canvas. After creating, i change the background pattern with test.svg. It's working, there's no problem here. What i want to do is to change the color of background pattern. Inside svg, i have a dot. i only want to change the dot color inside svg but not like "fill:color", just the dot. is this possible? i looked for sth like source color etc. but i couldn't find a solution.
var test = new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
});
test.fill = new fabric.Pattern({
source: "test.svg",
repeat: 'repeat',
});
// add canvas etc here...
// change the color of svg pattern. should be something like test.source.color?
I never used fabric.Pattern() but I guess it's just an other way to make context.createPattern()`.
For this, you have to first load the svg into an <img> tag. This action will block certain capacities over the svg document, like changing the color of inner elements by any external mean.
The only solution, is then to load an other document into an other <img> tag (or here into an other fabric.Pattern() object), which already has the right color.
One way of avoiding having a lot of svg files with only small changes, is to load once the svg, not in an <img> tag (it can be directly into the document, with a DOMParser, an <object> or an <iframe>), then edit your document with desired changes, and pass its dataURI version to the fabric.Pattern Constructor.
var changeSVGColor = function(color) {
// update the color
SVGCircle.setAttribute('fill', color);
// get the svg data as a string
var svgData = (new XMLSerializer()).serializeToString(svg);
// transfrom it to a dataURL
var svgURL = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
return svgURL;
}
var loadPattern = function(url) {
fabric.util.loadImage(url, function(img) {
test.fill = new fabric.Pattern({
source: img,
repeat: 'repeat'
});
canvas.renderAll();
});
}
var canvas = new fabric.Canvas('c');
var test = new fabric.Rect({
left: 0,
top: 0,
width: 300,
height: 300,
});
canvas.add(test);
loadPattern(changeSVGColor('blue'));
btn.onclick = function() {
loadPattern(changeSVGColor('red'));
}
#svg {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.js"></script>
<svg id="svg" width="20" height="20">
<circle id="SVGCircle" cx="10" cy="10" r="10" />
</svg>
<button id="btn">change color</button>
<canvas id="c"></canvas>

How save image with canvas in fabric.js

I am creating an application for T-shirt customization in which I have put the canvas on image using CSS, but the problem is saving that image as canvas. toDataURL just gives part of the canvas area, but I want the whole image. There are other solutions on Stack Overflow but they do not solve this problem.
Hello,
you have to create an image object (tshirt) with a text object that holds the message.
to do that , load the image with fabric.Image.fromURL() function and inside the function , also create a text object that is going to show the tshirt message.
so, your image and text belong to a group object.
every time you want to load new text , you call the loadText function and you change the text object.
i also added 4 buttons in order to manupulate up/down/left/right the text .
you can export the canvas + image+ text into the function saveImg(),
but on the jsfiddle you will get a security message for Tained canvases.
that happens because on the example i load the image from another domain and the code runs on another domain, you can run that code on your web application with no problem at all.
that is the code :
var canvas = new fabric.Canvas('c');
var scaleFactor=0.4
canvas.backgroundColor = 'yellow';
canvas.renderAll();
var myImg = 'http://izy.urweb.eu/files/tshirt.jpg';
fabric.Image.fromURL(myImg, function(myImg) {
var img1 = myImg.scale(scaleFactor).set({ left: 0, top: 0 });
var text = new fabric.Text('the_text_sample\nand more', {
fontFamily: 'Arial',
fontSize:20,
});
text.set("top",myImg.height*scaleFactor-myImg.height*scaleFactor+150);
text.set("left",myImg.width*scaleFactor/2-text.width/2);
var group = new fabric.Group([ img1,text ], { left: 10, top: 10 });
canvas.add(group);
});
$('#loadText').on('click',loadText);
$('#saveImg').on('click',saveImg);
function loadText(){
console.log($('#logo').val());
canvas._objects[0]._objects[1].text = $('#logo').val();
canvas.renderAll();
}
function saveImg(){
console.log('export image');
if (!fabric.Canvas.supports('toDataURL')) {
alert('This browser doesn\'t provide means to serialize canvas to an image');
}
else {
window.open(canvas.toDataURL('png'));
}
}
$('#left').on('click',function(){
canvas._objects[0]._objects[1].set('left',canvas._objects[0]._objects[1].left-1);
canvas.renderAll();
})
$('#right').on('click',function(){
canvas._objects[0]._objects[1].set('left',canvas._objects[0]._objects[1].left+1);
canvas.renderAll();
})
$('#top').on('click',function(){
canvas._objects[0]._objects[1].set('top',canvas._objects[0]._objects[1].top-1);
canvas.renderAll();
})
$('#bottom').on('click',function(){
canvas._objects[0]._objects[1].set('top',canvas._objects[0]._objects[1].top+1);
canvas.renderAll();
})
that is the jsfiddle example: http://jsfiddle.net/tornado1979/zrazuhcq/1/
hope helps, good luck.

Categories

Resources