Add Delete button on element in Canvas Fabric JS

后端 未结 4 1654
粉色の甜心
粉色の甜心 2021-01-31 23:32

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

相关标签:
4条回答
  • 2021-02-01 00:01

    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).

    1. I am going to override the object's prototype _drawControl function , for to add my custom corner images.
    2. And override the canvas prototype _setCornerCursor , for to change realtime the mouse cursor ,according to which corner is over.
    3. I have made a live fiddle here : 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).

    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.

    0 讨论(0)
  • 2021-02-01 00:05

    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

    0 讨论(0)
  • 2021-02-01 00:14

    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();
        }
    });
    
    0 讨论(0)
  • 2021-02-01 00:20

    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:

    • _drawControl --> draw icon
    • _setCornerCursor --> show cursor
    • _getActionFromCorner --> create action by mouse down
    • _performTransformAction --> perform action by mouse move

    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>

    0 讨论(0)
提交回复
热议问题