Clipboard - Web API 接口參考 | MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p id="cli">https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem</p>
<img src="https://static-file.qiniu.io/www/admin/1607061731" width="128" id="test" alt="123"/>
</body>
</html>
<script>
let imgSrc = document.getElementById("test").src;
console.log(imgSrc);
async function writeClipImg(imgSrc) {
try {
const imgURL = imgSrc;
const data = await fetch(imgURL);
const blob = await data.blob();
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
console.log('Fetched image copied.');
} catch (err) {
console.error(err.name, err.message);
}
};
document.getElementById('cli').addEventListener('click', async () => {
writeClipImg(imgSrc);
})
</script>
注意:
1、
直接在控制台執行:
writeClipImg(imgSrc)
NotAllowedError Document is not focused.
可以通過click頁面元素觸發。
2、
await
await navigator.clipboard.write
Clipboard
Clipboard 接口實現了 Clipboard API,如果用戶授予了相應的權限,就能提供系統剪貼板的讀寫訪問。在 Web 應用程序中,Clipboard API 可用於實現剪切、復制和粘貼功能。
系統剪貼板暴露於全局屬性 Navigator.clipboard 之中。
如果用戶沒有適時使用 Permissions API 授予相應權限和"clipboard-read" 或 "clipboard-write" 權限,調用 Clipboard 對象的方法不會成功。
注意:實際上,現在瀏覽器對於訪問剪貼板權限的索取各有不同,在章節 剪貼板可用性 查看更多細節。
所有剪貼板 API 方法都是異步的;它們返回一個 Promise 對象,在剪貼板訪問完成后被執行。如果剪貼板訪問被拒絕,promise 也會被拒絕。
方法
Clipboard 繼承自 EventTarget 接口,因此擁有它的方法。
-
read() -
從剪貼板讀取數據(比如圖片),返回一個
Promise對象。When the data has been retrieved, the promise is resolved with aDataTransferobject that provides the data。 -
readText() -
從操作系統讀取文本;returns a
Promisewhich is resolved with aDOMStringcontaining the clipboard's text once it's available。 -
write() -
寫入任意數據至操作系統剪貼板。This asynchronous operation signals that it's finished by resolving the returned
Promise。 -
writeText() -
寫入文本至操作系統剪貼板。returning a
Promisewhich is resolved once the text is fully copied into the clipboard。
剪貼板可用性
異步剪貼板 API 是一個相對較新的 API,瀏覽器仍在逐漸實現它。由於潛在的安全問題和技術復雜性,大多數瀏覽器正在逐步集成這個 API。
例如,Firefox 不支持 "clipboard-read" 和 "clipboard-write" 權限,所以使用其他方式訪問或改變剪貼板中的內容會受限。
對於瀏覽器擴展來說,你可以要求 clipboardRead 和 clipboardWrite 權限以使用 clipboard.readText() 和 clipboard.writeText()。但基於 HTTP 的網站中包含的腳本則不能獲得剪貼板對象。參考 extensions in Firefox 63。
除此之外, read() 以及write() 是默認禁用且需要修改偏好設置來啟用的。在使用之前請先確認瀏覽器兼容性表格。
規范
| 規范 | 狀態 | 備注 |
|---|---|---|
| Clipboard API and events Clipboard |
Working Draft | Initial definition. |
Clipboard.write()
Clipboard 的方法 write() 寫入圖片等任意的數據到剪貼板。 這個方法可以用於實現剪切和復制的功能。
但是你要提前獲取 "Permissions API" 的 "clipboard-write" 權限才能將數據寫入到剪貼板。
注意: 瀏覽器對這個異步剪貼板的 API 仍然在討論中。所以在使用它之前請檢查 compatibility table 和 Clipboard availability in Clipboard 以獲得更多的兼容性信息。
語法
var promise = navigator.clipboard.write(dataTransfer)
參數
-
dataTransfer -
DataTransfer對象包含了要寫入剪貼板的數據。
返回值
示例
這個例子展示了如何將當前剪貼板的內容替換為給定的內容。
function setClipboard(text) { let data = new DataTransfer(); data.items.add("text/plain", text); navigator.clipboard.write(data).then(function() { /* success */ }, function() { /* failure */ }); }
代碼創建了一個 DataTransfer 對象,要替換的內容存儲在這里。執行 DataTransferItemList.add() (en-US) 將數據寫入進去,然后執行 write() 方法,指定執行成功或錯誤的結果。
規范
| 規范 | 狀態 | 備注 |
|---|---|---|
| Clipboard API and events write() |
Navigator.clipboard - Web API 接口參考 | MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/clipboard
Navigator.clipboard
剪貼板 Clipboard API 為 Navigator 接口添加了只讀屬性 clipboard,該屬性返回一個可以讀寫剪切板內容的 Clipboard 對象。 在 Web 應用中,剪切板 API 可用於實現剪切、復制、粘貼的功能。
只有在用戶事先授予網站或應用對剪切板的訪問許可之后,才能使用異步剪切板讀寫方法。許可操作必須通過取得權限 Permissions API 的 "clipboard-read" 和/或 "clipboard-write" 項獲得。
語法
theClipboard = navigator.clipboard;
值
用於訪問系統剪切板的 Clipboard 對象。
示例
以下代碼使用 navigator.clipboard 來訪問系統剪切板,以讀取系統剪切板的內容。
navigator.clipboard.readText().then( clipText => document.querySelector(".cliptext").innerText = clipText);;
這個代碼片段將 HTML 中擁有類名 "cliptext" 的第一個元素的內容替換為剪切板中的內容。這段代碼可用於在瀏覽器拓展中定時自動更新或者由事件觸發,實時顯示當前剪切板上的內容。
如果剪切板為空,或者不包含文本,則 "cliptext" 元素的內容將被清空。這是因為在剪切板為空或者不包含文本時,readText() 會返回一個空字符串。
標准
ClipboardItem
The ClipboardItem interface of the Clipboard API represents a single item format, used when reading or writing data via the Clipboard API. That is clipboard.read() and clipboard.write() respectively.
The benefit of having the ClipboardItem interface to represent data, is that it enables developers to cope with the varying scope of file types and data easily.
Access to the contents of the clipboard is gated behind the Permissions API: The clipboard-write permission is granted automatically to pages when they are in the active tab. The clipboard-read permission must be requested, which you can do by trying to read data from the clipboard.
Note: To work with text see the Clipboard.readText() and Clipboard.writeText() methods of the Clipboard interface.
Note: You can only pass in one clipboard item at a time.
Constructor
-
ClipboardItem.ClipboardItem() -
Creates a new
ClipboardItemobject, with the MIME type as the key andBlobas the value
Properties
This interface provides the following properties.
-
typesRead only -
Returns an
Arrayof MIME types available within theClipboardItem. -
presentationStyleRead only -
Returns one of the following:
"unspecified","inline"or"attachment".
Methods
This interface defines the following methods.
Examples
Writing To Clipboard
Here we're writing a new ClipboardItem.ClipboardItem() to the clipboard by requesting a png image using the Fetch API, and in turn, the responses' blob() method, to create the new ClipboardItem.
async function writeClipImg() { try { const imgURL = '/myimage.png'; const data = await fetch(imgURL); const blob = await data.blob(); await navigator.clipboard.write([ new ClipboardItem({ [blob.type]: blob }) ]); console.log('Fetched image copied.'); } catch(err) { console.error(err.name, err.message); } }
Reading From The Clipboard
Here we're returning all items on the clipboard via the clipboard.read() method. Then utilizing the ClipboardItem.types property to set the getType() argument and return the corresponding blob object.
async function getClipboardContents() { try { const clipboardItems = await navigator.clipboard.read(); for (const clipboardItem of clipboardItems) { for (const type of clipboardItem.types) { const blob = await clipboardItem.getType(type); // we can now use blob here } } } catch (err) { console.error(err.name, err.message); } }
Interact with the clipboard
有兩種方式可以讓瀏覽器擴展與系統剪貼板交互: Document.execCommand() 方法以及現代的異步的 Clipboard API.
Document.execCommand() 方法常通過以下指令使用:
document.execCommand("copy")document.execCommand("cut")document.execCommand("paste")
Clipboard API 提供了異步的連接來直接讀寫剪貼板內容. 例, 如此從剪貼板讀取文本:
navigator.clipboard.readText().then(text => outputElem.innerText = text);
這將請求剪貼板內容, 並且當接收到響應時存儲剪貼板文本到一個元素的 innerText.
注意: 異步的 Clipboard API 方法是一個近期新增的規范, 並且這個規范可能不適用於所有瀏覽器. 請在使用前測試了每一種方法的兼容性, 以確保支持滿足您的需求.
寫入系統粘貼板
有兩種向剪貼板寫入數據的方法. 你可以使用 document.execCommand() 來觸發 "剪切" 和 "復制" 行為, 這將用選擇的數據覆蓋剪貼板的當前內容. 另一個選項是使用 Clipboard API 的 Clipboard.writeText() 或 Clipboard.write() 方法來用指定數據覆蓋剪貼板內容.
使用 execCommand()
document.execCommand() 方法的 "cut" 與 "copy" 命令可以被用於以選中素材代替剪貼板的當前內容. 這些命令無需任何特別的權限就可以使用, 如果你在一個用於用戶操作的短生存期的事件處理程序中使用他們(例如, 一次點擊事件).
例如,假設你有一個下面的彈出菜單頁面:
<input id="input" type="text"/> <button id="copy">Copy</button>
使 "copy"按鈕能復制 "input"中的文本,代碼如下:
function copy() { var copyText = document.querySelector("#input"); copyText.select(); document.execCommand("Copy"); } document.querySelector("#copy").addEventListener("click", copy);
由於execCommand()命令在單擊事件中,所以不需要特別的權限。
此外,如果用警報(alarm)替換上面的命令來觸發復制事件:
function copy() { var copyText = document.querySelector("#input"); copyText.select(); document.execCommand("Copy"); } browser.alarms.create({ delayInMinutes: 0.1 }); browser.alarms.onAlarm.addListener(copy);
這種觸發不一定成功,它取決於瀏覽器是否支持。Firefox瀏覽器就不支持該功能,你會在瀏覽器控制台中看到以下信息:
"document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler."
為了能夠在這種情形下使用,你需要擁有"clipboardWrite"的權限( permission)。 因此,"clipboardWrite"權限能使你不通過臨時事件處理程序就可以寫入系統粘貼板中。
使用 Clipboard API
Clipboard API 更加靈活, 因為你不僅可以將當前選擇復制到剪貼板中, 還可以直接指定要放入剪貼板的信息.
要使用 Clipboard API 需要在你的 manifest.json 文件中申請 clipboardRead 與 clipboardWrite 權限.
對於頁面腳本, 需要權限 API 的 clipboard-write 權限. 你可通過 navigator.permissions.query() (en-US) 來檢查這個權限:
navigator.permissions.query({name: "clipboard-write"}).then(result => { if (result.state == "granted" || result.state == "prompt") { /* write to the clipboard now */ } });
這個函數使用一個字符串作為輸入並且用它更新剪貼板:
function updateClipboard(newClip) { navigator.clipboard.writeText(newClip).then(function() { /* clipboard successfully set */ }, function() { /* clipboard write failed */ }); }
特定瀏覽器注意事項
這里涉及的剪貼板和其他API正在快速發展, 因此瀏覽器在工作方式上存在差異.
在Chrome中:
- 你可以在所有執行上下文中寫入系統粘貼板,像背景網頁、內容腳本、標簽頁和彈出菜單。
- 你不需要
"clipboardWrite"權限,甚至不需要在用戶生成的事件處理程序中寫入粘貼板
在Firefox中:
- 除了背景網頁外,你可以在所有執行上下文中使用 execCommand 寫入粘貼板。在Firefox中,你無法選擇文本或將輸入字段聚焦在后台頁面中,因此無法使用 execCommand 從后台頁面寫入剪貼板。
- 只有version 51以上才支持"clipboardWrite" 權限。
- 從 version 57 開始,可以使用
clipboard.setImageData()API 將圖像復制到剪貼板。 - 在 Firefox 633 中添加了對 Clipboard API
navigator.clipboard.writeText()方法的支持。 - 當使用一個內容腳本,Clipboard API 只可用於 HTTPS 頁。解決方法是,在內容腳本和后台腳本之間使用消息傳遞。
讀取系統粘貼板
execCommand() 方法提供了 "paste" 指令,能讓你粘貼內容。你可以使用 Clipboard API 的更靈活的方法: Clipboard.read() 和 Clipboard.readText()。
使用 execCommand()
首先,你需要為擴展申請 "clipboardRead" permission 。即便你在用戶生成的事件處理程序 ( 例如 click (en-US) 或 keypress (en-US) ) 中使用 "paste" 指令也是如此。
假設你的HTML頁面內容如下:
<input id="output" type="text"/> <button id="paste">粘貼</button>
要在用戶單機 id 為 "paste" 的 <button> 時從剪貼板設置 id 為 "output" 的 <textarea> 的內容,可以使用這樣的代碼:
function paste() { var pasteText = document.querySelector("#output"); pasteText.focus(); document.execCommand("paste"); console.log(pasteText.textContent); } document.querySelector("#paste").addEventListener("click", paste);
使用 Clipboard API
剪貼板 API 的 navigator.clipboard.readText() 和 navigator.clipboard.read() 方法讓你從剪貼板讀取任意文本或二進制數據。這讓你從剪貼板訪問數據無需將它們粘貼至一個可編輯的元素中。
一旦你通過 Permissions API 獲取了 "clipboard-read" 權限,你就可以輕松讀取剪貼板:
navigator.clipboard.readText().then(clipText => document.getElementById("outbox").innerText = clipText);
這個代碼片段從剪貼板提取文本並且用該文本替換 ID 為 "outbox" 的元素的當前內容。
特定瀏覽器注意事項
Firefox 在 54 版本提供了 "clipboardRead" permission ,但是僅支持向處於 內容可編輯模式 的元素粘貼,對於內容腳本,只能在 <textarea> 工作。對於后台腳本,任何元素都可被設置為內容可編輯模式。
復制指定區域,比如一張圖片
window.getSelection().removeAllRanges();
let range = document.createRange()
//img標簽id
range.selectNode(document.querySelector('#imgId'));
window.getSelection().addRange(range);
document.execCommand("Copy");
window.getSelection().removeAllRanges();
