Hi I want to add delete button in element using FabricJS. I Have an example:
I try adding this part of code but when I resize image the delete button don\'t sta
Hello i would suggest a different approach to this functionality that it is more stable as it does not add elements on the DOM , we can use it on as many objects as we like , we dont need to hide and show the custom corner buttons, and the corner buttons are visible each time the object is active(native fabricjs functions).
A. First of all i need to preload the custom corner images, so whenever we click on an object there would not be any delay(i used random images just for the show).
var ctrlImages = new Array()
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
ctrlImages[i] = new Image();
ctrlImages[i].src = preload.arguments[i];
}
}
preload(
"https://cdn1.iconfinder.com/data/icons/ui-color/512/Untitled-12-128.png",
"https://cdn2.iconfinder.com/data/icons/social-messaging-productivity-1/128/sync-16.png",
"https://cdn2.iconfinder.com/data/icons/social-messaging-productivity-1/128/write-compose-16.png",
B. I override the _drawcontrol (i show just the snippet that change the corners):
switch (control)
{
case 'tl':
SelectedIconImage.src = ctrlImages[1].src;//our custom img
break;
case 'tr':
if (flipiX && !flipiY) { n='2'; }
if (!flipiX && flipiY) { n='3'; }
if (flipiX && flipiY) { n='4'; }
SelectedIconImage.src = ctrlImages[0].src;//our custom img
break;
case 'mt':
break;
case 'bl':
if (flipiY) { n='2'; }
SelectedIconImage.src = ctrlImages[3].src;//our custom img
break;
case 'br':
if (flipiX || flipiY) { n='2'; }
if (flipiX && flipiY) { n=''; }
SelectedIconImage.src = ctrlImages[2].src;//our custom img
break;
case 'mb':
break;
case 'ml':
break;
case 'mr':
break;
default:
ctx[methodName](left, top, sizeX, sizeY);
break;
}
C. Override _setCornerCursor function, for to change the cursor when mouse is over object's corner. Inside the function i use the setCursor() function which actually takes a string as a parameter, so we can take a look here for cursors: https://www.w3.org/TR/css3-ui/#cursor
fabric.Canvas.prototype._setCornerCursor = function(corner, target) {
//for top left corner
if(corner == "tl"){
this.setCursor(this.rotationCursor); return false;
//for top right corner
}else if(corner == "tr"){
this.setCursor('pointer'); return false;
//for bottom left corner
}else if(corner == "bl"){
this.setCursor('help'); return false;
//for bottom right corner
}else if(corner == "br"){
this.setCursor('copy'); return false;
}
};
D. And finaly on mouse:down i check the corner and add functionality canvas.on('mouse:down',function(e){..}
Hope helps, good luck.
This answer should be updated with the most recent version of fabric.js which now has the concept of "controls". This seems like this best solution now.
http://fabricjs.com/custom-control-render
target.oCoords.mt
is middle-top corner.
Use the top-right corner instead: e.target.oCoords.tr
var canvas = new fabric.Canvas('canvas');
var HideControls = {
'tl':true,
'tr':false,
'bl':true,
'br':true,
'ml':true,
'mt':true,
'mr':true,
'mb':true,
'mtr':true
};
fabric.Image.fromURL('http://serio.piiym.net/CVBla/txtboard/thumb/1260285874089s.jpg', function (img) {
img.top = 60;
img.left = 30;
img.setControlsVisibility(HideControls);
canvas.add(img);
});
canvas.renderAll();
function addDeleteBtn(x, y){
$(".deleteBtn").remove();
var btnLeft = x-10;
var btnTop = y-10;
var deleteBtn = '<img src="https://www.funagain.com/images/old/common/delete-icon.png" class="deleteBtn" style="position:absolute;top:'+btnTop+'px;left:'+btnLeft+'px;cursor:pointer;width:20px;height:20px;"/>';
$(".canvas-container").append(deleteBtn);
}
canvas.on('object:selected',function(e){
addDeleteBtn(e.target.oCoords.tr.x, e.target.oCoords.tr.y);
});
canvas.on('mouse:down',function(e){
if(!canvas.getActiveObject())
{
$(".deleteBtn").remove();
}
});
canvas.on('object:modified',function(e){
addDeleteBtn(e.target.oCoords.tr.x, e.target.oCoords.tr.y);
});
canvas.on('object:scaling',function(e){
$(".deleteBtn").remove();
});
canvas.on('object:moving',function(e){
$(".deleteBtn").remove();
});
canvas.on('object:rotating',function(e){
$(".deleteBtn").remove();
});
$(document).on('click',".deleteBtn",function(){
if(canvas.getActiveObject())
{
canvas.remove(canvas.getActiveObject());
$(".deleteBtn").remove();
}
});
your reasoning is correct. Unfortunately, I have in your example "TypeError: t is undefined --> fabric.min.js:1:14099"
I have your example a little modified. I overriede four Methodes:
var canvas = new fabric.Canvas('canvas');
var DIMICON = 15;
var HideControls = {
'tl':true,
'tr':true,
'bl':true,
'br':true,
'ml':false,
'mt':false,
'mr':false,
'mb':false,
'mtr':false
};
var dataImage = [
"https://cdn1.iconfinder.com/data/icons/streamline-interface/60/cell-8-10-120.png", /*scale*/
"https://cdn1.iconfinder.com/data/icons/ui-color/512/Untitled-12-128.png", /*delete*/
"https://cdn2.iconfinder.com/data/icons/social-messaging-productivity-1/128/sync-16.png", /*rotate*/
"https://cdn2.iconfinder.com/data/icons/social-messaging-productivity-1/128/write-compose-16.png", /*change text*/
"https://cdn3.iconfinder.com/data/icons/social-messaging-productivity-1/128/save-16.png" /*save*/
];
//********override*****//
fabric.Object.prototype._drawControl = function(control, ctx, methodName, left, top) {
if (!this.isControlVisible(control)) {
return;
}
var SelectedIconImage = new Image();
var size = this.cornerSize;
/* fabric.isVML() ||*/ this.transparentCorners || ctx.clearRect(left, top, size, size);
switch (control)
{
case 'tl':/*delete*/
SelectedIconImage.src = dataImage[1];
break;
case 'tr':/*scale*/
SelectedIconImage.src = dataImage[0];
break;
case 'bl':/*scale*/
SelectedIconImage.src = dataImage[0];
break;
case 'br':/*rotate*/
SelectedIconImage.src = dataImage[2];
break;
default:
ctx[methodName](left, top, size, size);
}
if (control == 'tl' || control == 'tr' || control == 'bl' || control == 'br')
{
try {
ctx.drawImage(SelectedIconImage, left, top, DIMICON, DIMICON);
} catch (e) {
ctx[methodName](left, top, size, size);
}
}
}
//override prorotype _setCornerCursor to change the corner cusrors
fabric.Canvas.prototype._setCornerCursor = function(corner, target) {
if (corner === 'mtr' && target.hasRotatingPoint) {
this.setCursor(this.rotationCursor);
/*ADD*/
}else if(corner == "tr" || corner == "bl" ){
this.setCursor('sw-resize');
}else if(corner == "tl" || corner == "br"){
this.setCursor('pointer');
}
/*ADD END*/
else {
this.setCursor(this.defaultCursor);
return false;
}
};
fabric.Canvas.prototype._getActionFromCorner = function(target, corner){
var action = 'drag';
if (corner){
switch(corner){
case 'ml':
case 'mr':
action = 'scaleX';
break;
case 'mt':
case 'mb':
action = 'scaleY';
break;
case 'mtr':
action = 'rotate';
break;
/**ADD **/
case 'br':
action = 'rotate';
break;
case 'tl'://delete function if mouse down
action = 'delete';
canvas.remove(canvas.getActiveObject());
break;
/**ADD END**/
default: action = 'scale';
}
return action;
}
}
fabric.Canvas.prototype._performTransformAction = function(e, transform, pointer) {
var x = pointer.x,
y = pointer.y,
target = transform.target,
action = transform.action;
if (action === 'rotate') {
this._rotateObject(x, y);
this._fire('rotating', target, e);
}
else if (action === 'scale') {
this._onScale(e, transform, x, y);
this._fire('scaling', target, e);
}
else if (action === 'scaleX') {
this._scaleObject(x, y, 'x');
this._fire('scaling', target, e);
}
else if (action === 'scaleY') {
this._scaleObject(x, y, 'y');
this._fire('scaling', target, e);
}
/**ADD**/
else if (action === 'delete') {
//do nothing, because here function executed when mouse moves
}
/**ADD END**/
else {
this._translateObject(x, y);
this._fire('moving', target, e);
this.setCursor(this.moveCursor);
}
}
//********override END*****//
//create a rect object
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: "#FF0000",
stroke: "#000",
width: 100,
height: 100,
strokeWidth: 10,
opacity: .8
});
canvas.add(rect);
rect.setControlsVisibility(HideControls);
fabric.Image.fromURL('http://serio.piiym.net/CVBla/txtboard/thumb/1260285874089s.jpg', function (img) {
img.top = 60;
img.left = 250;
img.setControlsVisibility(HideControls);
canvas.add(img);
});
canvas.renderAll();
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<div id="canvas-container" class="over">
<div class="canvas-container" style="width: 800px; height: 600px; position: relative; -webkit-user-select: none;">
<canvas id="canvas" width="800" height="600"></canvas>
</div>
</div>