是否可以将画布图像复制到剪贴板?
Posted
技术标签:
【中文标题】是否可以将画布图像复制到剪贴板?【英文标题】:Is it possible to copy a canvas image to the clipboard? 【发布时间】:2015-03-07 22:54:15 【问题描述】:我使用canvas.toDataURL("image/png", 0.7)
从我的画布对象创建了一个图像。从上下文菜单中保存图像可以正常工作,但无法将图像复制到剪贴板并将其粘贴到邮件或 Word 文档中。是否可以让“复制到剪贴板”的行为与“正常”图像的行为方式相同?
我正在考虑创建一个小型服务器组件,它可以采用 base64 表示的图像并返回一个“正常”的 png 图像,我可以将其复制到剪贴板。这可以作为一种解决方法吗?
编辑:
澄清:我使用canvas.toDataURL("image/png", 0.7)
从画布创建图像,然后将img
标记的src
属性设置为结果。然后我可以在右键单击图像时从上下文菜单中选择“复制图像”。问题是我无法将图像粘贴到 Word 和电子邮件中(至少是 Outlook)。粘贴到写字板和 mspaint 可以正常工作。
【问题讨论】:
顺便说一句,Chrome(我也认为是 FF)已经让您可以右键单击复制到剪贴板的画布内容。剪贴板将包含一个从画布内容创建的 .png 图像。 @df1 答案对我来说效果很好(但是……)。它唯一的缺点是它复制 html 格式的图像而不是二进制图像。一些支持图像粘贴的应用程序不理解 HTML 格式的图像,但是所有应用程序都应该支持二进制图像,我已经寻找了很多并且无法访问任何生成它们的 javascript 代码。 【参考方案1】:用于图像的剪贴板 API 现在可在 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]);
);
【讨论】:
请注意,截至 2020 年 10 月,这是实验性的,在 Firefox 或 Safari 中不受支持:caniuse.com/mdn-api_clipboarditem 您可以在article 中查看完整的工作示例。目前,API 支持image/png
和image/svg+xml
。更多支持是 coming,包括完整原始剪贴板访问的计划。【参考方案2】:
您可以将画布转换为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://***.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);
【讨论】:
【参考方案3】:更容易 1 班轮: 假设你有一个画布。 以下代码会将画布(作为 blob --> PNG 图像)复制到剪贴板。
canvas.toBlob(blob => navigator.clipboard.write([new ClipboardItem('image/png': blob)]))
navigator.clipboard
【讨论】:
【参考方案4】:要添加到 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 );
`
【讨论】:
【参考方案5】:4 年后的今天,它是谷歌浏览器中星级最高的一期。使用 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(["...
会将您的 DOMString 转换为 UTF8 序列,即它只是一个带有此字符串的文本文件,它不会将 base64 解码为实际的二进制数据。以上是关于是否可以将画布图像复制到剪贴板?的主要内容,如果未能解决你的问题,请参考以下文章
Android - 将图像复制到剪贴板,有人得到这个工作吗?
异步剪贴板 API“ClipboardItem 未定义” - Reactjs 将图像复制到剪贴板