国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

這篇具有很好參考價(jià)值的文章主要介紹了前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1.功能需求

實(shí)習(xí)工作中,遇到一個(gè)需求,需要完成點(diǎn)擊復(fù)制的功能,當(dāng)文字過長的時(shí)候,讓用戶手拖再ctrl+c這種方式體驗(yàn)就不是很好了,如果可以點(diǎn)擊一下直接復(fù)制就是一種不錯(cuò)的優(yōu)化用戶體驗(yàn)的方式。

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

經(jīng)過查閱文檔,網(wǎng)絡(luò)上完成這個(gè)功能大多使用兩大類方法

第一種是以document.execCommand() 方法為主,無論是手寫還是使用clipboard.js插件都是依賴的這個(gè)方法,但是在MDN 文檔中已經(jīng)顯示過時(shí)了。

第二種是用了navigator.clipboard的方法,避免了過時(shí)問題,但是在復(fù)制圖片的時(shí)候會有一定的瀏覽器兼容性問題

?2.document.execCommand('copy')?

這個(gè)方法其實(shí)就是在模擬用戶選擇元素然后右鍵復(fù)制的動作。盡管MDN已經(jīng)顯示這個(gè)方法過時(shí)了,但是僅針對copy這個(gè)指令,大部分主流瀏覽器都可以支持,所以這個(gè)方法仍然可以作為一種實(shí)現(xiàn)問題的方案。

2.1 基本用法

根據(jù)MDN文檔學(xué)習(xí)本方法的傳參和返回值

語法

bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)

這個(gè)方法可以傳3個(gè)參數(shù),并且會返回一個(gè)布爾值

返回值

先從返回值開始,返回值相對比較簡單,如果返回的值是false就表示瀏覽器不支持使用這個(gè)操作,反之瀏覽器支持該操作就返回true。

雖然這個(gè)返回值看似可以用來提前判斷瀏覽器兼容性,但是文檔中不推薦在調(diào)用一個(gè)命令前,嘗試使用返回值去校驗(yàn)瀏覽器的兼容性

參數(shù)值

參數(shù)一共可以傳3個(gè),但是使用復(fù)制命令的時(shí)候只需要傳第一個(gè)參數(shù)就可以。這里簡單介紹一下3個(gè)參數(shù)

  1. aCommandName:一個(gè)字符串類型的參數(shù),是命令的名稱,比如復(fù)制用到的copy,剪切用到的cut
  2. aShowDefaultUI:一個(gè)布爾類型的參數(shù),表示是否展示用戶界面,一般為false,Mozilla 沒有實(shí)現(xiàn)
  3. aValueArgument:一些命令(例如 insertImage)需要額外的參數(shù)(insertImage 需要提供插入 image 的 url),默認(rèn)為 null。

簡單舉例

以本文主要講的復(fù)制命令為例子:document.execCommand('copy')

指令兼容性問題

前文講到,MDN不推薦在調(diào)用一個(gè)命令前,嘗試使用返回值去校驗(yàn)瀏覽器的兼容性,那么就需要用另外的方法去檢測瀏覽器是否支持某個(gè)指令,瀏覽器為我們提供了一個(gè)方法叫document.queryCommandSupported(),使用這個(gè)方法可以檢測瀏覽器是否支持某個(gè)指令,這個(gè)方法比較簡單,只有1個(gè)參數(shù),參數(shù)就傳指令字符串,方法的返回值是一個(gè)布爾值表示當(dāng)前瀏覽器是否支持這個(gè)指令。

舉例如下:

?文章來源地址http://www.zghlxwxcb.cn/news/detail-679237.html

    if(document.queryCommandSupported && document.queryCommandSupported('copy')){
        //先檢測是否支持document.queryCommandSupported和copy指令
        //如果都支持直接執(zhí)行指令
        document.execCommand('copy')
    }

?

MDN文檔中提到,document.queryCommandSupported也被棄用了,但是為了兼容性依然保留可用,當(dāng)我們使用document.execCommand的時(shí)候仍然可以用document.queryCommandSupported來檢測是否支持。同時(shí),它的瀏覽器兼容性也是比較好的,大部分主流瀏覽器都支持。

?

2.2?Selection Api

復(fù)制文本這個(gè)操作對比復(fù)制圖片是相對比較簡單的,一共包含2大步

一是選中要復(fù)制的元素

二是執(zhí)行復(fù)制指令。

執(zhí)行復(fù)制指令在前面的基本語法里已經(jīng)講到了,直接調(diào)用document.execCommand('copy')就可以了。剩下要做的便是先選中元素了。下面便介紹一下和選中元素相關(guān)的selection api

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

MDN文檔上寫道:Selection?對象表示用戶選擇的文本范圍或插入符號的當(dāng)前位置。它代表頁面中的文本選區(qū),可能橫跨多個(gè)元素。文本選區(qū)由用戶拖拽鼠標(biāo)經(jīng)過文字而產(chǎn)生。如果要獲取用于檢查或修改的?Selection?對象,可以調(diào)用?window.getSelection()?方法。

這看起來就十分的官方和抽象,簡單的來說Selection 對象所對應(yīng)的是用戶所選擇的?ranges?(區(qū)域),俗稱?拖藍(lán)。上圖中的拖藍(lán)就是selection對象中的一個(gè)區(qū)域。

通過getRangeAt方法可以獲取到具體的選中區(qū)域

    let selection = window.getSelection() //獲取selection對象
    let range = selection.getRangeAt(0)  //獲取第一個(gè)選中的區(qū)域

?除了獲取選區(qū)中的區(qū)域之外,我們還可以通過?document.createRange()創(chuàng)建一個(gè)新的區(qū)域,然后將該區(qū)域添加到選區(qū)中

<body>
    <div id="hello">你好</div>
    <div id="yes">是的</div>
</body>
<script>
    let selection = window.getSelection() //獲取selection對象
    const hello = document.querySelector('#hello')
    if(selection.rangeCount > 0){
        //如果有已經(jīng)選中的區(qū)域,直接全部去除
        selection.removeAllRanges()
    }
    let range = document.createRange() //創(chuàng)建range
    range.selectNode(hello) //range選中hello
    selection.addRange(range) //加入到選區(qū)中
</script>

?

效果如下,當(dāng)代碼執(zhí)行后,你好這個(gè)元素被直接選中

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

加入?yún)^(qū)域的api包括range.selectNode和range.selectNodeContents。其中selectNode表示選中整個(gè)節(jié)點(diǎn)而selectNodeContents表示選中節(jié)點(diǎn)中的內(nèi)容,針對文字的復(fù)制需要選中節(jié)點(diǎn)的內(nèi)容,而圖片的復(fù)制需要選中節(jié)點(diǎn)本身。

用法如下

<body>
    <div id="hello">你好</div>
    <div id="yes">是的</div>
    <button class="btn">點(diǎn)擊復(fù)制</button>
</body>
<script>
    const yes = document.querySelector('#yes')
    const selection = window.getSelection()
    const range= document.createRange()
    range.selectNode(yes)
    range.selectNode(yes)
</script>

?

?

2.3復(fù)制文字

通過以上的selection api可以完成 創(chuàng)建selection對象-->選中節(jié)點(diǎn)內(nèi)容-->添加到區(qū)域-->執(zhí)行一下copy指令就可以完成復(fù)制文字了

<body>
    <div id="hello">你好</div>
    <div id="yes">是的</div>
    <button class="btn">點(diǎn)擊復(fù)制</button>
</body>

<script>
    const btn = document.querySelector('.btn')
    const hello = document.querySelector('#hello')
    btn.addEventListener('click', () => {
        let range = document.createRange() //創(chuàng)建range
        range.selectNodeContents(hello) //range選中hello
        let selection = window.getSelection() //獲取selection對象
        if (selection.rangeCount > 0) {
            //如果有已經(jīng)選中的區(qū)域,直接全部去除
            selection.removeAllRanges()
        }
        selection.addRange(range) //加入到選區(qū)中
        if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
            //先檢測是否支持document.queryCommandSupported和copy指令
            //如果都支持直接執(zhí)行指令
            document.execCommand('copy')
            //去除選中區(qū)域,取消拖藍(lán)效果
            selection.removeAllRanges()
        }
    })
</script>

?

2.4復(fù)制圖像

復(fù)制圖像的操作是和復(fù)制文字基本相同的,只是需要在加入?yún)^(qū)域時(shí)選中整個(gè)節(jié)點(diǎn),也就是把selectNodeContents方法換成selectNode

<body>
    <div id="hello">你好</div>
    <div id="yes">是的</div>
    <img src="./test.png" alt="">
    <button class="btn">點(diǎn)擊復(fù)制</button>
</body>
<script>
    const btn = document.querySelector('.btn')
    const hello = document.querySelector('#hello')
    const img = document.querySelector('img')
    btn.addEventListener('click', () => {
        let range = document.createRange() //創(chuàng)建range
        range.selectNode(img) //range選中圖像節(jié)點(diǎn)
        let selection = window.getSelection() //獲取selection對象
        if (selection.rangeCount > 0) {
            //如果有已經(jīng)選中的區(qū)域,直接全部去除
            selection.removeAllRanges()
        }
        selection.addRange(range) //加入到選區(qū)中
        if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
            //先檢測是否支持document.queryCommandSupported和copy指令
            //如果都支持直接執(zhí)行指令
            document.execCommand('copy')
            //去除選中區(qū)域,取消拖藍(lán)效果
            selection.removeAllRanges()
        }
    })
</script>

?

3.clipboard.js

clipboard.js是一個(gè)第三方庫,也是使用了前文所講到的document.execCommand('copy')來實(shí)現(xiàn)的點(diǎn)擊復(fù)制,使用方便,但是只能用于文本的復(fù)制。

3.1安裝和引入clipboard.js

使用npm安裝

npm install clipboard --save

安裝后在html文件內(nèi)引入

<script src="dist/clipboard.min.js"></script>

或者使用CDN引入(這里只寫了一種CDN引入方式,可以選擇多種不同CDN方,具體請看https://github.com/zenorocha/clipboard.js/wiki/CDN-Providers)

<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script>

使用import的方式引入

import Clipboard from "clipboard";

3.2基本使用

初始化

直接創(chuàng)建一個(gè)ClipboardJS對象,傳的參數(shù)可以是選擇器字符串或者是DOM元素或者是DOM元素列表

new ClipboardJS('.btn') // import方式為 new Clipboard('.btn')

?

實(shí)現(xiàn)點(diǎn)擊復(fù)制文字功能

初始化完后,可以到要綁定的對應(yīng)元素下添加data-clipboard-target屬性,屬性值是要復(fù)制的元素的選擇器,這里要復(fù)制的元素是 ‘是的’ 那個(gè)div,所以屬性值就寫#yes。不進(jìn)行其他配置時(shí),我們點(diǎn)擊按鈕,觸發(fā)點(diǎn)擊事件后,就可以完成復(fù)制文字 ‘是的’ 了。

<body>
    <div id="hello" >你好</div>
    <div id="yes">是的</div>
    <button class="btn" data-clipboard-target="#yes">點(diǎn)擊復(fù)制</button>
</body>
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script>
<script>
    new ClipboardJS('.btn') // import方式為 new Clipboard('.btn')
</script>

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

?點(diǎn)擊后,是的這個(gè)元素被選中(拖藍(lán)),使用ctrl+v可以完成文字的復(fù)制,效果已經(jīng)達(dá)到。

此時(shí)有2個(gè)問題需要優(yōu)化

  1. 復(fù)制的內(nèi)容必須是頁面上的DOM元素,能不能是自己設(shè)定的?
  2. 拖藍(lán)的效果不是很好看,如何復(fù)制文字不顯示選中效果?

這時(shí)就要用到一個(gè)新的屬性data-clipboard-text,屬性值就是希望動態(tài)復(fù)制的內(nèi)容。對ClipboardJS綁定的元素設(shè)置這個(gè)屬性就可以動態(tài)復(fù)制自己設(shè)定的內(nèi)容,此時(shí)就不需要再設(shè)置data-clipboard-target屬性了(如果同時(shí)寫2個(gè)屬性,data-clipboard-text優(yōu)先)。以下代碼是一個(gè)寫死的簡單展示,真實(shí)使用的時(shí)候?qū)傩灾狄胘s設(shè)置成需要復(fù)制的值。

<body>
    <div id="hello" >你好</div>
    <div id="yes">是的</div>
    <button class="btn" data-clipboard-text="動態(tài)設(shè)置的內(nèi)容">點(diǎn)擊復(fù)制</button>
</body>
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script>
<script>
    new ClipboardJS('.btn') // import方式為 new Clipboard('.btn')
</script>

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

?上圖顯示點(diǎn)擊之后,復(fù)制內(nèi)容成功,這樣沒有選中元素的效果,不會拖藍(lán),交互效果更好的同時(shí)又能動態(tài)設(shè)置內(nèi)容

3.3更多用法

data-clipboard-action屬性

data-clipboard-action屬性可以決定執(zhí)行的操作,這個(gè)屬性有2個(gè)可選值copy或者是cut,默認(rèn)是copy也就是復(fù)制,前面的所有代碼中都沒有出現(xiàn)這個(gè)屬性,是直接使用的默認(rèn)值copy。cut剪切,只能在input和textarea標(biāo)簽中使用,顯然之前的div標(biāo)簽是無法使用的。使用方法仍是對ClipboardJS綁定的元素設(shè)置這個(gè)屬性。

<button class="btn" data-clipboard-text="動態(tài)設(shè)置的內(nèi)容" data-clipboard-action="copy">點(diǎn)擊復(fù)制</button>

事件處理

事件處理可以讓用戶設(shè)置復(fù)制或剪切成功或者失敗的回調(diào),事件名分別是success和error??梢酝ㄟ^on在ClipboardJS實(shí)例對象身上綁定success和error事件處理的回調(diào)。以下示例寫了最簡單alert打印成功和失敗

    const clipboard = new ClipboardJS('.btn') // import方式為 new Clipboard('.btn')
    clipboard.on('success',function(){
        alert('復(fù)制成功')
    })
    clipboard.on('error',function(){
        alert('復(fù)制失敗')
    })

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

純JS寫法

如果不想改HTML,加入過多的屬性,可以直接使用純JS寫法來初始化ClipboardJS對象構(gòu)造函數(shù)中傳入第二個(gè)參數(shù),第二個(gè)參數(shù)為對象,如下的示例中僅用完成js就完成了動態(tài)設(shè)置復(fù)制內(nèi)容。設(shè)置配置對象的text方法,返回值就是要復(fù)制的內(nèi)容

    new ClipboardJS('.btn',{
        text: function(){
            return '動態(tài)復(fù)制的內(nèi)容'
        }
    })

設(shè)置配置對象的target方法,返回值就是要復(fù)制的元素

    new ClipboardJS('.btn',{
        target: function (){
            return document.querySelector('#hello')
        }
    })

經(jīng)過測試,當(dāng)html中設(shè)置屬性的同時(shí),又在構(gòu)造函數(shù)里加入配置項(xiàng),以js構(gòu)造函數(shù)配置項(xiàng)為準(zhǔn)(優(yōu)先級高)

<body>
    <div id="hello">你好</div>
    <div id="yes">是的</div>
    <button class="btn" data-clipboard-target="#hello">點(diǎn)擊復(fù)制</button>
</body>
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script>
<script>
    new ClipboardJS('.btn',{
        target(){
            return document.querySelector('#yes')
        }
    })
</script>

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

銷毀對象

如果使用的是單頁應(yīng)用程序,可能希望更精確地管理DOM的生命周期??梢允褂胐estroy方法銷毀對象

var clipboard = new ClipboardJS('.btn');
clipboard.destroy();

3.4源碼分析

看了之前的api,想了解一下這個(gè)所謂的簡單的復(fù)制庫是如何實(shí)現(xiàn)的,于是打開了源碼開始分析一下

源碼地址?https://github.com/zenorocha/clipboard.js

初始化

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

構(gòu)造函數(shù)里面?zhèn)?個(gè)參數(shù),第一個(gè)trigger即觸發(fā)點(diǎn)擊的元素對象,第二個(gè)options配置項(xiàng)。從最簡單的例子來看,只需要傳一個(gè)trigger參數(shù)就可以實(shí)現(xiàn)功能,那就先不管options,直接看與trigger有關(guān)的listenClick方法。

listenClick方法調(diào)用了一個(gè)第三方庫的listen方法綁定了click事件和對應(yīng)的回調(diào)函數(shù)this.onClick,在onclick方法中,調(diào)用了ClipboardActionDefault方法,并且傳了對應(yīng)的幾個(gè)配置項(xiàng)參數(shù),action container,target,text,這些值都是this.xxx方法,這幾個(gè)方法又是在哪定義的呢?

?

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

找了一下類內(nèi)部,定義這些方法的地方是在前文構(gòu)造函數(shù)里的this.resolveOptions方法里

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

resolveOptions方法里的defaultAction,defaultText等等方法都是類似的,都是調(diào)用了一個(gè)getAttributeValue方法去獲取html模板上的屬性值

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

getAttributeValue方法如下,比較簡單?

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

ClipboardActionDefault

上面跳了這么多方法雖然不難,但是也有點(diǎn)繞,主要還是在干一件事,那就是通過定義來準(zhǔn)備好ClipboardActionDefault這個(gè)方法的參數(shù)。這時(shí)候就要看一下ClipboardActionDefault這個(gè)方法在干什么。

簡單來看,這個(gè)方法主要分4個(gè)if判斷,前2個(gè)if就是一些條件的判斷,判斷action只能是復(fù)制或者剪切,還有就是判斷要復(fù)制的目標(biāo)節(jié)點(diǎn)的節(jié)點(diǎn)類型和readonly問題等等,此處不展開去研究,有興趣者可以點(diǎn)擊本部分開始處的源碼鏈接下載。

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

后2個(gè)if判斷中的內(nèi)容如下,分別用于判斷是否有text值和target值,這2個(gè)值也是通過本庫的核心屬性data-clipboard-text和data-clipboard-target在html中獲取的(或者在js配置項(xiàng)里獲?。?。判斷完后就調(diào)用了ClipboardActionCopy或者ClipboardActionCut方法去實(shí)現(xiàn)復(fù)制或者剪切功能。

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

ClipboardActionCopy

這個(gè)方法就開始進(jìn)行文本的復(fù)制了,首先判斷要復(fù)制的目標(biāo)是普通的字符串(通過data-clipboard-text設(shè)置)還是節(jié)點(diǎn)(通過data-clipboard-target設(shè)置),如果是文本或者不是普通的輸入元素,直接調(diào)用fakeCopyAction方法執(zhí)行復(fù)制操作。

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

?

?fakeCopyAction先創(chuàng)建了虛擬元素,然后把這個(gè)元素插入dom里,最后執(zhí)行選中+復(fù)制操作

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

創(chuàng)建虛擬元素的方法也比較簡單,先通過原生方法createElement創(chuàng)建了一個(gè)textarea元素,然后把它隱藏。創(chuàng)建這種輸入類元素的好處就是可以直接去修改它的value,最后一步操作就是把文本text賦值給textarea

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

?創(chuàng)建完虛擬元素就要處理選中問題了,這里調(diào)用了select方法,方法內(nèi)部根據(jù)3種元素類型設(shè)置了不同的處理對策,select元素只要focus后賦值就好。輸入元素可以調(diào)用原生的select方法來選中元素,而普通元素就需要使用之前講到的selection api去獲取range和添加range了

function select(element) {
    var selectedText;

    if (element.nodeName === 'SELECT') {
        //針對select元素的處理
        element.focus();

        selectedText = element.value;
    }
    else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
        //選中輸入元素
        var isReadOnly = element.hasAttribute('readonly');

        if (!isReadOnly) {
            element.setAttribute('readonly', '');
        }

        element.select();
        element.setSelectionRange(0, element.value.length);

        if (!isReadOnly) {
            element.removeAttribute('readonly');
        }

        selectedText = element.value;
    }
    else {
        //普通元素選中
        if (element.hasAttribute('contenteditable')) {
            element.focus();
        }

        var selection = window.getSelection();
        var range = document.createRange();

        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);

        selectedText = selection.toString();
    }

    return selectedText;
}

最后的command('copy')也就是對執(zhí)行復(fù)制指令這個(gè)方法的簡單封裝,做了一下兼容性的處理。

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

4.?navigator.clipboard

前面的document.execCommand和第三方庫clipboard.js都非常的好用,但是他們可能面臨被棄用的風(fēng)險(xiǎn),那么該怎么解決復(fù)制粘貼這個(gè)問題呢??H5新推出的clipboard api是 處理復(fù)制粘貼相關(guān)的api,可以很好的解決這個(gè)問題。用promise的方式把數(shù)據(jù)寫入剪貼板,避免了頁面的卡頓。

4.1 復(fù)制文字

Clipboard對象

使用Clipboard api時(shí)我們不需要手動創(chuàng)建Clipboard對象,而是通過navigator.clipboard來獲取

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

打印出Clipboard對象后可以看出,這個(gè)對象有4個(gè)方法,分為兩大類,write和read類。其中與復(fù)制相關(guān)的是write類表示把數(shù)據(jù)寫入剪貼板,和粘貼相關(guān)的是read類表示從剪貼板里面讀取數(shù)據(jù)

?writeText方法

Clipboard對象中的writeText方法可以用于復(fù)制文字,也是非常簡單易用的一個(gè)方法。

參數(shù):傳一個(gè)字符串參數(shù),即要復(fù)制的內(nèi)容

返回值: 一個(gè)promise對象,如果成功復(fù)制則是成功的promise,如果寫入剪貼板失敗(復(fù)制失?。﹦t是失敗的promise

示例如下:先創(chuàng)建了一個(gè)clipboard對象,然后直接調(diào)用writeText方法復(fù)制文字123

navigator.clipboard.writeText('123')

根據(jù)之前的html結(jié)構(gòu),使用Clipboard api完成文字的復(fù)制

默認(rèn)情況下,會為當(dāng)前的激活的頁面自動授予剪貼板的寫入權(quán)限。出于安全方面考慮,這里我們還是先主動向用戶請求剪貼板的寫入權(quán)限,如果被授權(quán),就可以調(diào)用上面的方法直接完成復(fù)制了。

<body>
    <div id="hello">你好</div>
    <div id="yes">是的</div>
    <img src="./test.png" alt="">
    <button class="btn">點(diǎn)擊復(fù)制</button>
</body>
<script>
    const btn = document.querySelector('.btn')
    const hello = document.querySelector('#hello')
    const img = document.querySelector('img')
    btn.addEventListener('click', async () => {
        const { state } = await navigator.permissions.query({
            // 出于安全方面考慮,這里我們還是主動向用戶請求剪貼板的寫入權(quán)限
            name: "clipboard-write",
        });
        if (state == 'granted') {
            navigator.clipboard.writeText(hello.innerHTML)
        }
    })
</script>

?

4.2 復(fù)制圖像

write方法

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

以下是簡單的使用案例,先通過 Blob API 創(chuàng)建 Blob 對象,然后使用該 Blob 對象來構(gòu)造 ClipboardItem 對象,最后再通過 write 方法把數(shù)據(jù)寫入到剪貼板,復(fù)制了文字(當(dāng)前頁面的地址)

<button onclick="copyPageUrl()">拷貝當(dāng)前頁面地址</button>
<script>
   async function copyPageUrl() {
     const text = new Blob([location.href], {type: 'text/plain'});
     try {
       await navigator.clipboard.write(
         new ClipboardItem({
           "text/plain": text,
         }),
       );
       console.log("頁面地址已經(jīng)被拷貝到剪貼板中");
     } catch (err) {
       console.error("頁面地址拷貝失敗: ", err);
     }
  }
</script>

復(fù)制圖片案例

了解了write的基本用法,那使用Clipboard對象復(fù)制圖片也有辦法了,只要先把圖像變成Blob對象,然后構(gòu)造?ClipboardItem 對象,最后再調(diào)用write方法就好。

可是,如何把一個(gè)img標(biāo)簽里的圖片轉(zhuǎn)換成Blob對象呢?

首先從Blob對象的構(gòu)造函數(shù)開始,MDN文檔寫了Blob構(gòu)造函數(shù)所需要的參數(shù)

var aBlob = new Blob( array, options );

array 是一個(gè)由ArrayBuffer, ArrayBufferView, Blob, DOMString 等對象構(gòu)成的 Array ,或者其他類似對象的混合體,它將會被放進(jìn) Blob。DOMStrings 會被編碼為 UTF-8。
options 是一個(gè)可選的BlobPropertyBag字典,它可能會指定如下兩個(gè)屬性:

  1. type,默認(rèn)值為 "",它代表了將會被放入到 blob 中的數(shù)組內(nèi)容的 MIME 類型。
  2. endings,默認(rèn)值為"transparent",用于指定包含行結(jié)束符\n的字符串如何被寫入。它是以下兩個(gè)值中的一個(gè):"native",代表行結(jié)束符會被更改為適合宿主操作系統(tǒng)文件系統(tǒng)的換行符,或者 "transparent",代表會保持 blob 中保存的結(jié)束符不變

?

根據(jù)文檔中顯示,我們需要先準(zhǔn)備一個(gè)對應(yīng)的數(shù)組,然后才能構(gòu)造Blob對象,也就是要把圖片轉(zhuǎn)成二進(jìn)制數(shù)據(jù)。

分步驟實(shí)現(xiàn)把圖片轉(zhuǎn)換成Blob

  1. 把img圖像畫在canvas畫布上
  2. 調(diào)用canvas的toDataURL方法,獲取圖片的base64編碼
  3. 調(diào)用atob方法,把base64編碼的數(shù)據(jù)轉(zhuǎn)換成二進(jìn)制數(shù)據(jù)
  4. 根據(jù)轉(zhuǎn)換后的二進(jìn)制數(shù)據(jù),創(chuàng)建一個(gè)視圖,此視圖將把緩沖內(nèi)的數(shù)據(jù)格式化為一個(gè) 8 位無符號整數(shù)數(shù)組,也就是獲得了一個(gè)ArrayBufferView數(shù)組(關(guān)于ArrayBuffer和ArrayBufferView的內(nèi)容詳細(xì)可查閱?JavaScript 類型化數(shù)組)

?

下方代碼完成了基本的功能實(shí)現(xiàn):

?

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!

?微信輸入框顯示,可以完成復(fù)制

這個(gè)方法在瀏覽器兼容性上仍存在一些問題,比如火狐可能就不支持ClipboardItem對象,此時(shí)只能用前文寫的document.execCommand方法了。

<body>
    <div id="hello">你好</div>
    <div id="yes">是的</div>
    <img style="width: 400px; height: 200px" src="./test.png" alt="">
    <button class="btn">點(diǎn)擊復(fù)制</button>
</body>
<script>
    const btn = document.querySelector('.btn')
    const hello = document.querySelector('#hello')
    const img = document.querySelector('img')
    btn.addEventListener('click', async () => {
        const {
            state
        } = await navigator.permissions.query({
            // 出于安全方面考慮,這里我們還是主動向用戶請求剪貼板的寫入權(quán)限
            name: "clipboard-write",
        });
        if (state == 'granted') {
            //創(chuàng)建canvas對象
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            const image = new Image()
            image.src = img.src
            image.onload = async () => {
                canvas.width = image.width;
                canvas.height = image.height;
                context.drawImage(image, 0, 0, image.width, image.height); // img圖片轉(zhuǎn)成canvas
                const imageDataUrl = canvas.toDataURL() //通過canvas獲取base64編碼
                const binary = atob(imageDataUrl.split(',')[1]); // base64編碼轉(zhuǎn)二進(jìn)制數(shù)據(jù)
                const array = [];
                for (let i = 0; i < binary.length; i++) {
                    array.push(binary.charCodeAt(i));
                }
                //二進(jìn)制數(shù)據(jù)轉(zhuǎn)Blob對象
                const blob = new Blob([new Uint8Array(array)], {
                    type: 'image/png'
                });
                // 判斷瀏覽器是否有ClipboardItem對象,有些瀏覽器不支持本方法
                if (typeof ClipboardItem !== 'undefined') {
                    //把blob數(shù)據(jù)寫入剪貼板
                    await navigator.clipboard.write([
                        new ClipboardItem({
                            [blob.type]: blob
                        })
                    ])
                }
            }
        }
    })
</script>

?

?

到了這里,關(guān)于前端實(shí)現(xiàn)復(fù)制文字和圖片,原來這么簡單!的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • AI制作口播視頻,原來這么簡單

    AI制作口播視頻,原來這么簡單

    ??大家好,我是可夫小子,《小白玩轉(zhuǎn)ChatGPT》專欄作者,關(guān)注AIGC、讀書和自媒體。 在前面的文章中,我們介紹了生成自己專屬卡通形象照,這張照片不僅能作頭像,還可以讓照片說話,作為我們的數(shù)字人,能進(jìn)行口播短視頻制作。做自媒體的都知道,一旦跑通了幾個(gè)流程,

    2024年02月10日
    瀏覽(36)
  • vue 實(shí)現(xiàn)一鍵復(fù)制功能(復(fù)制圖片和文字)

    前言 一鍵復(fù)制這個(gè)功能也是經(jīng)常使用到的,實(shí)現(xiàn)起來并沒有那么復(fù)雜,原生就可以實(shí)現(xiàn)。 原理就是找到這個(gè)Dom元素把這個(gè)元素里面的文字和圖片直接復(fù)制下來。 細(xì)節(jié)復(fù)制方法的時(shí)候可能會出現(xiàn)斜桿(不是不生效不用管),圖片大小會維持原來的圖片大小。 注意在頁面scss寫

    2024年02月15日
    瀏覽(21)
  • 央視的《AI我中華》宣傳視頻,原來這么簡單?

    央視的《AI我中華》宣傳視頻,原來這么簡單?

    前段時(shí)間,央視的《愛我中華》AI宣傳短片火爆全網(wǎng),有一個(gè)穿越轉(zhuǎn)場效果非常驚艷! 今天就先來詳細(xì)講解,如何利用Stable Diffusion制作這樣的穿越轉(zhuǎn)場視頻。 用到的擴(kuò)展插件就是大名鼎鼎的Deforum,其實(shí)很早以前很火的“瞬息全宇宙”視頻也是用它來完成的。 需要AI繪畫素材

    2024年04月26日
    瀏覽(26)
  • 原來Vinted注冊這么簡單!Vinted注冊保姆級教程分享

    原來Vinted注冊這么簡單!Vinted注冊保姆級教程分享

    如果是日本的二手平臺代表是煤爐,美國是PoshMark,那歐洲呼聲最高的就是Vinted了,今天東哥就給大家科普一下Vinted這個(gè)平臺,教大家怎么去成功注冊Vinted,開啟自己的Vinted跨境電商之旅。 Vinted跟煤爐、某魚差不多性質(zhì),是一個(gè)二手服裝商品和配飾的平臺,支持在?iOS、Andr

    2024年02月09日
    瀏覽(17)
  • python輕量級web框架flask初探,搭建網(wǎng)站原來這么簡單

    python輕量級web框架flask初探,搭建網(wǎng)站原來這么簡單

    ?? 歡迎大家來到景天科技苑?? ???? 養(yǎng)成好習(xí)慣,先贊后看哦~???? ?? 作者簡介:景天科技苑 ??《頭銜》:大廠架構(gòu)師,華為云開發(fā)者社區(qū)專家博主,阿里云開發(fā)者社區(qū)專家博主,CSDN新星創(chuàng)作者,掘金優(yōu)秀博主,51CTO博客專家等。 ??《博客》:Python全棧,前后端開

    2024年03月19日
    瀏覽(575)
  • 【SpringBoot】集成SpringSecurity+JWT實(shí)現(xiàn)多服務(wù)單點(diǎn)登錄,原來這么easy

    【SpringBoot】集成SpringSecurity+JWT實(shí)現(xiàn)多服務(wù)單點(diǎn)登錄,原來這么easy

    Spring Boot+Spring Security+JWT實(shí)現(xiàn)單點(diǎn)登錄 介紹: 單點(diǎn)登錄(SingleSignOn,SSO) ,當(dāng)用戶在身份 認(rèn)證服務(wù)器 上登錄一次以后,即可 獲得訪問單點(diǎn)登錄系統(tǒng)中其他關(guān)聯(lián)系統(tǒng)和應(yīng)用軟件的權(quán)限 ,同時(shí)這種實(shí)現(xiàn)是不需要管理員對用戶的登錄狀態(tài)或其他信息進(jìn)行修改的,這意味著在多個(gè)應(yīng)用

    2024年02月02日
    瀏覽(26)
  • 物聯(lián)網(wǎng)網(wǎng)關(guān),原來是這么回事,感謝!

    物聯(lián)網(wǎng)網(wǎng)關(guān),原來是這么回事,感謝!

    《高并發(fā)系統(tǒng)實(shí)戰(zhàn)派》-- 你值得擁有 物聯(lián)網(wǎng)網(wǎng)關(guān)是連接物聯(lián)網(wǎng)設(shè)備和互聯(lián)網(wǎng)的重要橋梁,它負(fù)責(zé)將物聯(lián)網(wǎng)設(shè)備采集到的數(shù)據(jù)進(jìn)行處理、存儲和轉(zhuǎn)發(fā),使其能夠與云端或其他設(shè)備進(jìn)行通信。物聯(lián)網(wǎng)網(wǎng)關(guān)的作用是實(shí)現(xiàn)物聯(lián)網(wǎng)設(shè)備與云端的無縫連接和數(shù)據(jù)交換。 不要物聯(lián)網(wǎng)網(wǎng)關(guān)行

    2024年02月08日
    瀏覽(18)
  • 原來服務(wù)器這么有用-Docker安裝

    原來服務(wù)器這么有用-Docker安裝

    在此之前青陽通過各種方式介紹過自己通過服務(wù)器搭建的一些玩法,也寫過一些教程,但是那些教程,現(xiàn)在回頭來看,都是有些雜亂了,統(tǒng)一性不強(qiáng)。我就準(zhǔn)備重新整理一下之前寫的文章,并且準(zhǔn)備重新開一個(gè)專題來寫自己折騰的內(nèi)容,專題的名字就叫-原來服務(wù)器這么有用。

    2024年02月04日
    瀏覽(19)
  • 原來.NET寫的Linux桌面這么好看?

    本文將講解如何使用 Blazor 運(yùn)行跨平臺應(yīng)用,應(yīng)用到的技術(shù)有以下幾點(diǎn) Blazor Masa Blazor Photino.Blazor Ubuntu 用于驗(yàn)證跨平臺性,并且是否提高開發(fā)效率,Blazor和Photino一塊使用的技術(shù)稱為 Blazor Hybrid , Blazor是一種使用.NET和C#構(gòu)建客戶端Web應(yīng)用程序的新興技術(shù)。它允許開發(fā)者在瀏覽器

    2024年02月05日
    瀏覽(20)
  • Python制作進(jìn)度條,原來有這么多方法

    Python制作進(jìn)度條,原來有這么多方法

    如果你之前沒用過進(jìn)度條,八成是覺得它會增加不必要的復(fù)雜性或者很難維護(hù),其實(shí)不然。要加一個(gè)進(jìn)度條其實(shí)只需要幾行代碼。 在這幾行代碼中,我們可以看看如何在命令行腳本以及 PySimpleGUI UI 中添加進(jìn)度條。 下文將介紹 4 個(gè)常用的 Python 進(jìn)度條庫: 第一個(gè)要介紹的 Py

    2024年02月08日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包