向控件添加自定义删除(后退,前置)按钮

时间:2014-02-09 16:21:00

标签: javascript html5 canvas html5-canvas fabricjs

我想知道是否有一种简单的方法来添加删除,带到前面,带回来 功能到现有的 fabric.js 对象控件。

目前我只能点击会删除对象的按钮,然后将其带到前面等等。

我正在寻找能够按下对象上的X(在右上角)并删除对象的解决方案。

我想这将与覆盖,包装或子类化现有控件对象有关。

也许我已经监督了一些事情并且有一个简单的解决方案?请不要Div Wrapper。

Fabric.js Canvas Object Selection Delete X

5 个答案:

答案 0 :(得分:10)

Fabric.js不提供向对象添加控件的任何简单方法。 如果要创建自己的控件,则必须覆盖Object类,特别是:

  • 覆盖drawControls,以绘制自定义按钮
  • 您需要存储按钮的坐标,以便您可以检测用户何时单击它们。 C.F. _setCornerCoords_findTargetCorner
  • 将您的操作合并到__onMouseDown

你不需要照顾' undrawing'控件,因为取消选择对象时将重新渲染整个画布。

我希望这会有所帮助,祝你好运:)。

答案 1 :(得分:5)

我通过定位html元素实现了它

canvas.on('object:selected',function(e){


        jQuery(".deleteBtn").remove(); 
        var btnLeft = e.target.oCoords.mt.x;
        var btnTop = e.target.oCoords.mt.y - 25;
        var widthadjust=e.target.width/2;
        btnLeft=widthadjust+btnLeft-10;
        var deleteBtn = '<p" class="deleteBtn" title="Delete" style="position:absolute;top:'+btnTop+'px;left:'+btnLeft+'px;cursor:pointer;" title="Remove object">&#10005;</p>';
        jQuery(".canvas-container").append(deleteBtn);
        //.canvas-container is the parent div to the canvas positioned relative via CSS



    });

canvas.on('mouse:down',function(e){
    if(canvas.getActiveObject())
    {

    }
    else
    {
         jQuery(".deleteBtn").remove(); 
    }
});


canvas.on('object:modified',function(e){


        jQuery(".deleteBtn").remove(); 
        var btnLeft = e.target.oCoords.mt.x;
        var btnTop = e.target.oCoords.mt.y - 25;
        var widthadjust=e.target.width/2;
        btnLeft=widthadjust+btnLeft-10;
        var deleteBtn = '<p" class="deleteBtn" title="Delete" style="position:absolute;top:'+btnTop+'px;left:'+btnLeft+'px;cursor:pointer;" title="Remove object">&#10005;</p>';
        jQuery(".canvas-container").append(deleteBtn);
        //.canvas-container is the parent div to the canvas positioned relative via CSS



    });


//THE DELETE BUTTON CLICK EVENT
 jQuery(document).on('click',".deleteBtn",function(){


    if(canvas.getActiveObject())
    {
         canvas.remove(canvas.getActiveObject());
//this would remove the currently active object on stage,
         jQuery(this).remove();
         jQuery(".deleteBtn").remove();
    }


     })

答案 2 :(得分:2)

您可以尝试使用html按钮。看一下这个例子:

http://fabricjs.com/interaction-with-objects-outside-canvas/

以下是代码示例:

    (function() {
  var canvas = this.__canvas = new fabric.Canvas('c');
  fabric.Object.prototype.transparentCorners = false;
  fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

  fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
    return {
      left: object.left + this._offset.left,
      top: object.top + this._offset.top
    };
  }

  var btn = document.getElementById('inline-btn'),
      btnWidth = 85,
      btnHeight = 18;

  function positionBtn(obj) {
    var absCoords = canvas.getAbsoluteCoords(obj);

    btn.style.left = (absCoords.left - btnWidth / 2) + 'px';
    btn.style.top = (absCoords.top - btnHeight / 2) + 'px';
  }

  fabric.Image.fromURL('../lib/pug.jpg', function(img) {

    canvas.add(img.set({ left: 250, top: 250, angle: 30 }).scale(0.25));

    img.on('moving', function() { positionBtn(img) });
    positionBtn(img);
  });
})();

答案 3 :(得分:2)

我相信带有dom元素的解决方案并不是那么稳定,但如果满足您的需求则可以,  我还需要将默认对象的角落按钮更改为我的Web应用程序的自定义按钮。 我用,

  1. &#39;改变尺寸&#39;按钮,/ 我不再使用它出于我的原因 /
  2. &#39;删除对象&#39;按钮
  3. &#39;编辑对象&#39;按钮
  4. &#39;旋转物体&#39;按钮
  5. 所以你必须改变两件事才能成功:

    1。更改私人功能&#39; _drawControl&#39;来自fabric.js文件。这是关于13367号线(在我的fabric.js上)。在该功能结构上绘制对象的默认cornet按钮并在seleced上显示它们。 我们可以轻松地将png更改为我们的自定义。

    下面是我更改的_drawControl(fabric.js):

         _drawControl: function(control, ctx, methodName, left, top, flipiX, flipiY) {
    
                  var sizeX = this.cornerSize / this.scaleX,
                      sizeY = this.cornerSize / this.scaleY;
    
                  if (this.isControlVisible(control)) {
                    isVML || this.transparentCorners || ctx.clearRect(left, top, sizeX, sizeY);
    
              var SelectedIconImage = new Image();
              var lx='';
              var ly='';
              var n='';
    
              switch (control)
                {
                case 'tl':      
                  if (flipiY) { ly='b'; } else { ly = 't'; }
                  if (flipiX) { lx='r'; } else { lx = 'l'; }
                  break;
                case 'tr':
                  if (flipiY) { ly='b'; } else { ly = 't'; }
                  if (flipiX) { lx='l'; } else { lx = 'r'; }
                  break;
                case 'bl':
                  if (flipiY) { ly='t'; } else { ly = 'b'; }
                  if (flipiX) { lx='r'; } else { lx = 'l'; }
                  break;
                case 'br':
                  if (flipiY) { ly='t'; } else { ly = 'b'; }
                  if (flipiX) { lx='l'; } else { lx = 'r'; }
                  break;
                default:
                  ly=control.substr(0, 1);
                  lx=control.substr(1, 1);
                  break;
                }
    
              control=ly+lx;
    
              switch (control)
                {
                case 'tl':      
    
    //my custom png for the object's top left corner
                  SelectedIconImage.src = 'assets/img/icons/draw_control/icon_rotate.png';
                  break;
                case 'tr':
                  if (flipiX && !flipiY) { n='2'; }
                  if (!flipiX && flipiY) { n='3'; }
                  if (flipiX && flipiY) { n='4'; }
    
    //my custom png for the object's top right corner
                    SelectedIconImage.src = 'assets/img/icons/draw_control/icon_delete.png';
                  break;
                case 'mt':
                  SelectedIconImage.src = //add your png here if you want middle top custom image;
                  break;
                case 'bl':
                  if (flipiY) { n='2'; }
                  SelectedIconImage.src = //add your png here if you want bottom left corner custom image;
                  break;
                case 'br':
                  if (flipiX || flipiY) { n='2'; }
                  if (flipiX && flipiY) { n=''; }
    //my custom png for the object's bottom right corner
                  SelectedIconImage.src = 'assets/img/icons/draw_control/icon_settings.png';
                  break;
                case 'mb':
                  SelectedIconImage.src = //middle bottom png here ;
                  break;
                case 'ml':
                  SelectedIconImage.src = 'assets/img/icons/draw_control/icono_escala_horizontal'+n+'.jpg';
                  break;
                case 'mr':
                  SelectedIconImage.src = //middle right png here;
                  break;
                default:
                  ctx[methodName](left, top, sizeX, sizeY);
                  break;
                }
    
         // keep middle buttons size fixed
                if (control == 'tl' || control == 'tr' || control == 'bl' || control == 'br'
                || control == 'mt' || control == 'mb' || control == 'ml' || control == 'mr')
                {
                  sizeX = 19;
                  sizeY = 19;
                  ctx.drawImage(SelectedIconImage, left, top, sizeX, sizeY);
                }
    
    
                  try {
                    ctx.drawImage(SelectedIconImage, left, top, sizeX, sizeY); 
    
                  } catch (e) {
                    if (e.name != "NS_ERROR_NOT_AVAILABLE") {
                      throw e;
                    }
                  }
    
    
            }
      },
    
    1. 正如前面提到的 Toon Nelissen ,我在fabric.Canvas.prototype.__onMouseDown功能旁边,并控制我的自定义按钮。

      fabric.Canvas.prototype.__onMouseDown = function (e) {
      
      // accept only left clicks
      var isLeftClick  = 'which' in e ? e.which === 1 : e.button === 1;
      if (!isLeftClick && !fabric.isTouchSupported) {
          return;
      }
      
      if (this.isDrawingMode) {
          this._onMouseDownInDrawingMode(e);
          return;
      }
      
      // ignore if some object is being transformed at this moment
      if (this._currentTransform) {
          return;
      }
      
      var target = this.findTarget(e), 
      pointer = this.getPointer(e, true);
      
      //if user clicked on the top right corner image
      if (target && target.__corner === 'tr') {
                //my code goes here
          }
      } else {
          // save pointer for check in __onMouseUp event
          this._previousPointer = pointer;
      
          var shouldRender = this._shouldRender(target, pointer),
            shouldGroup = this._shouldGroup(e, target);
      
          if (this._shouldClearSelection(e, target)) {
              this._clearSelection(e, target, pointer);
          } else if (shouldGroup) {
              this._handleGrouping(e, target);
              target = this.getActiveGroup();
          }
      
          if (target && target.selectable && !shouldGroup) {
          this._beforeTransform(e, target);
          this._setupCurrentTransform(e, target);
          }
          // we must renderAll so that active image is placed on the top canvas
          shouldRender && this.renderAll();
      
          this.fire('mouse:down', { target: target, e: e });
          target && target.fire('mousedown', { e: e });
      }
      

      };

    2. 对于其他角落,我们还要编写相应的片段(在__onMouseDown内):

       //if user clicked on the bottom right corner image
              if (target && target.__corner === 'br') {
                   //my code here
               }else{
                  //the same as 'tr'
              }
      
       //if user clicked on the top left corner image
                  if (target && target.__corner === 'tl') {
                       //my code here
                   }else{
                      //the same as 'tr'
                  }
      
       //if user clicked on the bottom left corner image
                  if (target && target.__corner === 'bl') {
                       //my code here
                   }else{
                      //the same as 'tr'
                  }
      
      下面是我的网络应用程序自定义图像的屏幕截图

      enter image description here

答案 4 :(得分:1)

您可以覆盖__onMouseDown函数,例如这样。

目标对象包含__corner元素target.__corner

检查这是否是&#39; tr&#39; (右上角)并删除activeObject

    if (target.__corner === 'tr') {
        if(canvas.getActiveObject()){
            canvas.remove(canvas.getActiveObject());
        }
    }

完整代码:

fabric.Canvas.prototype.__onMouseDown = function (e) {

    // accept only left clicks
    var isLeftClick  = 'which' in e ? e.which === 1 : e.button === 1;
    if (!isLeftClick && !fabric.isTouchSupported) {
        return;
    }

    if (this.isDrawingMode) {
        this._onMouseDownInDrawingMode(e);
        return;
    }

    // ignore if some object is being transformed at this moment
    if (this._currentTransform) {
        return;
    }

    var target = this.findTarget(e), 
    pointer = this.getPointer(e, true);

    if (target && target.__corner === 'tr') {
        if(this.getActiveObject()){
            this.remove(this.getActiveObject());
        }
    } else {
        // save pointer for check in __onMouseUp event
        this._previousPointer = pointer;

        var shouldRender = this._shouldRender(target, pointer),
          shouldGroup = this._shouldGroup(e, target);

        if (this._shouldClearSelection(e, target)) {
            this._clearSelection(e, target, pointer);
        } else if (shouldGroup) {
            this._handleGrouping(e, target);
            target = this.getActiveGroup();
        }

        if (target && target.selectable && !shouldGroup) {
        this._beforeTransform(e, target);
        this._setupCurrentTransform(e, target);
        }
        // we must renderAll so that active image is placed on the top canvas
        shouldRender && this.renderAll();

        this.fire('mouse:down', { target: target, e: e });
        target && target.fire('mousedown', { e: e });
    }
};