gusjap
gusjap

Reputation: 2515

Is it possible to copy a canvas image to the clipboard?

I've created an image from my canvas object by using canvas.toDataURL("image/png", 0.7). It works fine to save the image from the context menu but it doesn't work to copy the image to the clipboard and paste it into a mail or a word document for example. Is it possible to get "copy to clipboard" to behave the same way it does for a "normal" image?

I'm thinking of creating a small server component that can take the base64 representation of the image and return a "normal" png image that I will be able to copy to clipboard. Could this work as a workaround?

Edit: To clearify: I'm using canvas.toDataURL("image/png", 0.7) to create an image from the canvas and I then set the src attribute of an img tag to the result. I can then select "copy image" from the context menu when right clicking on the image. The problem is then that I can't paste the image into Word and emails (Outlook at least). Pasting into Wordpad and mspaint works fine.

Upvotes: 25

Views: 33349

Answers (6)

Hoàng Vũ Tgtt
Hoàng Vũ Tgtt

Reputation: 2032

Clipboard feature is available only in secure contexts (HTTPS), in some or all supporting browsers. You need change protocol to https (SSL)

if (location.protocol !== 'https:') {
    location.replace(`https:${location.href.substring(location.protocol.length)}`);
}

Upvotes: -1

dwhitnee
dwhitnee

Reputation: 1

To add to the div.appendChild( img ) answer, this method of selecting works on most browsers:

window.getSelection().selectAllChildren( div );

As of 2022, the "right" way using ClipboardAPI does not work well on Safari or Firefox.

Complete code:

const canvas = document.getElementById("share");

let img = document.createElement('img'); 
img.src = canvas.toDataURL();

let div = document.createElement('div');
div.contentEditable = true;
div.appendChild( img );
document.body.appendChild( div );
div.focus();
window.getSelection().selectAllChildren( div );
document.execCommand('Copy');  // technically deprecated
document.body.removeChild( div );

`

Upvotes: 0

Konstantinos
Konstantinos

Reputation: 973

Much easier 1 liner:
Assuming u have a canvas.
The following code will copy the canvas (as blob --> PNG image) to your clipboard.

canvas.toBlob(blob => navigator.clipboard.write([new ClipboardItem({'image/png': blob})]))

Upvotes: 5

Adriano Tumminelli
Adriano Tumminelli

Reputation: 231

Clipboard API for images are now available on chrome

https://github.com/web-platform-tests/wpt/tree/master/clipboard-apis

const item = new ClipboardItem({ "image/png": blob });
navigator.clipboard.write([item]); 

Example

const canvas = document.createElement("canvas");
canvas.width = 100;
canvas.height = 100;
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#eee";
ctx.fillRect(10, 10, 50, 50);

//tested on chrome 76
canvas.toBlob(function(blob) { 
    const item = new ClipboardItem({ "image/png": blob });
    navigator.clipboard.write([item]); 
});

Upvotes: 22

Aminadav Glickshtein
Aminadav Glickshtein

Reputation: 24590

Today 4 years later, it's the most starred issue in Google Chrome. To copy images using JavaScript. And now it's possible!

Chrome 76 Beta supports it: https://blog.chromium.org/2019/06/chrome-76-beta-dark-mode-payments-new.html

You can read the full draft here: https://www.chromestatus.com/feature/5074658793619456

and here: https://w3c.github.io/clipboard-apis/#async-clipboard-api

Example:

var data = new Blob(["iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg=="], {type : "image/png"});

  const clipboardItemInput = new ClipboardItem({'image/png' : blobInput});
  await navigator.clipboard.write([clipboardItemInput]);

You can test it here: http://w3c-test.org/clipboard-apis/async-write-image-read-image-manual.https.html

(Now it support only Chrome 76 beta)

More info: The draft document [contain examples]: https://docs.google.com/document/d/1lpi3-9vBP_1b7hZc2xBs0s_HaACJ6UigZZqHlJSNeJg/edit#heading=h.do75bvtsde7a

Upvotes: -1

df1
df1

Reputation: 464

You can convert the canvas to img, put in inside a <div contenteditable>, select it and copy it.

var img = document.createElement('img');
img.src = canvas.toDataURL()

var div = document.createElement('div');
div.contentEditable = true;
div.appendChild(img);
document.body.appendChild(div);

// do copy
SelectText(div);
document.execCommand('Copy');
document.body.removeChild(div);

The SelectText function is from https://stackoverflow.com/a/40547470/1118626

function SelectText(element) {
    var doc = document;
    if (doc.body.createTextRange) {
        var range = document.body.createTextRange();
        range.moveToElementText(element);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();
        var range = document.createRange();
        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);
    }
}

Upvotes: 9

Related Questions