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 提供了几个关键的方法来实现剪贴板的读写操作:
- 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 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 })])
}
相关文章:
JavaScript系列:JS实现复制粘贴文字以及图片
文章目录 一. 基于 Clipboard API 复制文字(推荐)基本概念主要方法使用限制实际应用示例 二、基于 document.execCommand(copy)缺陷实际应用示例说明 三、复制图片功能四、封装 一. 基于 Clipboard API 复制文字(推荐) 基本概念 …...

音视频入门基础:H.264专题(14)——计算视频帧率的公式
一、引言 通过FFmpeg命令可以获取到H.264裸流文件的视频帧率: 在vlc中也可以获取到视频帧率(vlc底层也使用了FFmpeg进行解码): 所以FFmpeg和vlc是怎样获取到H.264编码的视频的帧率呢?它们其实是通过SPS中的VUI parame…...

LeetCode-返回链表倒数第K个节点、链表的回文结构,相交链表
一、返回链表倒数第k个节点 . - 力扣(LeetCode) 本体思路参展寻找中间节点的方法,寻找中间节点是定义快慢指针,快指针每次走两步,慢指针每次走一步,当快指针为空或者快指针的下一个节点是空时,…...

Linux 网络配置与连接
一、网络配置 1.1 ifconfig 网卡配置查询 ifconfig #查看所有启动的网络接口信息 ifconfig 指定的网卡 #查看指定网络接口信息 1.2 修改网络配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33 #ens33网络配置文…...
5. 基于Embedding实现超越elasticsearch高级搜索
Embedding介绍 Embedding是向量的意思,向量可以理解为平面坐标中的一个坐标点(x,y),在编程领域,一个二维向量就是一个大小为float类型的数组。也可以用三维坐标系中的向量表示一个空间中的点。在机器学习中,向量通常用于表示数据的特征。 向量…...

探索Docker网络配置和管理
目录 1.docker网络类型有几种? 2.自定义网络管理 1.查看网络信息 2.查看网络的详细信息 3.创建四种网络容器 3.none类型 1.验证 4.host类型 1.验证 5. bridge类型 1.验证 2.设备对 6. container类型 1.验证 2.详解 7.科普下docker的网络名称空间 “…...

【数据库】 mysql数据库管理工具 Navicat平替工具 免费开源数据库管理工具
一、数据库分享 本次分享针对mysql的数据库管理工具 全部为开源免费工具 1、beekeeper-studio 可以从github或者官方下载 1.1、官方网址 官方地址:https://www.beekeeperstudio.io/ 1.2、Github 网址 Github地址:https://github.com/beekeeper-studio…...

信息系统项目管理师(高项)—学习笔记二
第一章 以下是上一篇(信息系统项目管理师(高项)—学习笔记)的续写,因为是之前记录的,这一篇还是细致到每一个小节的内容,有些过于复杂了,后续会简化~ 1.3 现代化创新发展 党的十九…...
【Vue】 style中的scoped
一、什么是scoped,为什么要用 在vue文件中的style标签上,有一个特殊的属性:scoped。 当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,通过该属性,可以使得组件之间的样式不互相污染…...

maven项目容器化运行之2-maven中使用docker插件调用远程docker构建服务并在1Panel中运行
一.背景 公司主机管理小组的同事期望我们开发的maven项目能够在1Panel管理的docker容器部署。上一篇写了先开放1Panel中docker镜像构建能力maven项目容器化运行之1-基于1Panel软件将docker镜像构建能力分享给局域网-CSDN博客。这一篇就是演示maven工程的镜像构建、容器运行、运…...

电影购票小程序论文(设计)开题报告
一、课题的背景和意义 随着互联网技术的不断发展,人们对于购票的需求也越来越高。传统的购票方式存在着排队时间长、购票流程繁琐等问题,而网上购票则能够有效地解决这些问题。电影购票小程序是网上购票的一种新型应用,它能够让用户随时随地…...

IP风险画像 金融行业的安全盾牌
在当今数字化时代,金融行业面临着前所未有的安全挑战。随着在线交易和数字银行业务的迅猛发展,欺诈和网络攻击的威胁也在不断增加。金融机构需要高效、可靠的安全解决方案来保护客户的资产和个人信息,防止各种形式的欺诈行为。 IP风险画像是…...
探索老年综合评估实训室的功能与价值
一、引言 随着人口老龄化的加剧,老年健康问题日益受到关注。老年综合评估实训室作为专门为老年人健康服务而设立的场所,具有独特的功能和重要的价值。 二、老年综合评估实训室的功能 (一)健康评估功能 1、身体功能评估 通过专业设…...

视频剪辑软件如何选?FCPX和PR更适合新手呢
随着抖音、快手等短视频平台的迅速兴起,短视频数量急剧增加。想要发布一款简单、高质量的短视频,运用剪辑软件至关重要。目前比较流行的有Adobe家的Premiere,以及Final Cut Pro X,经常有用户在二者间,不知如何选择&…...

解决第三方模块ts声明文件编译错误问题
最近小卷在用vite脚手架学习vue组件开发,使用的语言框架是typescript。在搭建vitepress在线文档服务时,用到了vitepress-demo-preview模块来展示vue组件示例和源代码。 发现import相关依赖时,会有这样的编译错误: 也就是没找到第…...

数据结构小测试:排序算法
目录 1、请简述数据结构八大排序算法的思路。 2、常用排序算法手写 冒泡排序: 选择排序: 快速排序: 归并排序: 堆排序: 3、额外再加一个二分查找吧 1、请简述数据结构八大排序算法的思路。 冒泡排序ÿ…...

电脑远程开关机
1. 远程开机 参考:https://post.smzdm.com/p/664774/ 1.1 Wake On LAN - 局域网唤醒(需要主板支持,一般都支持) 要使用远程唤醒,有几种方式:使用类似向日葵开机棒(很贵)、公网ip&…...

# Redis 入门到精通(四)-- linux 环境安装 redis
Redis 入门到精通(四)-- linux 环境安装 redis 一、linux 环境安装 redis – 基于 Linux 安装 redis 1、基于 Center 0S7 或者 unbunt-18.04 安装 Redis 1)下载安装包wget http://download.redis.io/releases/redis-?.?.?.tar.gz 如&…...
SQL进阶技巧:如何按照固定尺寸(固定区间)对数据进行打分类标签?
目录 0 问题引入 应用案例1 应用案例2 小结 0 问题引入 在日常数据分析中,经常会遇到数据产品经理或数据分析师提出这样的需求,比如按照某一给定的区间或数据范围对数据进行分类标签,而遇到这样的问题,好多同学感觉SQL做起来有点困难或无从下手,其实面对这样的问题笔者…...

数学建模·灰色关联度
灰色关联分析 基本原理 灰色关联分析可以确定一个系统中哪些因素是主要因素,哪些是次要因素; 灰色关联分析也可以用于综合评价,但是由于数据预处理的方式不同,导致结果 有较大出入 ,故一般不采用 具体步骤 数据预处理…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...