JS實現(xiàn)復制粘貼文字及圖片功能
一. 基于 Clipboard API 復制文字(推薦)
基本概念
Clipboard API 是一組用于在瀏覽器中操作剪貼板的 JavaScript API,它允許開發(fā)者在網頁上讀取和寫入剪貼板內容,實現(xiàn)復制、剪切和粘貼等功能。Clipboard API 提供了一種在網頁上讀取和寫入剪貼板內容的方式,包括文本、圖像和其他類型的數(shù)據(jù)。Clipboard API 適用于需要與用戶剪貼板進行交互的網頁應用,如實現(xiàn)一鍵復制、粘貼功能,或者在用戶復制特定內容時自動添加額外信息等。
https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard_API
主要方法
Clipboard API 提供了幾個關鍵的方法來實現(xiàn)剪貼板的讀寫操作:
- navigator.clipboard.writeText(text):將給定的文本復制到剪貼板。這是一個異步方法,會返回一個 Promise 對象,成功時 Promise 會被解析,失敗時會被拒絕。
- navigator.clipboard.readText():從剪貼板讀取文本內容。這也是一個異步方法,返回一個 Promise 對象,解析后提供剪貼板中的文本內容。
- navigator.clipboard.write(data):寫入更復雜的數(shù)據(jù)類型到剪貼板,如文件、圖像等。data 參數(shù)是一個包含 ClipboardItem 對象的數(shù)組,每個 ClipboardItem 對象代表剪貼板中的一項數(shù)據(jù)。這也是一個異步方法,返回一個 Promise 對象。
- navigator.clipboard.read():從剪貼板讀取更復雜的數(shù)據(jù)類型,如文件、圖像等。這個方法會返回一個 Promise 對象,解析后提供一個包含 ClipboardItem 對象的數(shù)組。
使用限制
- 用戶授權:由于安全和隱私的考慮,瀏覽器在使用 Clipboard API 時通常需要用戶授權。例如,在嘗試從剪貼板讀取或寫入數(shù)據(jù)時,瀏覽器可能會要求用戶明確允許。
- 安全上下文:Clipboard API 只能在安全的環(huán)境中操作剪貼板,如 HTTPS 頁面、localhost本機下。
- 瀏覽器兼容性:雖然大多數(shù)現(xiàn)代瀏覽器都支持 Clipboard API,但仍有部分舊版瀏覽器可能不支持。因此,在使用時需要考慮瀏覽器的兼容性。
實際應用示例
<template> <el-button type="primary" @click="handleCopy">復制文本</el-button> <div>{{ message }}</div> </template> <script setup> import { ref } from 'vue' import { ElMessage } from 'element-plus' const message = ref('復制的內容') const handleCopy = () => { navigator.clipboard .writeText(message.value) .then(() => { ElMessage({ message: '復制成功', type: 'success', }) }) .catch((err) => { console.error('復制失敗:', err) ElMessage({ message: '復制失敗', type: 'error', }) }) } </script>
二、基于 document.execCommand('copy')
document.execCommand('copy')
是一個在網頁上執(zhí)行復制操作的舊式API,屬于 Web API 的一部分,用于在不需要用戶交互(如點擊或按鍵)的情況下,通過腳本復制文本到剪貼板。然而,這個API在現(xiàn)代Web開發(fā)中已經被視為過時(deprecated),并在許多現(xiàn)代瀏覽器中受到限制或不再支持,尤其是在沒有用戶明確交互的情況下。
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
缺陷
- 只能操作input, textarea或具有contenteditable屬性的元素
execCommand
是同步操作,如果復制/粘貼大量數(shù)據(jù),可能會導致頁面出現(xiàn)卡頓現(xiàn)象,影響用戶體驗。- 它只能將選中的內容復制到剪貼板,無法向剪貼板任意寫入內容
- 有些瀏覽器還會跳出提示框,要求用戶許可,這時在用戶做出選擇前,頁面會失去響應。
實際應用示例
<template> <el-button type="primary" @click="handleCopy2">復制文本2</el-button> <div>{{ message }}</div> </template> <script setup> import { copyText, copyImage, imageUrlToBase64, parseBase64, } from './common/copy' import { ref } from 'vue' import { ElMessage } from 'element-plus' const message = ref('復制的內容') const handleCopy2 = () => { // 動態(tài)創(chuàng)建 textarea 標簽 const textarea = document.createElement('textarea') // 將該 textarea 設為 readonly 防止 iOS 下自動喚起鍵盤,同時將 textarea 移出可視區(qū)域 textarea.readOnly = 'readonly' textarea.style.position = 'absolute' textarea.style.left = '-9999px' textarea.style.opacity = '0' // 將要 copy 的值賦給 textarea 標簽的 value 屬性 textarea.value = message.value // 將 textarea 插入到 body 中 document.body.appendChild(textarea) // 選中值并復制 textarea.select() const result = document.execCommand('Copy') if (result) { ElMessage({ message: '復制成功', type: 'success', }) } document.body.removeChild(textarea) } </script>
說明
clipboard.js
底層也是基于 document.execCommand
去實現(xiàn)的
function createFakeElement(value) { var isRTL = document.documentElement.getAttribute('dir') === 'rtl'; var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS fakeElement.style.fontSize = '12pt'; // Reset box model fakeElement.style.border = '0'; fakeElement.style.padding = '0'; fakeElement.style.margin = '0'; // Move element out of screen horizontally fakeElement.style.position = 'absolute'; fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically var yPosition = window.pageYOffset || document.documentElement.scrollTop; fakeElement.style.top = "".concat(yPosition, "px"); fakeElement.setAttribute('readonly', ''); fakeElement.value = value; return fakeElement; } var fakeCopyAction = function fakeCopyAction(value, options) { var fakeElement = createFakeElement(value); options.container.appendChild(fakeElement); var selectedText = select_default()(fakeElement); command('copy'); fakeElement.remove(); return selectedText; };
三、復制圖片功能
<template> <el-button type="primary" @click="handleCopyImage">復制圖片</el-button> <div>{{ message }}</div> </template> <script setup> import { ref } from 'vue' import { ElMessage } from 'element-plus' const message = ref('復制的內容') const handleCopyImage = async () => { //具體看下面的封裝 await copyImage('https://cn.vitejs.dev/logo-with-shadow.png') ElMessage({ message: '復制成功', type: 'success', }) } </script>
四、封裝
/** * 圖片轉base64 * @param {string} 圖片地址 * @returns */ export const imageUrlToBase64 = (imageUrl) => { return new Promise((resolve, reject) => { let image = new Image() image.setAttribute('crossOrigin', 'Anonymous') image.src = imageUrl image.onload = function () { const canvas = document.createElement('canvas') canvas.width = image.width canvas.height = image.height const context = canvas.getContext('2d') context.drawImage(image, 0, 0, image.width, image.height) const base64Str = canvas.toDataURL('image/png') resolve(base64Str) } image.onerror = function (e) { reject(e) } }) } /** * 轉換base64 * @param {string} base64 * @returns */ export function parseBase64(base64) { let re = new RegExp('data:(?<type>.*?);base64,(?<data>.*)') let res = re.exec(base64) if (res) { return { type: res.groups.type, ext: res.groups.type.split('/').slice(-1)[0], data: res.groups.data, } } } /** * 復制文字 * @param {string} text 要復制的文本 * @returns {boolean} true/false */ export const copyText = async (text) => { if (navigator && navigator.clipboard) { await navigator.clipboard.writeText(text) return true } // 動態(tài)創(chuàng)建 textarea 標簽 const textarea = document.createElement('textarea') // 將該 textarea 設為 readonly 防止 iOS 下自動喚起鍵盤,同時將 textarea 移出可視區(qū)域 textarea.readOnly = 'readonly' textarea.style.position = 'absolute' textarea.style.left = '-9999px' textarea.style.opacity = '0' // 將要 copy 的值賦給 textarea 標簽的 value 屬性 textarea.value = text // 將 textarea 插入到 body 中 document.body.appendChild(textarea) // 選中值并復制 textarea.select() const result = document.execCommand('Copy') document.body.removeChild(textarea) return result } /** * 復制圖片 * @param {string} imageUrl 圖片地址 * @param {boolean} isBase64 是否是base64 */ export const copyImage = async (imageUrl, isBase64 = false) => { let base64Url = '' if (!isBase64) { base64Url = await imageUrlToBase64(imageUrl) } else base64Url = imageUrl const parsedBase64 = parseBase64(base64Url) let type = parsedBase64.type //將base64轉為Blob類型 let bytes = atob(parsedBase64.data) let ab = new ArrayBuffer(bytes.length) let ua = new Uint8Array(ab) for (let i = 0; i < bytes.length; i++) { ua[i] = bytes.charCodeAt(i) } let blob = new Blob([ab], { type }) navigator.clipboard.write([new ClipboardItem({ [type]: blob })]) }
到此這篇關于JS實現(xiàn)復制粘貼文字以及圖片的文章就介紹到這了,更多相關js復制粘貼文字內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JS中showModalDialog關閉子窗口刷新主窗口用法詳解
這篇文章主要介紹了JS中showModalDialog關閉子窗口刷新主窗口用法,結合具體實例形式較為詳細的分析了showModalDialog常見用法與相關使用技巧,需要的朋友可以參考下2017-03-03javascript 制作坦克大戰(zhàn)游戲初步 圖片與代碼
javascript 制作坦克大戰(zhàn)游戲初步 圖片與代碼...2007-11-11詳解webpack-dev-server使用http-proxy解決跨域問題
這篇文章主要介紹了詳解webpack-dev-server使用http-proxy解決跨域問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01Javascript實現(xiàn)的常用算法(如冒泡、快速、鴿巢、奇偶等)
這篇文章主要介紹了Javascript實現(xiàn)的常用算法,如冒泡、快速、鴿巢、選擇、木桶、奇偶等,需要的朋友可以參考下2014-04-04JavaScript實現(xiàn)中文數(shù)字轉為阿拉伯數(shù)字的方法
在JavaScript編程中,實現(xiàn)阿拉伯數(shù)字和中文數(shù)字之間的互相轉換是一個常見的需求,這涉及到字符串處理和數(shù)值計算,本文將詳細介紹如何利用JavaScript實現(xiàn)這一功能,需要的朋友可以參考下2025-03-03Three.js實現(xiàn)3D乒乓球小游戲(物理效果)
本文將使用React Three Fiber 和 Cannon.js 來實現(xiàn)一個具有物理特性的乒乓球小游戲,使用 React Three Fiber 搭建基礎三維場景、如何使用新技術棧給場景中對象的添加物理特性等,最后利用上述知識點,將開發(fā)一個簡單的乒乓球小游戲,需要的朋友可以參考下2023-03-03