【问题标题】:Add Delete button on element in Canvas Fabric JS在 Canvas Fabric JS 中的元素上添加删除按钮
【发布时间】:2016-06-08 09:59:59
【问题描述】:

您好,我想使用 FabricJS 在元素中添加删除按钮。我有一个例子:

我尝试添加这部分代码,但是当我调整图像大小时,删除按钮不会留在原处。

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();
        }
    });

【问题讨论】:

    标签: javascript jquery fabricjs


    【解决方案1】:

    target.oCoords.mt 是中上角。

    请改用右上角: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();
        }
    });
    

    【讨论】:

      【解决方案2】:

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

      1. 我将覆盖对象的原型 _drawControl 函数,以添加我的自定义角图像。
      2. 并覆盖画布原型_setCornerCursor,用于实时改变鼠标光标,根据哪个角结束。
      3. 我在这里做了一个现场小提琴:https://jsfiddle.net/tornado1979/j987gb6f/

      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. 我覆盖了 _drawcontrol(我只显示了改变角的 sn-p):

      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. 重写_setCornerCursor 函数,用于在鼠标悬停在对象角上时改变光标。 在函数内部,我使用了 setCursor() 函数,它实际上将 string 作为参数,所以我们可以在这里查看游标: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. 最后在 mouse:down 我检查角落并添加功能 canvas.on('mouse:down',function(e){..}

      希望有所帮助,祝你好运。

      【讨论】:

      • 嗨,为什么需要 FlipiX 和 FlipiY?如果只是为了旋转图标,那么为什么将它们作为参数提供给 _drawControls 函数。我很困惑。
      【解决方案3】:

      你的推理是正确的。 不幸的是,我在你的例子中 "TypeError: t is undefined --> fabric.min.js:1:14099"

      我对您的示例进行了一些修改。 我重写了四个方法:

      • _drawControl --> 绘制图标
      • _setCornerCursor --> 显示光标
      • _getActionFromCorner --> 通过鼠标按下创建动作
      • _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>

      【讨论】:

        【解决方案4】:

        此答案应使用最新版本的 fabric.js 进行更新,该版本现在具有“控件”的概念。这似乎是现在最好的解决方案。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-02
          • 2021-03-11
          • 1970-01-01
          • 2021-06-17
          • 2019-05-01
          • 2016-04-21
          • 2018-08-05
          • 2021-10-18
          相关资源
          最近更新 更多