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

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

新聞中心

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

在寫了 這個(gè) 29.7 K 的剪貼板 JS 庫(kù)有點(diǎn)東西! 這篇文章之后,收到了小伙伴提的兩個(gè)問題:

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

1.clipboard.js 這個(gè)庫(kù)除了復(fù)制文字之外,能復(fù)制圖像么?

2.clipboard.js 這個(gè)庫(kù)依賴的 document.execCommand API 已被廢棄了,以后應(yīng)該怎么辦?

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

接下來(lái),本文將圍繞上述兩個(gè)問題展開,不過在看第一個(gè)問題之前,我們先來(lái)簡(jiǎn)單介紹一下 剪貼板 。

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

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

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

一、clipboard.js 能否復(fù)制圖像?

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

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

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

 
 
 
 
  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 的這個(gè)特性,我們可以定義以下 HTML 結(jié)構(gòu):

  
 
 
 
  1.    
  2.    

    大家好,我是阿寶哥

  • 復(fù)制
  •  然后在實(shí)例化 ClipboardJS 對(duì)象時(shí)設(shè)置復(fù)制的目標(biāo)是 #container 元素:

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

    之后,我們點(diǎn)擊頁(yè)面中的 復(fù)制 按鈕,對(duì)應(yīng)的效果如下圖所示:

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

    這里我們通過設(shè)置 document 對(duì)象的 onpaste 屬性,來(lái)打印一下粘貼事件對(duì)應(yīng)的事件對(duì)象:

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

    當(dāng)我們點(diǎn)擊 復(fù)制 按鈕,然后在頁(yè)面執(zhí)行 粘貼 操作后,控制臺(tái)會(huì)打印出以下內(nèi)容:

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

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

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

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

    接下來(lái),我們的目標(biāo)就是實(shí)現(xiàn)復(fù)制圖像的功能了,因?yàn)橐玫?Clipboard API,所以阿寶哥先來(lái)介紹一下該 API。

    二、Clipboard API 簡(jiǎn)介

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

    在實(shí)際項(xiàng)目中,我們不需要手動(dòng)創(chuàng)建 Clipboard 對(duì)象,而是通過 navigator.clipboard來(lái)獲取 Clipboard 對(duì)象:

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

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

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

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

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

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

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

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

    3.1 writeText()

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

     
     
     
     
    1. 拷貝當(dāng)前頁(yè)面地址

    對(duì)于上述代碼,當(dāng)用戶點(diǎn)擊 拷貝當(dāng)前頁(yè)面地址 按鈕時(shí),將會(huì)把當(dāng)前的頁(yè)面地址拷貝到剪貼板中。

    3.2 write()

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

     
     
     
     
    1. 拷貝當(dāng)前頁(yè)面地址

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

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

    4.1 readText()

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

     
     
     
     
    1. 讀取剪貼板中的文本

    對(duì)于上述代碼,當(dāng)用戶點(diǎn)擊 讀取剪貼板中的文本 按鈕時(shí),如果當(dāng)前剪貼板含有文本內(nèi)容,則會(huì)讀取剪貼板中的文本內(nèi)容。

    4.2 read()

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

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

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

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

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

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

     
     
     
     
    1.    
    2.    

      大家好,我是阿寶哥

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

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

    默認(rèn)情況下,會(huì)為當(dāng)前的激活的頁(yè)面自動(dòng)授予剪貼板的寫入權(quán)限。出于安全方面考慮,這里我們還是主動(dòng)向用戶請(qǐng)求剪貼板的寫入權(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 對(duì)象提供的 write 方法。如果要寫入圖像數(shù)據(jù),我們就需要獲取該圖像對(duì)應(yīng)的 Blob 對(duì)象,這里我們可以通過 fetch API 從網(wǎng)絡(luò)上獲取圖像對(duì)應(yīng)的響應(yīng)對(duì)象并把它轉(zhuǎn)化成 Blob 對(duì)象,具體實(shí)現(xiàn)方式如下:

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

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

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

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

     
     
     
     
    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("文本和圖像復(fù)制成功");
    16.         } catch (error) {
    17.           console.error("文本和圖像復(fù)制失敗", error);
    18.         }
    19.       }
    20.    }
    21. }

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

     
     
     
     
    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ù)寫入剪貼板了。下面我們來(lái)使用 navigator.clipboard 對(duì)象提供的 read 方法,來(lái)讀取已寫入的數(shù)據(jù)。如果你需要讀取剪貼板的數(shù)據(jù),則需要向用戶請(qǐng)求 clipboard-read 權(quán)限。

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

    這里我們定義了一個(gè) askReadPermission 函數(shù)來(lái)向用戶請(qǐng)求剪貼板讀取權(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. }

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

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

    創(chuàng)建好 askReadPermission 函數(shù),我們就可以利用之前介紹的 navigator.clipboard.read 方法來(lái)讀取剪貼板的數(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. }

    其實(shí),除了點(diǎn)擊 粘貼 按鈕之外,我們還可以通過監(jiān)聽 paste 事件來(lái)讀取剪貼板中的數(shù)據(jù)。需要注意的是,如果當(dāng)前的瀏覽器不支持異步 Clipboard API,我們可以通過 clipboardData.getData 方法來(lái)讀取剪貼板中的文本數(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. });

    而對(duì)于圖像數(shù)據(jù),則可以通過以下方式進(jìn)行讀?。?/p>

     
     
     
     
    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 方法用于實(shí)現(xiàn)把復(fù)制的圖片插入到當(dāng)前選區(qū)已選擇的區(qū)域中,對(duì)應(yīng)的代碼如下:

     
     
     
     
    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 對(duì)象的 paste 事件。除了該事件之外,與剪貼板相關(guān)的常見事件還有 copy 和 cut 事件。篇幅有限,阿寶哥就不繼續(xù)展開介紹了,感興趣的小伙伴可以自行閱讀相關(guān)資料。

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

    六、參考資源

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

    本文名稱:想要復(fù)制圖像?ClipboardAPI了解一下
    本文來(lái)源:http://www.5511xx.com/article/dhphjsi.html