Search code examples
javascriptcanvasfabricjs

Fabric js : fabric js drawing mode and selection mode options


I'm using fabric js to develop a application to draw a line, Rectangle and circle in one canvas.And there is a other function to drag and drop a image on to canvas. But when i added drag and drop function to the application other three function are not working. I have found this article. But i was unable to integrate it with my one.

function initCanvas() {
    $('.canvas-container').each(function (index) {

        var canvasContainer = $(this)[0];
        var canvasObject = $("canvas", this)[0];
        var url = $(this).data('floorplan');
        var canvas = window._canvas = new fabric.Canvas(canvasObject);

        canvas.setHeight(400);
        canvas.setWidth(500);
        canvas.setBackgroundImage(url, canvas.renderAll.bind(canvas));

        var imageOffsetX, imageOffsetY;

        function handleDragStart(e) {
            [].forEach.call(images, function (img) {
                img.classList.remove('img_dragging');
            });
            this.classList.add('img_dragging');


            var imageOffset = $(this).offset();
            imageOffsetX = e.clientX - imageOffset.left;
            imageOffsetY = e.clientY - imageOffset.top;
        }

        function handleDragOver(e) {
            if (e.preventDefault) {
                e.preventDefault();
            }
            e.dataTransfer.dropEffect = 'copy';
            return false;
        }

        function handleDragEnter(e) {
            this.classList.add('over');
        }

        function handleDragLeave(e) {
            this.classList.remove('over');
        }

        function handleDrop(e) {
            e = e || window.event;
            if (e.preventDefault) {
                e.preventDefault();
            }
            if (e.stopPropagation) {
                e.stopPropagation();
            }
            var img = document.querySelector('.furniture img.img_dragging');
            console.log('event: ', e);

            var offset = $(canvasObject).offset();
            var y = e.clientY - (offset.top + imageOffsetY);
            var x = e.clientX - (offset.left + imageOffsetX);

            var newImage = new fabric.Image(img, {
                width: img.width,
                height: img.height,
                left: x,
                top: y
            });
            canvas.add(newImage);
            return false;
        }

        function handleDragEnd(e) {
            [].forEach.call(images, function (img) {
                img.classList.remove('img_dragging');
            });
        }

        var images = document.querySelectorAll('.furniture img');
        [].forEach.call(images, function (img) {
            img.addEventListener('dragstart', handleDragStart, false);
            img.addEventListener('dragend', handleDragEnd, false);
        });
        canvasContainer.addEventListener('dragenter', handleDragEnter, false);
        canvasContainer.addEventListener('dragover', handleDragOver, false);
        canvasContainer.addEventListener('dragleave', handleDragLeave, false);
        canvasContainer.addEventListener('drop', handleDrop, false);
    });
}
initCanvas();

var canvas = new fabric.Canvas('canvas1', { selection: false });

var line, isDown;
function myFun() {
    removeEvents();    
    canvas.on('mouse:down', function (o) {
        isDown = true;
        var pointer = canvas.getPointer(o.e);
        var points = [pointer.x, pointer.y, pointer.x, pointer.y];
        line = new fabric.Line(points, {
            strokeWidth: 5,
            fill: '#07ff11a3',
            stroke: '#07ff11a3',
            originX: 'center',
            originY: 'center'
        });
        canvas.add(line);
    });
    canvas.on('mouse:move', function (o) {
        if (!isDown) return;
        var pointer = canvas.getPointer(o.e);
        line.set({ x2: pointer.x, y2: pointer.y });
        canvas.renderAll();
    });

    canvas.on('mouse:up', function (o) {
        isDown = false;
    });
    canvas.selection = false;

}

function drawrec() {
    var line, isDown, origX, origY;
    removeEvents();

    canvas.on('mouse:down', function (o) {
        isDown = true;
        var pointer = canvas.getPointer(o.e);
        origX = pointer.x;
        origY = pointer.y;
        var pointer = canvas.getPointer(o.e);
        line = new fabric.Rect({
            left: origX,
            top: origY,
            originX: 'left',
            originY: 'top',
            width: pointer.x - origX,
            height: pointer.y - origY,
            angle: 0,
            fill: '#07ff11a3',
            stroke: 'black',
            transparentCorners: false
        });
        canvas.add(line);
    });

    canvas.on('mouse:move', function (o) {
        if (!isDown) return;
        var pointer = canvas.getPointer(o.e);

        if (origX > pointer.x) {
            line.set({ left: Math.abs(pointer.x) });
        }
        if (origY > pointer.y) {
            line.set({ top: Math.abs(pointer.y) });
        }

        line.set({ width: Math.abs(origX - pointer.x) });
        line.set({ height: Math.abs(origY - pointer.y) });


        canvas.renderAll();
    });

    canvas.on('mouse:up', function (o) {
        isDown = false;
    });
}

function drawcle() {

    var circle, isDown, origX, origY;
    removeEvents();
    canvas.on('mouse:down', function (o) {
        isDown = true;
        var pointer = canvas.getPointer(o.e);
        origX = pointer.x;
        origY = pointer.y;
        circle = new fabric.Circle({
            left: pointer.x,
            top: pointer.y,
            radius: 1,
            strokeWidth: 1,
            fill: '#07ff11a3',
            stroke: 'black',
            selectable: false,
            originX: 'center', originY: 'center'
        });
        canvas.add(circle);
    });

    canvas.on('mouse:move', function (o) {
        if (!isDown) return;
        var pointer = canvas.getPointer(o.e);
        circle.set({ radius: Math.abs(origX - pointer.x) });
        canvas.renderAll();
    });

    canvas.on('mouse:up', function (o) {
        isDown = false;
    });

}

function removeEvents() {
    canvas.off('mouse:down');
    canvas.off('mouse:up');
    canvas.off('mouse:move');
}
<div class="fullpage">
  <div class="section">
  <a class="thmb" href="#" onclick="myFun()" style="padding: 0px 10px;margin:5px;border: 2px solid;">line</a>
  <a class="thmb" href="#" onclick="drawrec()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Rectangle</a>
  <a class="thmb" href="#" onclick="drawcle()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Circle</a>
    <div class="canvas-container">
      <canvas id="canvas1" style="border: 1px solid;width: 500px;height: 500px"></canvas>
    </div>
    <div class="furniture" style="padding: 20px;border: 1px solid;width: 460px">
      <h3>Drag the image to canvas</h3> 
      <img draggable="true" src="https://www.mve.com/media/Move_logo_-01.png" width="60">
    </div>
  </div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>

<script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.min.js'></script>

  


Solution

  • var canvas = window._canvas = new fabric.Canvas(canvasObject);
    

    inside initCanvas() you are again creating fabric canvas, so remove it. And to enable free drawing you need to do canvas.isDrawingMode = true

    function initCanvas() {
      $('.canvas-container').each(function(index) {
    
        var canvasContainer = $(this)[0];
        var canvasObject = $("canvas", this)[0];
    
        var imageOffsetX, imageOffsetY;
    
        function handleDragStart(e) {
          [].forEach.call(images, function(img) {
            img.classList.remove('img_dragging');
          });
          this.classList.add('img_dragging');
          var imageOffset = $(this).offset();
          imageOffsetX = e.clientX - imageOffset.left;
          imageOffsetY = e.clientY - imageOffset.top;
        }
    
        function handleDragOver(e) {
          if (e.preventDefault) {
            e.preventDefault();
          }
          e.dataTransfer.dropEffect = 'copy';
          return false;
        }
    
        function handleDragEnter(e) {
          this.classList.add('over');
        }
    
        function handleDragLeave(e) {
          this.classList.remove('over');
        }
    
        function handleDrop(e) {
          e = e || window.event;
          if (e.preventDefault) {
            e.preventDefault();
          }
          if (e.stopPropagation) {
            e.stopPropagation();
          }
          var img = document.querySelector('.furniture img.img_dragging');
          console.log('event: ', e);
    
          var offset = $(canvasObject).offset();
          var y = e.clientY - (offset.top + imageOffsetY);
          var x = e.clientX - (offset.left + imageOffsetX);
    
          var newImage = new fabric.Image(img, {
            width: img.width,
            height: img.height,
            left: x,
            top: y
          });
          canvas.add(newImage);
          return false;
        }
    
        function handleDragEnd(e) {
          [].forEach.call(images, function(img) {
            img.classList.remove('img_dragging');
          });
        }
    
        var images = document.querySelectorAll('.furniture img');
        [].forEach.call(images, function(img) {
          img.addEventListener('dragstart', handleDragStart, false);
          img.addEventListener('dragend', handleDragEnd, false);
        });
        canvasContainer.addEventListener('dragenter', handleDragEnter, false);
        canvasContainer.addEventListener('dragover', handleDragOver, false);
        canvasContainer.addEventListener('dragleave', handleDragLeave, false);
        canvasContainer.addEventListener('drop', handleDrop, false);
      });
    }
    initCanvas();
    
    var canvas = new fabric.Canvas('canvas1', {
      selection: false
    });
    
    var line, isDown;
    
    function drawLine() {
      removeEvents();
      changeObjectSelection(false);
      canvas.on('mouse:down', function(o) {
        isDown = true;
        var pointer = canvas.getPointer(o.e);
        var points = [pointer.x, pointer.y, pointer.x, pointer.y];
        line = new fabric.Line(points, {
          strokeWidth: 5,
          fill: '#07ff11a3',
          stroke: '#07ff11a3',
          originX: 'center',
          originY: 'center',
          selectable: false
        });
        canvas.add(line);
      });
      canvas.on('mouse:move', function(o) {
        if (!isDown) return;
        var pointer = canvas.getPointer(o.e);
        line.set({
          x2: pointer.x,
          y2: pointer.y
        });
        canvas.renderAll();
      });
    
      canvas.on('mouse:up', function(o) {
        isDown = false;
        line.setCoords();
      });
    }
    
    function drawrec() {
      var rect, isDown, origX, origY;
      removeEvents();
      changeObjectSelection(false);
    
      canvas.on('mouse:down', function(o) {
        isDown = true;
        var pointer = canvas.getPointer(o.e);
        origX = pointer.x;
        origY = pointer.y;
        var pointer = canvas.getPointer(o.e);
        rect = new fabric.Rect({
          left: origX,
          top: origY,
          originX: 'left',
          originY: 'top',
          width: pointer.x - origX,
          height: pointer.y - origY,
          angle: 0,
          selectable:false,
          fill: '#07ff11a3',
          stroke: 'black',
          transparentCorners: false
        });
        canvas.add(rect);
      });
    
      canvas.on('mouse:move', function(o) {
        if (!isDown) return;
        var pointer = canvas.getPointer(o.e);
    
        if (origX > pointer.x) {
          rect.set({
            left: Math.abs(pointer.x)
          });
        }
        if (origY > pointer.y) {
          rect.set({
            top: Math.abs(pointer.y)
          });
        }
    
        rect.set({
          width: Math.abs(origX - pointer.x)
        });
        rect.set({
          height: Math.abs(origY - pointer.y)
        });
    
    
        canvas.renderAll();
      });
      
      canvas.on('mouse:up', function(o) {
        isDown = false;
        rect.setCoords();
      });
    }
    
    function drawcle() {
      var circle, isDown, origX, origY;
      removeEvents();
      changeObjectSelection(false);
      canvas.on('mouse:down', function(o) {
        isDown = true;
        var pointer = canvas.getPointer(o.e);
        origX = pointer.x;
        origY = pointer.y;
        circle = new fabric.Circle({
          left: pointer.x,
          top: pointer.y,
          radius: 1,
          strokeWidth: 1,
          fill: '#07ff11a3',
          stroke: 'black',
          selectable: false,
          originX: 'center',
          originY: 'center'
        });
        canvas.add(circle);
      });
    
      canvas.on('mouse:move', function(o) {
        if (!isDown) return;
        var pointer = canvas.getPointer(o.e);
        circle.set({
          radius: Math.abs(origX - pointer.x)
        });
        canvas.renderAll();
      });
    
      canvas.on('mouse:up', function(o) {
        isDown = false;
        circle.setCoords();
      });
    
    }
    
    function enableFreeDrawing(){
      removeEvents();
      canvas.isDrawingMode = true;
    }
    
    function enableSelection() {
      removeEvents();
      changeObjectSelection(true);
      canvas.selection = true;
    }
    
    function changeObjectSelection(value) {
      canvas.forEachObject(function (obj) {
        obj.selectable = value;
      });
      canvas.renderAll();
    }
    
    function removeEvents() {
      canvas.isDrawingMode = false;
      canvas.selection = false;
      canvas.off('mouse:down');
      canvas.off('mouse:up');
      canvas.off('mouse:move');
    }
    <div class="fullpage">
      <div class="section">
      <a class="thmb" href="#" onclick="drawLine()" style="padding: 0px 10px;margin:5px;border: 2px solid;">line</a>
      <a class="thmb" href="#" onclick="drawrec()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Rectangle</a>
      <a class="thmb" href="#" onclick="drawcle()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Circle</a>
      <a class="thmb" href="#" onclick="enableFreeDrawing()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Drawing</a>
      <a class="thmb" href="#" onclick="enableSelection()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Selection</a>
        <div class="canvas-container">
          <canvas id="canvas1" style="border: 1px solid;width: 500px;height: 500px"></canvas>
        </div>
        <div class="furniture" style="padding: 20px;border: 1px solid;width: 460px">
          <h3>Drag the image to canvas</h3> 
          <img draggable="true" src="https://www.mve.com/media/Move_logo_-01.png" width="60">
        </div>
      </div>
    </div>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
    
    <script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.min.js'></script>