简体   繁体   English

在 Canvas Fabric JS 中的元素上添加删除按钮

[英]Add Delete button on element in Canvas Fabric JS

Hi I want to add delete button in element using FabricJS.嗨,我想使用 FabricJS 在元素中添加删除按钮。 I Have an example:我有一个例子:

[1]:http://i.imgur.com/kEcWKYY.png“元素”

I try adding this part of code but when I resize image the delete button don't stay on place.我尝试添加这部分代码,但是当我调整图像大小时,删除按钮不会留在原处。

http://jsfiddle.net/wxao1on8/13/ http://jsfiddle.net/wxao1on8/13/

   function addDeleteBtn(x, y, w){
        $(".deleteBtn").remove();
        var btnLeft = x;
        var btnTop = y - 30;
        var widthadjust=w/2;
        btnLeft=widthadjust+btnLeft-1
        var deleteBtn = '<img src="https://www.funagain.com/images/old/common/delete-icon.png" class="deleteBtn" ' +
                'style="position:absolute;top:'+btnTop+'px;right:'+btnLeft+'px;cursor:pointer;"/>';
        $(".canvas-container").append(deleteBtn);
    }

    canvas.on('object:selected',function(e){
        addDeleteBtn(e.target.oCoords.mt.x, e.target.oCoords.mt.y, e.target.width);
    });

    canvas.on('mouse:down',function(e){
        if(!canvas.getActiveObject())
        {
            $(".deleteBtn").remove();
        }
    });

    canvas.on('object:modified',function(e){
        addDeleteBtn(e.target.oCoords.mt.x, e.target.oCoords.mt.y, e.target.width);
    });

    canvas.on('object:moving',function(e){
        $(".deleteBtn").remove();
    });

    $(document).on('click',".deleteBtn",function(){
        if(canvas.getActiveObject())
        {
            canvas.remove(canvas.getActiveObject());
            $(".deleteBtn").remove();
        }
    });

target.oCoords.mt is middle-top corner. target.oCoords.mt是中上角。

Use the top-right corner instead: e.target.oCoords.tr改用右上角: 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();
    }
});

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).您好,我建议对此功能采用不同的方法,它更稳定,因为它不会在 DOM 上添加元素,我们可以在任意数量的对象上使用它,我们不需要隐藏和显示自定义角按钮,并且每次对象处于活动状态时,角落按钮都是可见的(本机 fabricjs 功能)。

  1. I am going to override the object's prototype _drawControl function , for to add my custom corner images.我将覆盖对象的原型_drawControl函数,以添加我的自定义角图像。
  2. And override the canvas prototype _setCornerCursor , for to change realtime the mouse cursor ,according to which corner is over.并覆盖画布原型_setCornerCursor ,根据哪个角落结束实时更改鼠标光标。
  3. I have made a live fiddle here : https://jsfiddle.net/tornado1979/j987gb6f/我在这里做了一个现场小提琴: https : //jsfiddle.net/tornado1979/j987gb6f/

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). A.首先,我需要预加载自定义的角图像,所以无论何时我们点击一​​个对象都不会有任何延迟(我使用随机图像只是为了展示)。

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): B.我覆盖了 _drawcontrol(我只展示了改变角落的片段):

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. C.覆盖_setCornerCursor函数,用于在鼠标悬停在对象的角上时更改光标。 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在函数内部,我使用 setCursor() 函数,该函数实际上将字符串作为参数,因此我们可以在这里查看游标: 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){..} D.最后在 mouse:down 我检查角落并添加功能 canvas.on('mouse:down',function(e){..}

自定义角图像和光标

Hope helps, good luck.希望有帮助,祝你好运。

your reasoning is correct.你的推理是正确的。 Unfortunately, I have in your example "TypeError: t is undefined --> fabric.min.js:1:14099"不幸的是,我在你的例子中有“TypeError: t is undefined --> fabric.min.js:1:14099”

I have your example a little modified.我对你的例子做了一些修改。 I overriede four Methodes:我覆盖了四种方法:

  • _drawControl --> draw icon _drawControl --> 绘制图标
  • _setCornerCursor --> show cursor _setCornerCursor --> 显示光标
  • _getActionFromCorner --> create action by mouse down _getActionFromCorner --> 通过鼠标创建动作
  • _performTransformAction --> perform action by mouse move _performTransformAction --> 通过鼠标移动执行动作

 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>

This answer should be updated with the most recent version of fabric.js which now has the concept of "controls".这个答案应该用最新版本的 fabric.js 更新,它现在具有“控件”的概念。 This seems like this best solution now.现在这似乎是最好的解决方案。

http://fabricjs.com/custom-control-render http://fabricjs.com/custom-control-render

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM