Search code examples
javascriptjquerycanvasfabricjsclipboard

Paste image from clipboard to fabric.js canvas?


I'm trying to create a function that pastes an image from the user's clipboard to the canvas as a new fabric.Image(). Any search result I find either describes cloning objects already on the canvas or pasting IText data. This SO question is related to what I'm asking about, but it's 4 years old and the function in the top answer doesn't work:

How to do Copy and paste the image from User system to Canvas using fabric.js

Here's the code I'm currently trying to use. I'm trying to set up a paste function I can call later:

var $wrapper = $('#content'), 
  canvas = new fabric.Canvas('canvas', {
    width: 400,
    height: 550
  }),
pasteImage = function (e) {
    var items=e.originalEvent.clipboardData.items;

    e.preventDefault();
    e.stopPropagation();

    // Fabric.js image function
    function canvasImage(url) {
      var img = new fabric.Image(url);
      img.scale(0.75).center().setCoords();
      canvas.add(img).renderAll();
    }

    //Loop through files
    for(var i=0;i<items.length;i++){
      var file = items.items[i],
          type = file.type;

      if (type.indexOf("image")!=-1) {
        var imageData = file.getAsFile();
        var imageURL=window.webkitURL.createObjectURL(imageData);
        canvasImage(imageURL);
      }
    }
  };
$wrapper.on('paste', pasteImage);

Here's a fiddle to see it in action (or inaction, I guess). This will eventually be part of a Photoshop plugin, so thankfully I only need to worry about this working in Chrome.


Solution

  • I couldn't get your paste event handler to trigger, because i'm not sure if div can natively take the past event unless you make it a contenteditable div, which in your use case i doubt you want to do.

    I just recently implemented this in an app of my own, but i wasn't using fabric, just native canvas and js.

    You're going to have to rework your code, but try changing

    $wrapper.on('paste', pasteImage);
    

    to

    $(window).on('paste', pasteImage);
    

    Regardless, I tinkered with your current code, and this is what I got to work, albeit it might not have your settings being triggered completely, but it is pasting the image in:

    (function() {
      var $wrapper = $('#content'), 
          canvas = new fabric.Canvas('canvas', {
            width: 400,
            height: 550
          }),
          txtStyles = {
            top: 100,
            left: 200,
            padding: 6,
            fill: '#d6d6d6',
            fontFamily: 'sans-serif',
            fontSize: '24',
            originY: 'center',
            originX: 'center',
            borderColor: '#d6d6d6',
            cornerColor: '#d6d6d6',
            cornerSize: 5,
            cornerStyle: 'circle',
            transparentCorners: false,
            lockUniScaling: true
          },
          imgAttrs = {
            left: 200,
            top: 200,
            originY: 'center',
            originX: 'center',
            borderColor: '#d6d6d6',
            cornerColor: '#d6d6d6',
            cornerSize: 5,
            cornerStyle: 'circle',
            transparentCorners: false,
            lockUniScaling: true
          },
          introTxt = new fabric.Text('Paste images here', txtStyles),
          pasteImage = function (e) {
            var items=e.originalEvent.clipboardData.items;
    
            e.preventDefault();
            e.stopPropagation();
    
            //Loop through files
            for(var i=0;i<items.length;i++){
              if (items[i].type.indexOf('image')== -1) continue;
              var file = items[i],
                  type = items[i].type;
              var imageData = file.getAsFile();
              var URLobj = window.URL || window.webkitURL;
              var img = new Image();
              img.src = URLobj.createObjectURL(imageData);
              fabric.Image.fromURL(img.src, function(img){
                canvas.add(img);
              });
            }
          },
    
          //Canvas starter text
          introCanvas = function() {
            canvas.add(introTxt);
          };
    
      introCanvas();
      $(window).on('paste', pasteImage);
    })();
    

    fiddlers: https://jsfiddle.net/c0kw5dbu/3/