Image shrink resizing using fabric js - javascript

I am using fabric js. After editing and saving Image it is shrinking in canvas and loosing quality.
This is code using while saving and sending through ajax call.
c.discardActiveGroup().renderAll();
var objs = c.getObjects().map(function(o) {
return o.set({'active': false, hasBorders: false});
});
var group = new fabric.Group(objs, {
originX: 'center',
originY: 'center',
strokeWidth : 0
});
var cloneGroup = new fabric.Group(objs, {
originX: 'center',
originY: 'center',
strokeWidth : 0
});
cloneGroup.scaleToWidth(imgWidth-1);
var dataURL = cloneGroup.toDataURL({
format: 'png',
left: 1,
top: 1,
width: imgWidth,
height: imgHeight
});
saveAjaxCall(dataURL, flagBit);
group._restoreObjectsState();
c.remove(cloneGroup);
c.renderAll();

Related

How to add a border radius to a Textbox in FabricJS

I can't add border radius to Textbox using FabricJS and make it working with edit text.
I Added a Textbox into FabricJS, i used a snippet to add background color to padding.
The only way it worked, i added a rect and grouped it with Textbox, when i did it, the edit was gone.
I created a fiddle for it:
canvas = new fabric.Canvas('main-canvas', {
allowTouchScrolling: true
});
context = canvas.getContext("2d");
var textbox = new fabric.Textbox('Test', {
left: (canvas.width - 150) / 2, // 150 is width of text box
top: (canvas.height - 25) / 2, // 25 is height of text box
width: 150,
fontSize: 20,
fontFamily: 'rubik',
originX: 'center',
originY: 'center',
rx: 10,
ry: 10,
textAlign: 'center',
fill: "#ffffff",
backgroundColor: '#ffffff',
textBackgroundColor: '#ffffff',
padding: 10
});
textbox.setGradient('fill', {
x1: -textbox.width / 2,
y1: 0,
x2: textbox.width / 2,
y2: 0,
colorStops: {
0: "black",
0.5: "red",
1: "blue"
}
});
textbox.setControlsVisibility({
mt: false,
mb: false,
ml: false,
mr: false,
bl: false,
br: false,
tl: false,
tr: false,
mtr: false
});
textbox.set({ // enable padding background color
_getNonTransformedDimensions(){ // Object dimensions
return new fabric.Point(this.width, this.height).scalarAdd(this.padding);
},
_calculateCurrentDimensions(){ // Controls dimensions
return fabric.util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true);
}
});
textbox.borderColor = "#fff";
canvas.add(textbox).setActiveObject(textbox);
canvas.renderAll();
body{
background: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.js"></script>
<div id="canvas-container">
<canvas id="main-canvas" width="300" height="300"></canvas>
</div>
I want the text to have a border radius and able to edit the text.

Unable to add an image to fabric js group

Hello i am trying to add an image to a group of circle and text, and finally add the group to the canvas but it is failling to show the image.
Can anyone tell me what is the problem ?
Here is the snippets
const canvas = new fabric.Canvas('canvas', {
selection: false
});
const circle = new fabric.Circle({
left: 100,
top: 100,
radius: 50,
fill: '#eef',
originX: 'center',
originY: 'center'
});
const img = new Image();
img.src = '/Content/assets/img/logo.png';
const newImage = new fabric.Image(img, {
left: circle.left + 15,
top: circle.top,
perPixelTargetFind: true,
padding: 2,
hasBorders: false,
hasControls: false,
width: 20,
height: 30,
originX: 'center',
originY: 'center',
});
const text = new fabric.Text('Hello World', {
left: circle.left,
top: circle.top,
fontFamily: 'Arial',
fontWeight: 'bold',
fontSize: 10,
fill: 'black',
originX: 'center',
originY: 'center',
});
const group = new fabric.Group([circle, text, newImage], {
left: circle.left,
top: circle.top,
originX: 'center',
originY: 'center'
});
canvas.add(group);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.0.0/fabric.min.js"></script>
<canvas id="canvas" width="500" height="300" style="border: 2px solid green;"></canvas>
Because you are passing the image object instead of the source. Do this
fabric.Image.fromURL('http://placekitten.com/200/300', function(img) {
canvas.add(img1);
});
const canvas = new fabric.Canvas('canvas', {
selection: false
});
fabric.Image.fromURL('http://placekitten.com/200/300', function(img) {
var img1 = img.set({ left: 0, top: 0 ,width:200, height:350});
canvas.add(img1);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.0.0/fabric.min.js"></script>
<canvas id="canvas" width="500" height="300" style="border: 2px solid green;"></canvas>
new fabric.Image(img, here img should be a string. Not an Image instance
To add that image in the group, do
let ImageInstance;
fabric.Image.fromURL('http://placekitten.com/200/300', function(img) {
var img1 = img.set({ left: 0, top: 0 ,width:200, height:350});
ImageInstance = img1;
});
if (ImageInstance){
const group = new fabric.Group([circle, text, ImageInstance], {
left: circle.left,
top: circle.top,
originX: 'center',
originY: 'center'
});
canvas.add(group);
}

FabricJS canvas objects group is being hidden when adding its clone to another canvas

I try to export a group of objects from a canvas to svg. To do so, I clone the group in another canvas (which will have the same height/width of the group).It works very well. But the problem is the group becomes hidden in the original canvas, I don't know why.
here is the code:
this.__canvas = new fabric.Canvas('meCanvas', {
preserveObjectStacking: true,
height: 300,
width: 200,
backgroundColor: '#1F1F1F',
canvasKey:'azpoazpoaz'
});
let newID = (new Date()).getTime().toString().substr(5);
let rect = new fabric.Rect({
fill: 'red',
width: 48,
height: 32,
left: 100,
top: 100,
originX: 'center',
originY: 'center',
fontWeight: 'normal',
myid: newID
});
let newID1 = (new Date()).getTime().toString().substr(5);
let text = new fabric.IText('Text', {
fontFamily: 'Times',
fontSize: 18,
fill: 'white',
left: 100,
top: 100,
originX: 'center',
originY: 'center',
fontWeight: 'normal',
myid: newID1,
objecttype: 'text'
});
this.__canvas.add(rect);
this.__canvas.add(text);
this.__canvas.renderAll();
$('#generate').click((e)=>{
let obj = this.__canvas.getActiveObject();
if(!obj) return;
let obj1 = $.extend(true, {}, obj);
this.tempCanvas = new fabric.Canvas('tempCanvas', {
canvasKey:'efsdfsd',
preserveObjectStacking: true,
height: obj1.getScaledHeight(),
width: obj1.getScaledWidth()
});
obj1.left= 0;
obj1.top=0;
this.tempCanvas.add(obj1);
let mySVG = this.tempCanvas.toSVG();
//console.log(this.tempCanvas.toSVG());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<div style='display: inline-block'>
<div>
<canvas id='meCanvas' ref='meFabric'/>
</div>
<div>
<button id='generate'>Generate the SVG</button>
</div>
<div style='display: inline-block'>
<div id="rect"></div>
<div id="recttext"></div>
</div>
</div>
If you select both the text and the red rectangle at once, and then click on the button "Generate the SVG", and then click on the canvas again, the group will disappear. And I don't know why.
Please how to fix it ?
To copy an object use obj.clone() instead of $.extend
EXAMPLE
this.__canvas = new fabric.Canvas('meCanvas', {
preserveObjectStacking: true,
height: 300,
width: 200,
backgroundColor: '#1F1F1F',
canvasKey: 'azpoazpoaz'
});
let newID = (new Date()).getTime().toString().substr(5);
let rect = new fabric.Rect({
fill: 'red',
width: 48,
height: 32,
left: 100,
top: 100,
originX: 'center',
originY: 'center',
fontWeight: 'normal',
myid: newID
});
let newID1 = (new Date()).getTime().toString().substr(5);
let text = new fabric.IText('Text', {
fontFamily: 'Times',
fontSize: 18,
fill: 'white',
left: 100,
top: 100,
originX: 'center',
originY: 'center',
fontWeight: 'normal',
myid: newID1,
objecttype: 'text'
});
this.__canvas.add(rect);
this.__canvas.add(text);
this.__canvas.renderAll();
$('#generate').click((e) => {
let obj = this.__canvas.getActiveObject();
if (!obj) return;
obj.clone(function(clonedObj) {
let obj1 = clonedObj;
this.tempCanvas = new fabric.Canvas('tempCanvas', {
canvasKey: 'efsdfsd',
preserveObjectStacking: true,
height: obj.getScaledHeight(),
width: obj.getScaledWidth()
});
obj1.left = 0;
obj1.top = 0;
this.tempCanvas.add(obj1);
let mySVG = this.tempCanvas.toSVG();
})
//console.log(this.tempCanvas.toSVG());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<div style='display: inline-block'>
<div>
<canvas id='meCanvas' ref='meFabric'/>
</div>
<div>
<button id='generate'>Generate the SVG</button>
</div>
<div style='display: inline-block'>
<div id="rect"></div>
<div id="recttext"></div>
</div>
</div>

FabricJS is not support russian letters

I have a trouble with FabricJS. When I create a russian text with follow constructor, I have no russian text only symbol '!'.
What am I doing wrong?
var textObject = new fabric.Text('Привет!', {
originX: 'center',
originY: 'center',
left: zone.left,
top: zone.getCenterPoint().y,
textAlign: 'center',
fill: finalFill,
stroke: '#000',
strokeWidth: bezel,
fontSize: fontSize,
spacing: 5,
fontFamily: 'Arial',
fontWeight: 'bold',
fontStyle: 'normal'
});
I've checked your example. It looks good.
Generally, the Russian text shouldn't be a problem, because we use it in our project. I didn't see any problems with it.
What can I guess:
1. Your left and top values are so, that text is outside of the canvas, and you see only the symbol "!".
2. Other, but hardly - some of your variables have wrong values. Try to set values, as in my example (I've tested it with fabric 2.0.3 and 1.7.22).
https://jsfiddle.net/Eugene_Ilyin/o2drxd0L/
var canvas = new fabric.Canvas('c');
var textObject = new fabric.Text('Привет!', {
originX: 'center',
originY: 'center',
left: 100,
top: 100,
textAlign: 'center',
fill: 'red',
stroke: '#000',
strokeWidth: 1,
fontSize: 20,
spacing: 5,
fontFamily: 'Arial',
fontWeight: 'bold',
fontStyle: 'normal'
});
canvas.add(textObject);
canvas.renderAll();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.3/fabric.min.js"></script>
<canvas id="c"></canvas>
For me it is rendered like this:

Fabric JS: Copy/paste object on mouse down

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
}
});
});
}
See Jsfiddle here, I add the function to do this.
function draggable(object) {
object.on('mousedown', function() {
var temp = this.clone();
temp.set({
hasControls: false,
hasBorders: false,
});
canvas.add(temp);
draggable(temp);
});
object.on('mouseup', function() {
// Remove an event handler
this.off('mousedown');
// Comment this will let the clone object able to be removed by drag it to menu bar
// this.off('mouseup');
// Remove the object if its position is in menu bar
if(this.top<=75) {
canvas.remove(this);
}
});
}
draggable(squareBtn);
draggable(circleBtn);
draggable(triangleBtn);

Categories

Resources