Not able to delete shape objects from fabric canvas - javascript

I uploaded an image as background image, so that I am able to draw circle and rectangle on top of it.
But, when I try to delete any shape, I am not able to do that.
I tried debugging and it just says Unexpected token ) on Delete
I am just not able to figure out what exactly is the problem here.
//-----------------------------Getting hold of Canvas----------------------------
var canvas = new fabric.Canvas('canvas');
canvas.setHeight(window.innerHeight * .75);
canvas.setWidth(window.innerWidth * .75);
drawBackground();
//--------------------------Image Rendering--------------------------------------
function drawBackground() {
fabric.Image.fromURL('https://upload.wikimedia.org/wikipedia/commons/f/f9/Phoenicopterus_ruber_in_S%C3%A3o_Paulo_Zoo.jpg', function(img) {
img.scaleToWidth(window.innerWidth * .75);
img.scaleToHeight(window.innerHeight * .75);
canvas.setBackgroundImage(img);
canvas.renderAll();
});
}
//------------------------Reset--------------------------------------------------
/*window.reset = function(){
canvas = new fabric.Canvas('canvas');
drawBackground();
}*/
//------------------------Rectangle----------------------------------------------
window.addRect = function() {
var rect = new fabric.Rect({
left: 0,
top: 0,
stroke: 'red',
fill: 'rgba(255,0,0,.4)',
width: 50,
height: 50,
});
rect.hasRotatingPoint = false;
canvas.add(rect);
}
//---------------------Circle----------------------------------------------------
window.addCircle = function() {
var circle = new fabric.Circle({
left: 0,
top: 0,
radius: 20,
stroke: 'green',
fill: 'transparent',
});
circle.hasRotatingPoint = false;
canvas.add(circle);
}
//--------------------Delete Objects---------------------------------------------
window.delete = function() {
canvas.remove(canvas.getActiveObject());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js">
</script>
<canvas id="canvas" width="800" height="600" style="border:1px solid red;"></canvas>
<!--<button onClick="reset()">Reset</button> !-->
<button onClick="addCircle()">Circle</button>
<button onClick="addRect()">Box</button>
<button onClick="delete()">Delete</button>

delete is a reserved word and cant be used as a function on the window object.
A helpful link:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
You use delete as function inline right here:
<button onClick="delete()">Delete</button>

Related

FabricJS: Why cant I click on objects during animations?

I need a circle, which gets bigger every second. If I click the circle, it should disappear.
Ok so I added an animation and a mousedown function. But at the end of the animation the mousedown function does not work.
The circle is not recognized any more and is null until the animation finishes.
Any suggestions?
MyCode:
let canvas = new fabric.Canvas('c');
var temp = new fabric.Circle({
left: 0,
top: 0,
fill: 'red',
radius: 20
});
temp.on('mousedown', function(e){
console.log("clicked");
});
temp.selectable = false;
canvas.add(temp);
function animate(c){
c.animate('radius', '80',{
duration: 6000,
onChange: canvas.renderAll.bind(canvas)
});
}
animate(temp);
You need to call object#setCoords. in onChange handler.
DEMO
let canvas = new fabric.Canvas('c');
var temp = new fabric.Circle({
left: 0,
top: 0,
fill: 'red',
radius: 20,
selectable: false
});
temp.on('mousedown', function(e) {
console.log("clicked");
canvas.remove(temp);
temp.isRemoved = true;
});
canvas.add(temp);
function animate(c) {
c.animate('radius', '80', {
duration: 6000,
onChange: function() {
c.setCoords();
canvas.requestRenderAll();
},
abort: function() {
return c.isRemoved;
}
});
}
animate(temp);
canvas {
border: 1px solid #999;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.0.0/fabric.js"></script>
<canvas id='c' width=300 height=200></canvas>
<div id='result'></div>
<div id='result2'>
</div>

How can I delete a fabric canvas arrow?

I created an arrow using Fabric.js group functionality by grouping Rectangle and Triangle.
Unfortunately I am not able to delete it as a group.
I figured out that getActiveObject() for a single object works fine. Instead, while debugging getActiveGroup() gives error.
var canvas = new fabric.Canvas('canvas');
canvas.setHeight(window.innerHeight * 0.75);
canvas.setWidth(window.innerWidth * 0.75);
//-------------------------Group - Rectangle and Triangle----------------------------------------------
window.addArrow = function() {
var rect = new fabric.Rect({
left: 0,
top: 0,
stroke: 'red',
fill: 'red',
width: 1,
height: 50,
});
rect.hasRotatingPoint = true;
canvas.add(rect);
var triangle = new fabric.Triangle({
width: 10,
height: 10,
fill: 'red',
left: -4,
top: -10
});
var group = new fabric.Group([rect, triangle], {
left: 150,
top: 100,
angle: 90
});
canvas.add(group);
}
//-------------------------Group Delete----------------------------------------------
window.deleteObject = function() {
return canvas.getActiveObject() == null ? canvas.getActiveGroup() : canvas.getActiveObject();
}
function getActiveGroup() {
canvas.getActiveGroup().forEachObject(function(o) {
canvas.remove(o)
});
}
function getActiveObject() {
canvas.remove(canvas.getActiveObject());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js"></script>
<canvas id="canvas" width="800" height="600" style="border:1px solid red;"></canvas>
<button onClick="addArrow()">Arrow</button>
<button onClick="deleteObject()">Delete</button>
Because you didn't set any active object you cannot use getActiveObject.
In this case you may use getObjects:
canvas.getObjects('group') // in order to get the group
canvas.getObjects('rect') // in order to get the rectangle
var canvas = new fabric.Canvas('canvas');
canvas.setHeight(window.innerHeight * 0.75);
canvas.setWidth(window.innerWidth * 0.75);
//-------------------------Group - Rectangle and Triangle----------------------------------------------
window.addArrow = function() {
var rect = new fabric.Rect({
left: 0,
top: 0,
stroke: 'red',
fill: 'red',
width: 1,
height: 50,
});
rect.hasRotatingPoint = true;
canvas.add(rect);
var triangle = new fabric.Triangle({
width: 10,
height: 10,
fill: 'red',
left: -4,
top: -10
});
var group = new fabric.Group([rect, triangle], {
left: 150,
top: 100,
angle: 90
});
canvas.add(group);
}
//-------------------------Group Delete----------------------------------------------
window.deleteObject = function() {
// remove group....
canvas.getObjects('group').forEach(function(ele,idx) {
canvas.remove(ele);
});
canvas.getObjects('rect').forEach(function(ele,idx) {
canvas.remove(ele);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js"></script>
<canvas id="canvas" width="800" height="600" style="border:1px solid red;"></canvas>
<button onClick="addArrow()">Arrow</button>
<button onClick="deleteObject()">Delete</button>
use sub classing in fabric.js for creating arrow object so that single object is only needed. So handling will be easier.
[http://fabricjs.com/fabric-intro-part-3#subclassing][1]

How can i able to move image beneath rectangle in canvas?

I could select the background image from inside rectangle, but not able to move.
To move the image, i should go outside of the rectangle.
I know that the rectangle is created over the image, I'm looking for any option to move the image as it is selectable from inside rectangle.
My canvas screenshot
This is how i set the image and rectangle.
changeImage(innercanvasHeight, innercanvasWidth) {
const base_image = new Image();
base_image.crossOrigin = 'Anonymous';
base_image.src = 'assets/images/1wal.jpg';
fabric.Image.fromURL(base_image.src, (myImg) => {
const img1 = myImg.set({left: 160, top: 80, width: 600, height:
400, id: 'wallpaper'});
this.FabriCanvas.add(img1).setActiveObject(img1);
const hiddenImg = document.createElement('img');
hiddenImg.src = this.FabriCanvas.getActiveObject().toDataURL();
hiddenImg.id = 'target';
hiddenImg.style.display = 'none';
document.body.appendChild(hiddenImg);
this.innerCanvas(innercanvasHeight, innercanvasWidth);
});
innerCanvas(height, width) {
this.innercanvas = this.FabriCanvas.add(new fabric.Rect({
left: 160,
top: 80,
id: 'innerCan',
fill: 'transparent',
stroke: '#fff',
strokeWidth: 1,
width: width,
height: height,
selectable: false
}));
this.FabriCanvas.renderAll();
}
Use preserveObjectStacking so it wont come up while dragging, and use perPixelTargetFind to click through the object if it is transparent.
DEMO
var canvas = new fabric.Canvas('canvas',{
preserveObjectStacking: true
});
var image = new fabric.Image('');
var rect = new fabric.Rect({
left: 160,
top: 80,
id: 'innerCan',
fill: 'transparent',
stroke: '#fff',
strokeWidth: 1,
width: 100,
height: 100,
selectable: false,
perPixelTargetFind : true
});
canvas.add(image,rect);
image.setSrc('//fabricjs.com/assets/pug.jpg',function(img){
img.set({ scaleX:canvas.width/img.width,scaleY: canvas.height/img.height});
img.setCoords();
canvas.renderAll();
})
canvas{
border: 2px solid #000;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id='canvas' width=300 height=300></canvas>

How to use the same functions on canvases that have different background images on different pages?

I'm using fabric.js to manipulate different canvases with their own dimensions and background images. My problem is that I'm not sure how to continue using the below functions with new canvases with different background images (I'm stuck with one background image). I've tried creating new canvases with the following for example and controlling their backgrounds with CSS but it breaks the app on the second page:
var canvas = new fabric.Canvas('d');
I'm still learning how to work with different canvases so wasn't sure how to handle this. Thanks in advance.
The Details:
Right now I have 2 pages, one with:
<canvas width="500" height="500" id="c"></canvas>
and the other with:
<canvas width="700" height="700" id="c"></canvas>
They're both using this the following JavaScript and CSS:
var canvas = new fabric.Canvas('c');
// Upload image
document.getElementById('file').addEventListener("change", function(e) {
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) {
//create shadow
var shadow = {
color: '#888888',
blur: 70,
offsetX: 45,
offsetY: 45,
opacity: 0.8
}
var oImg = img.set({
left: 0,
top: 0,
angle: 0,
stroke: '#fffcf7',
strokeWidth: 20
}).scale(1);
oImg.setShadow(shadow); //set shadow
canvas.add(oImg).renderAll();
var dataURL = canvas.toDataURL({
format: 'png',
quality: 1
});
});
};
reader.readAsDataURL(file);
});
// Add text
function Addtext() {
canvas.add(new fabric.IText('Tap and Type', {
// left: 0,
// top: 0,
fontFamily: 'helvetica neue',
fill: '#000',
stroke: '#000',
strokeWidth: .2,
fontSize: 45
}));
}
// Delete selected object
window.deleteObject = function() {
var activeGroup = canvas.getActiveGroup();
if (activeGroup) {
var activeObjects = activeGroup.getObjects();
for (let i in activeObjects) {
canvas.remove(activeObjects[i]);
}
canvas.discardActiveGroup();
canvas.renderAll();
} else canvas.getActiveObject().remove();
}
// Send selected object to front or back
var selectedObject;
canvas.on('object:selected', function(event) {
selectedObject = event.target;
});
var sendtoback = function() {
canvas.sendToBack(selectedObject);
}
var sendtofront = function() {
canvas.bringToFront(selectedObject);
}
fabric.Object.prototype.set({
transparentCorners: true,
lockUniScaling: true,
cornerColor: '#22A7F0',
borderColor: '#22A7F0',
cornerSize: 12,
padding: 5
});
#c {
background: url(http://i.imgur.com/RkNFWSY.jpg);
}
.myFile {
position: relative;
overflow: hidden;
float: left;
clear: left;
}
.myFile input[type="file"] {
display: block;
position: absolute;
top: 0;
right: 0;
opacity: 0;
font-size: 30px;
filter: alpha(opacity=0);
}
first
Give your canvas (that is on the second page) a different id , for instance d ...
<canvas width="700" height="700" id="d"></canvas>
second
Initiate your new fabric canvas instance as such ...
var id = document.getElementById('c') && c ||
document.getElementById('d') && d;
var canvas = new fabric.Canvas(id);
this will ensure that the appropriate canvas is present on the page
third
Now, set different background image for each canvas (by their id) in your css, like so ...
#c {
background: url(http://i.imgur.com/RkNFWSY.jpg);
}
#d {
background: url(http://i.imgur.com/GYpod56.jpg);
}

Why does shape appears on click of canvas element after removing it?

When I remove the object and click on canvas element , the removed shape re-appears and I am not able to select it also.
var delete = function(){
var canvas = document.getElementById("canvas").fabric;
canvas.remove(canvas.getActiveObject());
}
You have to register an handler to object selection on canvas, then remove the object.
Check the runnable snippet below if could work for your needs:
$(function() {
var canvas = new fabric.Canvas('c')
var operation = '';
var circle = new fabric.Circle({
radius: 20,
fill: 'green',
left: 100,
top: 100
});
var triangle = new fabric.Triangle({
width: 20,
height: 30,
fill: 'blue',
left: 50,
top: 50
});
canvas.add(circle, triangle);
canvas.on('object:selected', doOperationHandler);
function doOperationHandler() {
if (operation == 'remove') {
remove();
}
}
function remove() {
canvas.remove(canvas.getActiveObject());
}
$('#btn_select').on('click', function() {
operation = '';
});
$('#btn_delete').on('click', function() {
operation = 'remove';
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id='c'>
</canvas>
<button id='btn_select'>Select</button>
<button id='btn_delete'>Delete</button>

Categories