能否将画布图像复制到剪贴板?

24
我使用canvas.toDataURL("image/png", 0.7)从我的画布对象创建了一张图片。保存图片到上下文菜单中可以正常工作,但是将图片复制到剪贴板并粘贴到邮件或Word文档中等操作就无法正常工作了。有没有可能让"复制到剪贴板"像"普通"图片一样正常工作呢?
我考虑创建一个小型服务器组件,该组件可以接收基于base64的图像表示,并返回我能够复制到剪贴板的"普通"png图像。这种方法可行吗? 编辑: 澄清一下:我使用canvas.toDataURL("image/png", 0.7)从画布创建图像,然后将img标记的src属性设置为结果。然后,我可以右键单击图像选择“复制图像”。问题在于,我无法将图像粘贴到Word和电子邮件(至少Outlook中无法)。在Wordpad和mspaint中粘贴可以正常工作。

1
顺便说一下,Chrome(我认为FF也是)已经可以让你右键点击复制到剪贴板的画布内容了。剪贴板将包含从画布内容创建的.png图像。 - markE
@df1的答案对我很有效(但是……)。它唯一的缺点是它复制的是HTML格式化图像而不是二进制图像。一些支持图像粘贴的应用程序无法理解HTML格式化图像,然而所有应用程序都应该支持二进制图像,我已经寻找了很多,但到目前为止找不到任何生成它们的Javascript代码。 - Omar
6个回答

20

Chrome现在支持图像的剪贴板API。

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

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

示例

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

1
请注意,截至2020年10月,此功能仍处于试验阶段,并且在Firefox或Safari浏览器中不受支持:https://caniuse.com/mdn-api_clipboarditem - Josh Kelley
您可以在文章中查看完整的工作示例。目前,该API支持image/pngimage/svg+xml。更多支持正在到来,包括完整原始剪贴板访问计划。 - DenverCoder9

7
你可以将画布转换为 img,将其放入 <div contenteditable> 中,选择它并复制它。
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);

SelectText函数来自 https://dev59.com/oVwX5IYBdhLWcg3w-DbJ#40547470

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

4

更简单的一行代码:
假设你有一个画布(canvas)。
以下代码将把画布复制到剪贴板中(以blob形式为PNG图像)。

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

0

剪贴板功能仅在安全上下文(HTTPS)中可用,在某些或所有支持的浏览器中。 您需要将协议更改为https(SSL)

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

0

除了div.appendChild(img)的答案之外,这种选择方法在大多数浏览器上都适用:

window.getSelection().selectAllChildren(div);

截至2022年,使用ClipboardAPI的“正确”方法在Safari或Firefox上效果不佳。

完整代码:

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

`


-1

今天距离最初发布已经过去了4年,这是Google Chrome中星标最多的问题。使用JavaScript复制图像现在成为可能!

Chrome 76 Beta支持此功能:https://blog.chromium.org/2019/06/chrome-76-beta-dark-mode-payments-new.html

您可以在此处阅读完整草案: https://www.chromestatus.com/feature/5074658793619456

以及这里:https://w3c.github.io/clipboard-apis/#async-clipboard-api

示例:

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

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

你可以在这里测试:http://w3c-test.org/clipboard-apis/async-write-image-read-image-manual.https.html

(目前只支持 Chrome 76 beta)

更多信息:草案文档[包含示例]:https://docs.google.com/document/d/1lpi3-9vBP_1b7hZc2xBs0s_HaACJ6UigZZqHlJSNeJg/edit#heading=h.do75bvtsde7a


你确定你的示例代码吗?new Blob(["..."])将把你的DOM字符串转换为UTF8序列,也就是说它只是一个文本文件,包含此字符串,并不会将base64解码为实际的二进制数据。 - Kaiido
在Firefox中不起作用。 - serge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接