日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
想要復制圖像?ClipboardAPI了解一下

在寫了 這個 29.7 K 的剪貼板 JS 庫有點東西! 這篇文章之后,收到了小伙伴提的兩個問題:

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供西藏網(wǎng)站建設(shè)、西藏做網(wǎng)站、西藏網(wǎng)站設(shè)計、西藏網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、西藏企業(yè)網(wǎng)站模板建站服務,10年西藏做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡服務。

1.clipboard.js 這個庫除了復制文字之外,能復制圖像么?

2.clipboard.js 這個庫依賴的 document.execCommand API 已被廢棄了,以后應該怎么辦?

(圖片來源:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand)

接下來,本文將圍繞上述兩個問題展開,不過在看第一個問題之前,我們先來簡單介紹一下 剪貼板 。

  • 剪貼板(英語:clipboard),有時也稱剪切板、剪貼簿、剪貼本。它是一種軟件功能,通常由操作系統(tǒng)提供,作用是使用復制和粘貼操作短期存儲數(shù)據(jù)和在文檔或應用程序間轉(zhuǎn)移數(shù)據(jù)。它是圖形用戶界面(GUI)環(huán)境中最常用的功能之一,通常實現(xiàn)為匿名、臨時的數(shù)據(jù)緩沖區(qū),可以被環(huán)境內(nèi)的大部分或所有程序使用編程接口訪問?!?維基百科

通過以上的描述我們可以知道,剪貼板架起了一座橋梁,使得在各種應用程序之間,傳遞和共享信息成為可能。然而美中不足的是,剪貼板只能保留一份數(shù)據(jù),每當新的數(shù)據(jù)傳入,舊的便會被覆蓋。

了解完 剪貼板 的概念和作用之后,我們馬上來看一下第一個問題:clipboard.js 這個庫除了復制文字之外,能復制圖像么?

一、clipboard.js 能否復制圖像?

clipboard.js 是一個用于將 文本 復制到剪貼板的 JS 庫。沒有使用 Flash,沒有使用任何框架,開啟 gzipped 壓縮后僅僅只有 3kb。

(圖片來源:https://clipboardjs.com/#example-text)

當你看到 “A modern approach to copy text to clipboard” 這個描述,你是不是已經(jīng)知道答案了。那么實際的情況是怎樣呢?下面我們來動手驗證一下。在 這個 29.7 K 的剪貼板 JS 庫有點東西! 這篇文章中,阿寶哥介紹了在實例化 ClipboardJS 對象時,可以通過 options 對象的 target 屬性來設(shè)置復制的目標:

 
 
 
 
  1. // https://github.com/zenorocha/clipboard.js/blob/master/demo/function-target.html
  2. let clipboard = new ClipboardJS('.btn', {
  3.   target: function() {
  4.     return document.querySelector('div');
  5.   }
  6. });

利用 clipboard.js 的這個特性,我們可以定義以下 HTML 結(jié)構(gòu):

  
 
 
 
  1.    
  2.    

    大家好,我是阿寶哥

  • 復制
  •  然后在實例化 ClipboardJS 對象時設(shè)置復制的目標是 #container 元素:

     
     
     
     
    1. const clipboard = new ClipboardJS(".btn", {
    2.   target: function () {
    3.     return document.querySelector("#container");
    4.   }
    5. });

    之后,我們點擊頁面中的 復制 按鈕,對應的效果如下圖所示:

    觀察上圖可知,頁面中的圖像和文本都已經(jīng)被復制了。對于文本來說,大家應該都很清楚。而對于圖像來說,到底復制了什么?我們又該如何獲取已復制的內(nèi)容呢?針對這個問題,我們可以利用 HTMLElement 對象上的 onpaste 屬性或者監(jiān)聽元素上的 paste 事件。

    這里我們通過設(shè)置 document 對象的 onpaste 屬性,來打印一下粘貼事件對應的事件對象:

     
     
     
     
    1. document.onpaste = function (e) {
    2.   console.dir(e);
    3. }

    當我們點擊 復制 按鈕,然后在頁面執(zhí)行 粘貼 操作后,控制臺會打印出以下內(nèi)容:

    通過上圖可知,在 ClipboardEvent 對象中含有一個 clipboardData 屬性,該屬性包含了與剪貼板相關(guān)聯(lián)的數(shù)據(jù)。詳細分析了 clipboardData 屬性之后,我們發(fā)現(xiàn)已復制的圖像和普通文本被封裝為 DataTransferItem 對象。

    為了更方便地分析 DataTransferItem 對象,阿寶哥重新更新了 document 對象的 onpaste屬性:

    在上圖中,我們可以清楚的看到 DataTransferItem 對象上含有 kind 和 type 屬性分別用于表示數(shù)據(jù)項的類型(string 或 file)及數(shù)據(jù)對應的 MIME 類型。利用 DataTransferItem 對象提供的 getAsString 方法,我們可以獲取該對象中保存的數(shù)據(jù):

    相信看完以上的輸出結(jié)果,小伙伴們就很清楚第一個問題的答案了。那么如果想要復制圖像的話,應該如何實現(xiàn)呢?其實這個問題的答案與小伙伴提的第二個問題的答案是一樣的,我們可以利用 Clipboard API 來實現(xiàn)復制圖像的問題及解決 document.execCommand API 已被廢棄的問題。

    接下來,我們的目標就是實現(xiàn)復制圖像的功能了,因為要利用到 Clipboard API,所以阿寶哥先來介紹一下該 API。

    二、Clipboard API 簡介

    Clipboard 接口實現(xiàn)了 Clipboard API,如果用戶授予了相應的權(quán)限,就能提供系統(tǒng)剪貼板的讀寫訪問。在 Web 應用程序中,Clipboard API 可用于實現(xiàn)剪切、復制和粘貼功能。該 API 用于取代通過 document.execCommand API 來實現(xiàn)剪貼板的操作。

    在實際項目中,我們不需要手動創(chuàng)建 Clipboard 對象,而是通過 navigator.clipboard來獲取 Clipboard 對象:

    在獲取 Clipboard 對象之后,我們就可以利用該對象提供的 API 來訪問剪貼板,比如:

     
     
     
     
    1. navigator.clipboard.readText().then(
    2.   clipText => document.querySelector(".editor").innerText = clipText);

    以上代碼將 HTML 中含有 .editor 類的第一個元素的內(nèi)容替換為剪貼板的內(nèi)容。如果剪貼板為空,或者不包含任何文本,則元素的內(nèi)容將被清空。這是因為在剪貼板為空或者不包含文本時,readText 方法會返回一個空字符串。

    在繼續(xù)介紹 Clipboard API 之前,我們先來看一下 Navigator API: clipboard 的兼容性:

    (圖片來源:https://caniuse.com/mdn-api_navigator_clipboard)

    異步剪貼板 API 是一個相對較新的 API,瀏覽器仍在逐漸實現(xiàn)它。由于潛在的安全問題和技術(shù)復雜性,大多數(shù)瀏覽器正在逐步集成這個 API。對于瀏覽器擴展來說,你可以請求 clipboardRead 和 clipboardWrite 權(quán)限以使用 clipboard.readText() 和 clipboard.writeText()。

    好的,接下來阿寶哥來演示一下如何使用 clipboard 對象提供的 API 來操作剪貼板,以下示例的運行環(huán)境是 Chrome 87.0.4280.88。

    三、將數(shù)據(jù)寫入到剪貼板

    3.1 writeText()

    writeText 方法可以把指定的字符串寫入到系統(tǒng)的剪貼板中,調(diào)用該方法后會返回一個 Promise 對象:

     
     
     
     
    1. 拷貝當前頁面地址

    對于上述代碼,當用戶點擊 拷貝當前頁面地址 按鈕時,將會把當前的頁面地址拷貝到剪貼板中。

    3.2 write()

    write 方法除了支持文本數(shù)據(jù)之外,還支持將圖像數(shù)據(jù)寫入到剪貼板,調(diào)用該方法后會返回一個 Promise 對象。

     
     
     
     
    1. 拷貝當前頁面地址

    在以上代碼中,我們先通過 Blob API 創(chuàng)建 Blob 對象,然后使用該 Blob 對象來構(gòu)造 ClipboardItem 對象,最后再通過 write 方法把數(shù)據(jù)寫入到剪貼板。介紹完如何將數(shù)據(jù)寫入到剪貼板,下面我們來介紹如何從剪貼板中讀取數(shù)據(jù)。

    四、從剪貼板中讀取數(shù)據(jù)

    4.1 readText()

    readText 方法用于讀取剪貼板中的文本內(nèi)容,調(diào)用該方法后會返回一個 Promise 對象:

     
     
     
     
    1. 讀取剪貼板中的文本

    對于上述代碼,當用戶點擊 讀取剪貼板中的文本 按鈕時,如果當前剪貼板含有文本內(nèi)容,則會讀取剪貼板中的文本內(nèi)容。

    4.2 read()

    read 方法除了支持讀取文本數(shù)據(jù)之外,還支持讀取剪貼板中的圖像數(shù)據(jù),調(diào)用該方法后會返回一個 Promise 對象:

     
     
     
     
    1. 讀取剪貼板中的內(nèi)容

    對于上述代碼,當用戶點擊 讀取剪貼板中的內(nèi)容 按鈕時,則會開始讀取剪貼板中的內(nèi)容。到這里 clipboard 對象中涉及的 4 個 API,阿寶哥都已經(jīng)介紹完了,最后我們來看一下如何實現(xiàn)復制圖像的功能。

    五、實現(xiàn)復制圖像的功能

    在最后的這個示例中,阿寶哥將跟大家一步步實現(xiàn)復制圖像的核心功能,除了復制圖像之外,還會同時支持復制文本。在看具體代碼前,我們先來看一下實際的效果:

    在上圖對應的網(wǎng)頁中,我們先點擊 復制 按鈕,則圖像和文本都會被選中。之后,我們在點擊 粘貼 按鈕,則控制臺會輸出從剪貼板中讀取的實際內(nèi)容。在分析具體的實現(xiàn)方式前,我們先來看一下對應的頁面結(jié)構(gòu):

     
     
     
     
    1.    
    2.    

      大家好,我是阿寶哥

  • 復制
  • 粘貼
  •  上面的頁面結(jié)構(gòu)很簡單,下一步我們來逐步分析一下以上功能的實現(xiàn)過程。

    5.1 請求剪貼板寫權(quán)限

    默認情況下,會為當前的激活的頁面自動授予剪貼板的寫入權(quán)限。出于安全方面考慮,這里我們還是主動向用戶請求剪貼板的寫入權(quán)限:

     
     
     
     
    1. async function askWritePermission() {
    2.   try {
    3.     const { state } = await navigator.permissions.query({
    4.       name: "clipboard-write",
    5.     });
    6.       return state === "granted";
    7.   } catch (error) {
    8.       return false;
    9.   }
    10. }

    5.2 往剪貼板寫入圖像和普通文本數(shù)據(jù)

    要往剪貼板寫入圖像數(shù)據(jù),我們就需要使用 navigator.clipboard 對象提供的 write 方法。如果要寫入圖像數(shù)據(jù),我們就需要獲取該圖像對應的 Blob 對象,這里我們可以通過 fetch API 從網(wǎng)絡上獲取圖像對應的響應對象并把它轉(zhuǎn)化成 Blob 對象,具體實現(xiàn)方式如下:

     
     
     
     
    1. async function createImageBlob(url) {
    2.   const response = await fetch(url);
    3.   return await response.blob();
    4. }

    而對于普通文本來說,只需要使用前面介紹的 Blob API 就可以把普通文本轉(zhuǎn)換為 Blob 對象:

     
     
     
     
    1. function createTextBlob(text) {
    2.   return new Blob([text], { type: "text/plain" });
    3. }

    在創(chuàng)建完圖像和普通文本對應的 Blob 對象之后,我們就可以利用它們來創(chuàng)建 ClipboardItem 對象,然后再調(diào)用 write 方法把這些數(shù)據(jù)寫入到剪貼板中,對應的代碼如下所示:

     
     
     
     
    1. async function writeDataToClipboard() {
    2.   if (askWritePermission()) {
    3.     if (navigator.clipboard && navigator.clipboard.write) {
    4.         const textBlob = createTextBlob("大家好,我是阿寶哥");
    5.         const imageBlob = await createImageBlob(
    6.           "http://cdn.semlinker.com/abao.png"
    7.         );
    8.         try {
    9.           const item = new ClipboardItem({
    10.             [textBlob.type]: textBlob,
    11.             [imageBlob.type]: imageBlob,
    12.           });
    13.           select(document.querySelector("#container"));
    14.           await navigator.clipboard.write([item]);
    15.           console.log("文本和圖像復制成功");
    16.         } catch (error) {
    17.           console.error("文本和圖像復制失敗", error);
    18.         }
    19.       }
    20.    }
    21. }

    在以上代碼中,使用了一個 select 方法,該方法用于實現(xiàn)選擇的效果,對應的代碼如下所示:

     
     
     
     
    1. function select(element) {
    2.   const selection = window.getSelection();
    3.   const range = document.createRange();
    4.   range.selectNodeContents(element);
    5.   selection.removeAllRanges();
    6.   selection.addRange(range);
    7. }

    通過 writeDataToClipboard 方法,我們已經(jīng)把圖像和普通文本數(shù)據(jù)寫入剪貼板了。下面我們來使用 navigator.clipboard 對象提供的 read 方法,來讀取已寫入的數(shù)據(jù)。如果你需要讀取剪貼板的數(shù)據(jù),則需要向用戶請求 clipboard-read 權(quán)限。

    5.3 請求剪貼板讀取權(quán)限

    這里我們定義了一個 askReadPermission 函數(shù)來向用戶請求剪貼板讀取權(quán)限:

     
     
     
     
    1. async function askReadPermission() {
    2.   try {
    3.     const { state } = await navigator.permissions.query({
    4.       name: "clipboard-read",
    5.     });
    6.     return state === "granted";
    7.   } catch (error) {
    8.     return false;
    9.   }
    10. }

    當調(diào)用 askReadPermission 方法后,將會向當前用戶請求剪貼板讀取權(quán)限,對應的效果如下圖所示:

    5.4 讀取剪貼板中已寫入的數(shù)據(jù)

    創(chuàng)建好 askReadPermission 函數(shù),我們就可以利用之前介紹的 navigator.clipboard.read 方法來讀取剪貼板的數(shù)據(jù)了:

     
     
     
     
    1. async function readDataFromClipboard() {
    2.   if (askReadPermission()) {
    3.     if (navigator.clipboard && navigator.clipboard.read) {
    4.       try {
    5.         const clipboardItems = await navigator.clipboard.read();
    6.         for (const clipboardItem of clipboardItems) {
    7.           console.dir(clipboardItem);
    8.           for (const type of clipboardItem.types) {
    9.             const blob = await clipboardItem.getType(type);
    10.             console.log("已讀取剪貼板中的內(nèi)容:", await blob.text());
    11.           }
    12.         }
    13.       } catch (err) {
    14.          console.error("讀取剪貼板內(nèi)容失敗: ", err);
    15.       }
    16.      }
    17.    }
    18. }

    其實,除了點擊 粘貼 按鈕之外,我們還可以通過監(jiān)聽 paste 事件來讀取剪貼板中的數(shù)據(jù)。需要注意的是,如果當前的瀏覽器不支持異步 Clipboard API,我們可以通過 clipboardData.getData 方法來讀取剪貼板中的文本數(shù)據(jù):

     
     
     
     
    1. document.addEventListener('paste', async (e) => {
    2.   e.preventDefault();
    3.   let text;
    4.   if (navigator.clipboard) {
    5.     text = await navigator.clipboard.readText();
    6.   } else {
    7.     text = e.clipboardData.getData('text/plain');
    8.   }
    9.   console.log('已獲取的文本數(shù)據(jù): ', text);
    10. });

    而對于圖像數(shù)據(jù),則可以通過以下方式進行讀取:

     
     
     
     
    1. const IMAGE_MIME_REGEX = /^image\/(p?jpeg|gif|png)$/i;
    2. document.addEventListener("paste", async (e) => {
    3.   e.preventDefault();
    4.   if (navigator.clipboard) {
    5.     let clipboardItems = await navigator.clipboard.read();
    6.     for (const clipboardItem of clipboardItems) {
    7.        for (const type of clipboardItem.types) {
    8.          if (IMAGE_MIME_REGEX.test(type)) {
    9.            const blob = await clipboardItem.getType(type);
    10.            loadImage(blob);
    11.            return;
    12.          }
    13.         }
    14.      }
    15.    } else {
    16.        const items = e.clipboardData.items;
    17.        for (let i = 0; i < items.length; i++) {
    18.          if (IMAGE_MIME_REGEX.test(items[i].type)) {
    19.          loadImage(items[i].getAsFile());
    20.          return;
    21.        }
    22.     }
    23.   }
    24. });

    以上代碼中的 loadImage 方法用于實現(xiàn)把復制的圖片插入到當前選區(qū)已選擇的區(qū)域中,對應的代碼如下:

     
     
     
     
    1. function loadImage(file) {
    2.   const reader = new FileReader();
    3.   reader.onload = function (e) {
    4.     let img = document.createElement("img");
    5.     img.src = e.target.result;
    6.     let range = window.getSelection().getRangeAt(0);
    7.     range.deleteContents();
    8.     range.insertNode(img);
    9.   };
    10.   reader.readAsDataURL(file);
    11. }

    在前面代碼中,我們監(jiān)聽了 document 對象的 paste 事件。除了該事件之外,與剪貼板相關(guān)的常見事件還有 copy 和 cut 事件。篇幅有限,阿寶哥就不繼續(xù)展開介紹了,感興趣的小伙伴可以自行閱讀相關(guān)資料。

    好的,至此本文就已經(jīng)結(jié)束了,希望閱讀完本文之后,大家對異步的 Clipboard API 會有些了解。

    六、參考資源

    • 維基百科 - 剪貼板
    • MDN - Clipboard
    • MDN - execCommand
    • Web.dev - async-clipboard

    新聞名稱:想要復制圖像?ClipboardAPI了解一下
    標題網(wǎng)址:http://m.5511xx.com/article/dhphjsi.html