fabric.js
Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) Parser
Fabric.js Javascript Canvas Library
HTML:
<div class="canvas-wrapper">
<canvas id="myCanvas"></canvas>
</div>
CSS
.canvas-wrapper {
width: 900px;
min-height: 600px;
}
#myCanvas{
border:1px solid red;
position: absolute;
top:22px;
left:0px;
eight: 100%;
width: 99%;
}
JS
var myCanvas = new fabric.Canvas('myCanvas');
My canvas get resized to 300x150 after it's been initialized, why?
Source: (StackOverflow)
I've read 3-5 topics about mouse offset, but i still can't get where is the mess.
In my case everything works fine in 60%. In other 40% mouse is offset. Demo here.
Sometimes object position doesn't relate to mouse behavior. (IE & Chrome have the bigest mess)
I've tried to edit stylesheets and parent div but nothing. The worst thing: i don't see any regularity. I will be greatful for any help.
Source: (StackOverflow)
I'm using Fabric.js and I've created a fabric canvas object at one place.
var x = new fabric.Canvas("mycanvas");
Now at another place, I want to access this object where 'x' won't be available. So how can I get the same fabric canvas object.
I don't wanna change the scope of x or pass x as arg.
Also, how to get the toDataURL from the fabric canvas object?
Source: (StackOverflow)
I got lots of simple apps or examples that are built using Fabric.js.
Can I use Fabric.js for making advanced applications? I want to check some apps and see it's performance so that I would confirm that Fabric.js can handle big apps too.
Source: (StackOverflow)
I have a simple AngularJS / FabricJs application, the intent is to allow an image to be moved /re-sized prior to upload. Essentially four steps:
1) I present a form with a canvas, and a rectangle inside of form to represent a clip area
2) browse for a local file
3) add it to the canvas
4) and have a button to capture the clip area inside of the canvas
The problem occurs when I move the code from a directly embedded form to sitting behind an angular directive. Once I moved the form into the directive an issue popped up, the image is loaded and added to the canvas without (any obvious) issues. However once you click anywhere on the canvas (for instance, in an attempt to move the image) the image you added no longer appears on the canvas (although inspection of the fabricJs Canvas object still shows it as inside of its object array).
The JS App and helper:
var myApp = angular.module('myApp', [])
// helper function to bind tot he on change of a input/file object (angularJs workaround)
var invokeImageChange = function(that) {
angular.element(that).scope().imageChange(that)
angular.element(that).scope().$digest();
}
Controller:
var ImageCtrl = function($scope) {
var desiredHeight = 300
var desiredWidth = 770
// I understand this docucment.gelElementById is not the angular way - and needs to be changed
var myImageData = document.getElementById('fileData')
var myImage = document.getElementById('myImage')
var canvas = new fabric.Canvas('myCanvas')
var rect = new fabric.Rect({
fill: 'lightgray',
left: canvas.width / 2,
top: canvas.height / 2,
width: desiredWidth,
height: desiredHeight,
stroke: 'darkgray',
strokeDashArray: [5, 5],
selectable: false
});
canvas.add(rect)
var clipZone = {
y: rect.top - (.5 * rect.height),
x: rect.left - (.5 * rect.width),
width: desiredWidth,
height: desiredHeight,
quality: 1
}
$scope.caption = "" ;
$scope.fileUrl = "" ;
$scope.imageChange = function(inp) {
console.log('imageChange')
file = inp.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
var img = null
function createImage() {
console.log('createImage')
img = new Image();
img.onload = imageLoaded;
img.src = fr.result;
}
function imageLoaded() {
console.log('imageLoaded')
var fabImg = new fabric.Image(img)
fabImg.scale(1.0).set({
left: canvas.width / 2,
top: canvas.height / 2
});
canvas.add(fabImg)
canvas.setActiveObject(fabImg)
}
}
$scope.submit = function(event) {
}
$scope.capture = function() {
console.log('capture')
}
}
The Directive code:
myApp.directive('ngImageEditor', function() {
return {
restrict: 'E',
transclude: true,
replace: true,
controller: 'ImageCtrl',
templateUrl: '\blah\pathToForm'
};
});
where the TemplateUrl refers to this form
<form name="uploadForm" ng-controller="ImageCtrl" method="post" enctype="multipart/form-data"
action="/main/update" ng-submit="submit()">
<div class="control-group">
<label class="control-label" for="file">Image File</label>
<div class="controls">
<input type="file" name="file" ng-model="file" onchange="invokeImageChange(this)"/>
<input type="text" id="fileData" name="fileData" ng-model="fileUrl"/>
</div>
</div>
<div class="control-group">
<div class="controls">
<input type="button" value="Upload" ng-click="capture()"/>
</div>
</div>
<div>
<canvas id="myCanvas" width="800" height="400" style="border:1px solid #000000;"></canvas>
</div>
<img id="myImage" style="border: 1px solid burlywood">
</form>
Hopefully the JsFiddle below helps folks understand what I am talking about. Thanks in advance!
To reproduce
1) browse to an image
2) move the image (notice the image disappears in the second link)
Working (image can be moved) (without directive):
http://jsfiddle.net/PNwbp/1/
Broken / Issues (image disappears when moved) (with directive):
http://jsfiddle.net/faFVW/23/
Source: (StackOverflow)
I'm trying to create a block game where you select shapes from a menu and place them on the canvas. There is a shape menu where you can drag the shapes onto the canvas. I would like for it to leave the main shape in the menu as it drags a clone onto the canvas. Is this possible? I have created a jsfiddle to help.
JSFIDDLE
window.canvas = new fabric.Canvas('fabriccanvas');
var edgedetection = 10; //pixels to snap
canvas.selection = false;
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.setHeight(window.innerHeight);
canvas.setWidth(window.innerWidth);
canvas.renderAll();
}
// resize on init
resizeCanvas();
//Initialize Everything
init();
function init(top, left, width, height, fill) {
var bg = new fabric.Rect({
left: 0,
top: 0,
fill: "#eee",
width: window.innerWidth,
height: 75,
lockRotation: true,
maxHeight: document.getElementById("fabriccanvas").height,
maxWidth: document.getElementById("fabriccanvas").width,
selectable: false,
});
var squareBtn = new fabric.Rect({
top: 6,
left: 18,
width: 40,
height: 40,
fill: '#af3',
lockRotation: true,
originX: 'left',
originY: 'top',
cornerSize: 15,
hasRotatingPoint: false,
perPixelTargetFind: true,
});
var circleBtn = new fabric.Circle({
radius: 20,
fill: '#f55',
top: 6,
left: 105,
});
var triangleBtn = new fabric.Triangle({
width: 40,
height: 35,
fill: 'blue',
top: 10,
left: 190,
});
var sqrText = new fabric.IText("Add Square", {
fontFamily: 'Indie Flower',
fontSize: 14,
fontWeight: 'bold',
left: 6,
top: 50,
selectable: false,
});
var cirText = new fabric.IText("Add Circle", {
fontFamily: 'Indie Flower',
fontSize: 14,
fontWeight: 'bold',
left: 95,
top: 50,
selectable: false,
});
var triText = new fabric.IText("Add Triangle", {
fontFamily: 'Indie Flower',
fontSize: 14,
fontWeight: 'bold',
left: 175,
top: 50,
selectable: false,
});
var shadow = {
color: 'rgba(0,0,0,0.6)',
blur: 3,
offsetX: 0,
offsetY: 2,
opacity: 0.6,
fillShadow: true,
strokeShadow: true
}
window.canvas.add(bg);
bg.setShadow(shadow);
window.canvas.add(sqrText);
window.canvas.add(cirText);
window.canvas.add(triText);
window.canvas.add(squareBtn);
window.canvas.add(circleBtn);
window.canvas.add(triangleBtn);
canvas.forEachObject(function (e) {
e.hasControls = e.hasBorders = false; //remove borders/controls
});
this.canvas.on('object:moving', function (e) {
var obj = e.target;
obj.setCoords(); //Sets corner position coordinates based on current angle, width and height
canvas.forEachObject(function (targ) {
activeObject = canvas.getActiveObject();
if (targ === activeObject) return;
if (Math.abs(activeObject.oCoords.tr.x - targ.oCoords.tl.x) < edgedetection) {
activeObject.left = targ.left - activeObject.currentWidth;
}
if (Math.abs(activeObject.oCoords.tl.x - targ.oCoords.tr.x) < edgedetection) {
activeObject.left = targ.left + targ.currentWidth;
}
if (Math.abs(activeObject.oCoords.br.y - targ.oCoords.tr.y) < edgedetection) {
activeObject.top = targ.top - activeObject.currentHeight;
}
if (Math.abs(targ.oCoords.br.y - activeObject.oCoords.tr.y) < edgedetection) {
activeObject.top = targ.top + targ.currentHeight;
}
if (activeObject.intersectsWithObject(targ) && targ.intersectsWithObject(activeObject)) {
} else {
targ.strokeWidth = 0;
targ.stroke = false;
}
if (!activeObject.intersectsWithObject(targ)) {
activeObject.strokeWidth = 0;
activeObject.stroke = false;
activeObject === targ
}
});
});
}
Source: (StackOverflow)
see below link
http://liveweave.com/JckSgC
when I try to drag drop items item gets stuck somewhere on mobile screen without being dropped to droppable area,
and when I click somewhere and screen it starts working (this basically happened once I open page for first time)
what could be the issue and how do I resolve it?
below is code
js code
(function () {
var canvas = new fabric.Canvas('canvas');
var canvas_el = document.getElementById('canvas');
var canvas1 = new fabric.Canvas('canvas1');
var group;
fabric.Image.fromURL('img/blank.png', function (img) {
var img1 = img.set({
left: 0,
top: 0
});
fabric.Image.fromURL('img/blank.png', function (img) {
var img2 = img.set({
left: 0,
top: 0
});
group = new fabric.Group([img1, img2], {
left: 0,
top: 0
});
canvas.add(group)
});
});
fabric.Image.fromURL('img/blank.png', function (img) {
var img1 = img.set({
left: 0,
top: 0
});
fabric.Image.fromURL('img/blank.png', function (img) {
var img2 = img.set({
left: 0,
top: 0
});
group1 = new fabric.Group([img1, img2], {
left: 0,
top: 0
});
canvas1.add(group1)
});
});
$(document).ready(function () {
/* Define drag and drop zones */
var $drop = $('#canvas-drop-area,#canvas-drop-area1'),
$gallery = $('td > #image-list li'),
$draggedImage=null;
/* Define the draggable properties */
$gallery.draggable({
helper: 'clone',
start: function (e) {
$draggedImage=event.target;
$drop.css({
'display': 'block'
})
},
stop: function () {
$(this).find('img').css({
/* 'opacity': 0.4 */
});
$drop.css({
'display': 'none'
});
$draggedImage=null;
},
revert: true
});
/* Define the events for droppable properties */
$drop.droppable({
over: function (event, ui) {
$(this).addClass('active');
},
drop: function (event, ui) {
var image =$draggedImage&& $draggedImage.src;
console.log($draggedImage.alt);
img_to_canvas(image,$draggedImage.alt,$(event.target).is("#canvas-drop-area")?1:2);
},
out: function (event, ui) {
$(this).removeClass('active');
},
deactivate: function (event, ui) {
$(this).removeClass('active');
}
});
});
var img_to_canvas = function(image,sendfront,checkcanvas) {
var img = new Image();
img.src = image;
if(checkcanvas =='1'){
if(sendfront=='top'){
fabric.util.loadImage(img.src, function (img) {
group.item(0).setElement(img);
canvas.renderAll();
});
}else{
fabric.util.loadImage(img.src, function (img) {
group.item(1).setElement(img);
canvas.renderAll();
});
}
canvas.calcOffset();
}else{
if(sendfront=='top'){
fabric.util.loadImage(img.src, function (img) {
group1.item(0).setElement(img);
canvas1.renderAll();
});
}else{
fabric.util.loadImage(img.src, function (img) {
group1.item(1).setElement(img);
canvas1.renderAll();
});
}
canvas1.calcOffset();
}
}
})();
Source: (StackOverflow)
I'd like to be able to save the current canvas' state to a server-side database, probably as a JSON string, and then later restore it with loadFromJSON
. Typically, this is easily accomplished using:
var canvas = new fabric.Canvas();
function saveCanvas() {
// convert canvas to a json string
var json = JSON.stringify( canvas.toJSON() );
// save via xhr
$.post('/save', { json : json }, function(resp){
// do whatever ...
}, 'json');
}
And then
function loadCanvas(json) {
// parse the data into the canvas
canvas.loadFromJSON(json);
// re-render the canvas
canvas.renderAll();
// optional
canvas.calculateOffset();
}
However, I've also been setting a few custom attributes on the fabric objects I'm adding to the canvas using the builtin Object#set
method:
// get some item from the canvas
var item = canvas.item(0);
// add misc properties
item.set('wizard', 'gandalf');
item.set('hobbit', 'samwise');
// save current state
saveCanvas();
The problem is that when I check the request on the server-side, I see that my custom attributes were not parsed from the canvas and sent along with everything else. This probably has to do with how toObject
method removes anything that's not a default attribute in the object class. What would be a good way to tackle this issue, such that I'll be able to both save and restore the canvas from a JSON string sent by the server, and the restored canvas will also include my custom attributes? thanks.
Source: (StackOverflow)
I'm using FabricJS and I encounter a problem with the display of my SVG in the canvas:
- the result is displayed outside the selection box of fabricJS (due to a translation ?)
- the anchors of the selection disappear after a transformation and then it's impossible to find them back.
Here is a screenshot :
I'm using an output SVG of Potrace and I think it's the origin of my issue.
Here is the code of the SVG: SVG code in pastebin
You can test it with FabricJS on this page: FabricJS Kitchensing example.
Just paste the code of the SVG in the "Load SVG" area, then resize and rotate the section box to display the SVG.
Do you know the part of my SVG code or the part of the fabricjS code that causes the issue ?
If so, can I change it easily by myself ? If not, is it possible for anybody to correct or locate the possible mistake?
Thank you very much for your help.
EDIT: seemingly, FabricJS doesn't like this line of the SVG:
<g transform="translate(0,648) scale(0.098780,-0.098780)" fill="#000000" stroke="none">
And more especially the translate and scale attributesā¦ How to fix it?
EDIT2: the solution would be that the translate and the scale are respectively equal to (0,0) and (1,1) or, better, that they're applied to the coordinates.
Does anybody have an idea to do that with Potrace or JS script?
Source: (StackOverflow)
I want to save canvas as PNG, without opening it in a new window as base64-encoded image.
I used this code:
jQuery("#btnPreview").click(function(){
if (!fabric.Canvas.supports('toDataURL')) {
alert('Sorry, your browser is not supported.');
}
else {
canvas.deactivateAll();
canvas.forEachObject(function(o){
if(o.get("title") == "||Watermark||"){
canvas.bringToFront(o);
}
});
window.open(canvas.toDataURL('png'), "");
canvas.forEachObject(function(o){
if(o.get("title") == "||Watermark||"){
canvas.sendToBack(o);
}
});
canvas.renderAll();
}
});
I want to make the button save the image as a PNG or JPG.
Source: (StackOverflow)
I'm actually working on a html5 canvas project which uses the fabric.js Framework for the canvas interactions. Now I'm struggeling with the deletion of multiple objects. The following code does not seem to track the selected objects, but tracks all objects on the canvas.
var deleteSelectedObject = document.getElementById('delete-item');
deleteSelectedObject.onclick = function(){
var curSelectedObjects = new Array();
curSelectedObjects = canvas.getObjects(canvas.getActiveGroup);
canvas.discardActiveGroup();
for (var i = 0; i < curSelectedObjects.length; i++){
canvas.setActiveObject(curSelectedObjects[i]);
canvas.remove(canvas.getActiveObject());
}
};
Don't get my failure.
Source: (StackOverflow)
I would like to know if there is an easy way to add a delete, bring to front, bring to back
function into the existing fabric.js object controls.
At the moment I can only click on buttons which would delete object, bring to front etc.
I am working on finding a solution to be able to press X (on the upper right corner) on the object and delete the object.
I guess it will have to do with overwriting, wrapping or subclassing the existing control object.
Maybe I have overseen something and there is an easy solution? Please no Div Wrapper.
Source: (StackOverflow)
When using 'canvas = new fabric.Canvas('foo')', Fabric converts the canvas element that has a css class with width=100% attached to it into something like that:
<div class="canvas-container" style="position: relative" width="293px">
<canvas class="upper-canvas"></canvas>
<canvas class="lower-canvas" id="c"></canvas>
</div>
The wrapping div as well as both canvas elements are getting style tags and fixed width/height. In terms of initialization, IĀ“ve only found canvas.setWdith which only takes numeric values though (no percent values).
Is there a way to initialize Fabric to respect/use the given 100% width?
Update:
Example: http://jsfiddle.net/thomasf1/kb2Hp/
Source: (StackOverflow)