当前位置: 首页 > news >正文

JavaScript系列:JS实现复制粘贴文字以及图片

文章目录

    • 一. 基于 Clipboard API 复制文字(推荐)
      • 基本概念
      • 主要方法
      • 使用限制
      • 实际应用示例
    • 二、基于 document.execCommand('copy')
      • 缺陷
      • 实际应用示例
      • 说明
    • 三、复制图片功能
    • 四、封装

一. 基于 Clipboard API 复制文字(推荐)

基本概念

Clipboard API 是一组用于在浏览器中操作剪贴板的 JavaScript API,它允许开发者在网页上读取和写入剪贴板内容,实现复制、剪切和粘贴等功能。Clipboard API 提供了一种在网页上读取和写入剪贴板内容的方式,包括文本、图像和其他类型的数据。Clipboard API 适用于需要与用户剪贴板进行交互的网页应用,如实现一键复制、粘贴功能,或者在用户复制特定内容时自动添加额外信息等。

https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard_API

主要方法

Clipboard API 提供了几个关键的方法来实现剪贴板的读写操作:

  1. navigator.clipboard.writeText(text):将给定的文本复制到剪贴板。这是一个异步方法,会返回一个 Promise 对象,成功时 Promise 会被解析,失败时会被拒绝。
  2. navigator.clipboard.readText():从剪贴板读取文本内容。这也是一个异步方法,返回一个 Promise 对象,解析后提供剪贴板中的文本内容。
  3. navigator.clipboard.write(data):写入更复杂的数据类型到剪贴板,如文件、图像等。data 参数是一个包含 ClipboardItem 对象的数组,每个 ClipboardItem 对象代表剪贴板中的一项数据。这也是一个异步方法,返回一个 Promise 对象。
  4. 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 iOSfakeElement.style.fontSize = '12pt'; // Reset box modelfakeElement.style.border = '0';fakeElement.style.padding = '0';fakeElement.style.margin = '0'; // Move element out of screen horizontallyfakeElement.style.position = 'absolute';fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position verticallyvar 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 = imageUrlimage.onload = function () {const canvas = document.createElement('canvas')canvas.width = image.widthcanvas.height = image.heightconst 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 = imageUrlconst 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 })])
}
http://www.lryc.cn/news/400645.html

相关文章:

  • 音视频入门基础:H.264专题(14)——计算视频帧率的公式
  • LeetCode-返回链表倒数第K个节点、链表的回文结构,相交链表
  • Linux 网络配置与连接
  • 5. 基于Embedding实现超越elasticsearch高级搜索
  • 探索Docker网络配置和管理
  • 【数据库】 mysql数据库管理工具 Navicat平替工具 免费开源数据库管理工具
  • 信息系统项目管理师(高项)—学习笔记二
  • 【Vue】 style中的scoped
  • maven项目容器化运行之2-maven中使用docker插件调用远程docker构建服务并在1Panel中运行
  • 电影购票小程序论文(设计)开题报告
  • IP风险画像 金融行业的安全盾牌
  • 探索老年综合评估实训室的功能与价值
  • 视频剪辑软件如何选?FCPX和PR更适合新手呢
  • 解决第三方模块ts声明文件编译错误问题
  • 数据结构小测试:排序算法
  • 电脑远程开关机
  • # Redis 入门到精通(四)-- linux 环境安装 redis
  • SQL进阶技巧:如何按照固定尺寸(固定区间)对数据进行打分类标签?
  • 数学建模·灰色关联度
  • EMQX开源版安装
  • R语言进行集成学习算法:随机森林
  • 虚拟机的状态更新
  • 基于hive数据库的泰坦尼克号幸存者数据分析
  • excel根据数据批量创建并重命名工作表
  • 智能合约和分布式应用管理系统:技术革新与未来展望
  • Spring MVC 中的拦截器的使用“拦截器基本配置” 和 “拦截器高级配置”
  • MyBatis框架学习笔记(四):动态SQL语句、映射关系和缓存
  • 【C++PythonJava】字符处理详细解读_字符_ASCLL码_字母数字转换_算法竞赛_开发语言
  • 人像视频淡入淡出效果的灵敏检验方法
  • Unity UGUI Image Maskable