JS实现复制粘贴文字及图片功能
作者:Code技术分享
Clipboard API 是一组用于在浏览器中操作剪贴板的 JavaScript API,它允许开发者在网页上读取和写入剪贴板内容,实现复制、剪切和粘贴等功能,这篇文章主要介绍了JS实现复制粘贴文字及图片功能,需要的朋友可以参考下
一. 基于 Clipboard API 复制文字(推荐)
基本概念
Clipboard API 是一组用于在浏览器中操作剪贴板的 JavaScript API,它允许开发者在网页上读取和写入剪贴板内容,实现复制、剪切和粘贴等功能。Clipboard API 提供了一种在网页上读取和写入剪贴板内容的方式,包括文本、图像和其他类型的数据。Clipboard API 适用于需要与用户剪贴板进行交互的网页应用,如实现一键复制、粘贴功能,或者在用户复制特定内容时自动添加额外信息等。
https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard_API
主要方法
Clipboard API 提供了几个关键的方法来实现剪贴板的读写操作:
- navigator.clipboard.writeText(text):将给定的文本复制到剪贴板。这是一个异步方法,会返回一个 Promise 对象,成功时 Promise 会被解析,失败时会被拒绝。
- navigator.clipboard.readText():从剪贴板读取文本内容。这也是一个异步方法,返回一个 Promise 对象,解析后提供剪贴板中的文本内容。
- navigator.clipboard.write(data):写入更复杂的数据类型到剪贴板,如文件、图像等。data 参数是一个包含 ClipboardItem 对象的数组,每个 ClipboardItem 对象代表剪贴板中的一项数据。这也是一个异步方法,返回一个 Promise 对象。
- navigator.clipboard.read():从剪贴板读取更复杂的数据类型,如文件、图像等。这个方法会返回一个 Promise 对象,解析后提供一个包含 ClipboardItem 对象的数组。
使用限制
- 用户授权:由于安全和隐私的考虑,浏览器在使用 Clipboard API 时通常需要用户授权。例如,在尝试从剪贴板读取或写入数据时,浏览器可能会要求用户明确允许。
- 安全上下文:Clipboard API 只能在安全的环境中操作剪贴板,如 HTTPS 页面、localhost本机下。
- 浏览器兼容性:虽然大多数现代浏览器都支持 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')
是一个在网页上执行复制操作的旧式API,属于 Web API 的一部分,用于在不需要用户交互(如点击或按键)的情况下,通过脚本复制文本到剪贴板。然而,这个API在现代Web开发中已经被视为过时(deprecated),并在许多现代浏览器中受到限制或不再支持,尤其是在没有用户明确交互的情况下。
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
缺陷
- 只能操作input, textarea或具有contenteditable属性的元素
execCommand
是同步操作,如果复制/粘贴大量数据,可能会导致页面出现卡顿现象,影响用户体验。- 它只能将选中的内容复制到剪贴板,无法向剪贴板任意写入内容
- 有些浏览器还会跳出提示框,要求用户许可,这时在用户做出选择前,页面会失去响应。
实际应用示例
<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 = () => { // 动态创建 textarea 标签 const textarea = document.createElement('textarea') // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域 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
去实现的
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 } // 动态创建 textarea 标签 const textarea = document.createElement('textarea') // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域 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实现复制粘贴文字以及图片的文章就介绍到这了,更多相关js复制粘贴文字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!