JavaScript如何实现复制图片功能?
最近开发中遇到一个需求,就是用户希望能通过直接点击按钮复制图片,然后就可以很方便的把图片发送到班群中,于是就有了复制图片的需求。
那么如何通过JavaScript来实现复制图片呢?
一、前置知识:如何实现复制?
既然要复制图片,那我们先看看前端是怎么实现复制功能的。
一般来说,实现复制有2种方案:
document.execCommand()方法;Clipboard API;
复制功能的安全限制:复制脚本需要放在监听事件回调里面进行执行,由用户触发(比如点击事件),如果直接执行脚本,浏览器可能会报错。
下面分别介绍下这2个方法:
1.1 document.execCommand()
使用方法:
先选中文本,然后调用 document.execCommand('copy'),即可将选中的文本复制到剪贴板。
const input = document.getElementById("input");
input.select(); // 注意 input 框不能添加 disabled 属性,否则会影响 select() 方法
document.execCommand("copy");
同样的它还可以实现剪切和粘贴功能。
document.execCommand('cut'):剪切选中的文本到剪贴板。document.execCommand('paste'):从剪贴板粘贴文本到光标位置。
剪切功能的使用和复制一样,所以这里就不做演示了。我这边再演示一下粘贴功能。
粘贴功能有以下使用限制:
- 确保元素是可编辑的,比如
input、textarea、contenteditable属性为true的元素。 - 确保元素是焦点元素,可以使用
focus()方法将焦点设置到元素上。
const target = document.getElementById('pasteTargetInput');
target.focus(); // 确保目标元素获得焦点
document.execCommand('paste'); // 尝试粘贴
但是现代浏览器比如(Chrome、Firefox、Edge)已经限制或废弃了 execCommand("paste") 的直接使用,所以不推荐用这个api了。
最后总结一下,document.execCommand()是实现复制的一个传统方法,它的优缺点如下:
- 优点:低版本浏览器兼容性好,
- 缺点:
- 已被
web 标准弃用,不推荐使用。 - 只能复制文本,不能复制图片或者二进制数据。
- 只能讲选中的内容写入到剪贴板,不能直接写入自定义内容。
- 它是同步操作,如果复制内容过多,会引起页面卡顿。
1.2 Clipboard API
在浏览器的BOM对象中,有一个API叫clipboard,它提供了系统剪贴板的读写访问能力,可以实现剪切、复制和粘贴功能,我们可以通过window上的navigator对象直接访问到一个clipboard对象。
console.log(navigator.clipboard);
clipboard提供了四个方法:
read():从剪切板读取数据,它会返回一个Promise,并将数据包装成一个ClipboardItem对象回传,readText():从剪切板中读取文本,它会返回一个Promise对象,并将剪切板数据作为String回传,write():写入数据(ClipboardItem对象)到剪切板,它会返回一个Promise,Promise成功意味着写入完成,writeText():写入文本到剪切板,它会返回一个Promise,Promise成功意味着写入完成。
我们可以通过上面描述的write()和writeText()方法实现复制功能,writeText()只能写入文本,而write()方法则可以写入任意数据,所以我们需要使用write()方法实现复制图片的功能。
二、实现复制图片
一般图片是通过两种形式加载:
- 远程URL,最常见的是
cdn地址,比如https://cdn.xxx.cn/example.png, - base64 URL,一些体积较小的图片通常会打包成
base64字符串,以减少网站资源请求数量,比如data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...。
不管是什么图片形式的图片,我们最终目的都是需要将它转化为blob对象,然后通过navigator.clipboard.write()方法写入到剪贴板。
比如这样一张图片:
<img src="https://xxx" alt="加载失败" id="img"/>
我们可以通过 canvas 将图片复制到剪贴板,具体代码如下:
function copyImage(img) {const canvas = document.createElement('canvas')canvas.width = img.widthcanvas.height = img.heightconst ctx = canvas.getContext('2d')ctx.drawImage(img, 0, 0, img.width, img.height)canvas.toBlob((blob) => {// 目前图片只支持 png 类型const clipboardItem = new ClipboardItem({ 'image/png': blob })navigator.clipboard.write([clipboardItem])})
}
img.addEventListener("click", () => {copyImage(img);
});
这里如果出现Uncaught SecurityError: Failed to execute 'toBlob' on 'HTMLCanvasElement'报错,可能是你使用的图片跨域了,首先确保图片资源服务器允许跨域使用,然后需要在img标签上增加crossOrigin属性。
<img src="xxx" crossOrigin/>
当然实际业务中可能提供的只是一个图片点击后的跳转链接,需要先把链接转成一张二维码图片,再进行复制。
这里使用第三方库qrcode,把链接转化成二维码。
import QRcode from 'qrcode';async function copyImage(url) {// 转成 base64 的 urlconst url = await QRcode.toDataURL(link, {errorCorrectionLevel: 'H', // 纠错级别最高width: 128,margin: 2,scale: 1,});const blob = await (await fetch(url)).blob();const clipboardItem = new ClipboardItem({ 'image/png': blob })navigator.clipboard.write([clipboardItem])
}
我们这里通过QRcode.toDataURL()方法,拿到二维码的base64图片url,然后通过原生的fetch方法,把二维码图片转化成blob对象,最后以ClipboardItem形式写入到clipboard中。
除了fetch以外,还可以通过如下方式将base64图片转化为blob对象,具体代码如下:
function dataURIToBlob(dataURI) {const base64Index = dataURI.indexOf(';base64,') + 8;const base64 = dataURI.substring(base64Index);const byteCharacters = atob(base64);const byteArrays = [];for (let i = 0; i < byteCharacters.length; i++) {byteArrays.push(byteCharacters.charCodeAt(i));}const byteArray = new Uint8Array(byteArrays);const blob = new Blob([byteArray], { type: 'image/png' });return blob;
}
三、clipboard兼容性问题
在一些浏览器上可能不支持Clipboard API,所以需要通过navigator.clipboard的值是否为undefined判断此浏览器是否支持复制功能,如果不支持Clipboard API的话,就无法复制图片了,这时候可以使用document.execCommand('copy')来复制文本,或者直接给用户提示该浏览器不支持复制图片。
// 将dataBase64复制到剪切板
function copyToClipboard(text) {let a = document.createElement('input');a.value = text;document.body.appendChild(a);a.select();document.execCommand('copy');a.remove();
}function copyImage() {if (navigator.clipboard) {//...const clipboardItem = new ClipboardItem({ 'image/png': imgBlob });navigator.clipboard.write([clipboardItem]);console.log('复制成功');} else {copyToClipboard(img.src);}
}
四、其它功能
4.1 预览图片
预览图片主要依赖于URL.createObjectURL这个原生API,具体代码如下:
function previewImage(img) {const url = URL.createObjectURL(blob);const img = document.createElement('img');img.src = url;document.body.appendChild(img);
}
4.2 下载图片
下载图片主要依赖于a标签的download属性,具体代码如下:
function downloadImage(img) {const url = URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = true;a.click();URL.revokeObjectURL(url);console.log('下载图片成功');
}
五、小结
本文主要介绍了前端如何实现复制图片的功能,核心是通过Clipboard API来实现的,如遇到浏览器兼容问题,可以考虑回退使用document.execCommand()进行低版本的兼容,另外还介绍了预览图片和下载图片的实现思路,希望能帮助到大家!
相关文章:
JavaScript如何实现复制图片功能?
最近开发中遇到一个需求,就是用户希望能通过直接点击按钮复制图片,然后就可以很方便的把图片发送到班群中,于是就有了复制图片的需求。 那么如何通过JavaScript来实现复制图片呢? 一、前置知识:如何实现复制…...
MySQL 8 设置允许远程连接(Windows环境)
🌟 MySQL 8 设置允许远程连接(Windows环境) 在开发和部署应用时,经常需要从远程主机连接到MySQL数据库。默认情况下,MySQL仅允许本地连接,因此需要进行一些配置才能允许远程访问。今天,我将详细…...
我又又又又又又更新了~~纯手工编写C++画图,有注释~~~
再再再次感谢Ttcofee提的问题 本次更新内容: 鼠标图案(切换),版本号获取,输入框复制剪切板 提前申明:如果运行不了,请到主页查看RedpandaDevc下载,若还是不行就卸了重装。 版本号&…...
Python控制语句——循环语句-for
1.下面的语句哪个会无限循环下去()。 A、 for a in range(10): time.sleep(10) B、 while 1<10: time.sleep(10) C、 while True: break D、 a = [3,-1,2] for i in a: if i==-1: break 答案:B。1<10始终为True,循环体中又没有break的条件,故B会无限循环。 2.for s i…...
全面解析:将采购入库单数据集成到MySQL的技术实施
旺店通旗舰版-采购入库单集成到MySQL的技术案例分享 在数据驱动的业务环境中,如何高效、准确地实现系统间的数据对接是企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例:将旺店通旗舰奇门平台上的采购入库单数据集成到MySQL数据库中&#x…...
12. Pandas :使用pandas读Excel文件的常用方法
一 read_excel 函数 其他参数根据实际需要进行查找。 1.接受一个工作表 在 11 案例用到的 Excel 工作簿中,数据是从第一张工作表的 A1 单元格开始的。但在实际场景中, Excel 文件可能并没有这么规整。所以 panda 提供了一些参数来优化读取过程。 比如 s…...
记录致远OA服务器硬盘升级过程
前言 日常使用中OA系统突然卡死,刷新访问进不去系统,ping服务器地址正常,立马登录服务器检查,一看磁盘爆了。 我大脑直接萎缩了,谁家OA系统配400G的空间啊,过我手的服务器没有50也是30台,还是…...
Java网络多线程
网络相关概念: 关于访问: IP端口 因为一个主机上可能有多个服务, 一个服务监听一个端口,当你访问的时候主机通过端口号就能知道要和哪个端口发生通讯.因此一个主机上不能有两个及以上的服务监听同一个端口. 协议简单来说就是数据的组织形式 好像是两个人交流一样,要保证自己说…...
【H2O2 | 软件开发】Axios发送Http请求
目录 前言 开篇语 准备工作 正文 概念 封装工具包 示例 结束语 前言 开篇语 本系列为短篇,每次讲述少量知识点,无需一次性灌输太多的新知识点。该主题文章主要是围绕前端、全栈开发相关面试常见问题撰写的,希望对诸位有所帮助。 如…...
VScode 运行LVGL
下载vscode解压 环境安装 安装mingw64,gcc 版本必须8.3以上 安装cmak 系统环境变量Path中添加(以实际安装目录为准) C:\Program Files\mingw64\bin C:\Program Files\CMake\bin 将GUI-Guider生成的代码目录拷贝一份放到vscode项目目录…...
AIP-165 按条件删除
编号165原文链接https://google.aip.dev/165状态批准创建日期2019-12-18更新日期2019-12-18 有时API需要提供一种机制,按照一些过滤参数删除大量资源,而非提供待删除的各资源名字。 这是一个稀有的场景,用于用户一次性删除数千或更多资源的…...
React Next项目中导入Echart世界航线图 并配置中文
公司业务要求做世界航线图,跑了三个ai未果,主要是引入world.json失败,echart包中并不携带该文件,源码的world.json文件页面404找不到。需要自己寻找。这是整个问题卡壳的关键点,特此贴出资源网址。 目录 一、安装 二…...
QT与网页显示数据公式的方法
一.网页中显示数学公式通常有三种主要方法 1.图片方式 原理:将公式转换为图片(如 PNG、SVG),通过 <img> 标签嵌入网页。 实现步骤: 使用工具(如 LaTeX dvipng、在线生成工具)将公式渲…...
深入解析APP订阅页的运作机制(订阅页如何运作)
在当今数字经济的背景下,订阅模式已成为许多企业获取稳定收入的重要方式。无论是软件、视频流媒体还是电子商务,订阅服务都能为用户提供持续的价值体验。然而,如何有效地设计和运作一个订阅页,是决定用户是否愿意订阅的关键因素。…...
Golang倒腾一款简配的具有请求排队功能的并发受限服务器
golang官方指南[1]给了一些代码片段,层层递进演示了信道的能力: 1>. 信号量2>. 限流能力 var sem make(chan int, MaxOutstanding) func Serve(queue chan *Request) {for req : range queue {req: reqsem <- 1 go func() { // 只会开启MaxOutstandin…...
【运维】服务器系统从centos7重装为ubuntu22.04
目录 一、硬盘准备二、系统安装三、安装基本系统组件四、挂载机械硬盘五、问题解决 一、硬盘准备 【注意:这一步会把硬盘的数据清空,所以需要找一个空的U盘或者把U盘数据备份】 ubuntu22.04下载 需要先安装 bittorrent 下载完之后会打开一个网页 然后…...
创新技术引领软件供应链安全,助力数字中国建设
编者按 随着数字化转型的加速,针对软件供应链的攻击事件呈快速增长态势,目前已成为网络空间安全的焦点。如何将安全嵌入到软件开发到运营的全流程,实现防护技术的自动化、一体化、智能化,成为技术领域追逐的热点。 悬镜安全作为…...
【设计模式】建造者模式——工厂模式
三、建造者模式——工厂模式 3.1 工厂模式 创建一个类对象的传统方式是使用关键字new, 因为用new 创建的类对象是一个堆对象,可以实现多态。工厂模式通过把创建对象的代码包装起来,实现创建对象的代码与具体 的业务逻辑代码相隔离的目的(将对象的创建和…...
Java基础:枚举类enum入门案例
1.基础枚举定义与使用: package com.zxy;public class Main {public static void main(String[] args) { // 获取枚举值cars car cars.BMW;switch (car){case BMW :System.out.println("BMW");break;case BENZ :System.out.println("BENZ&…...
蓝桥备赛(18)- 红黑树和 set 与 map(上)
对于二叉搜索树 , 平衡二叉树 , 以及红黑树 , 目前只需要了解背后的原理 , 不做代码实现的要求 , 重要的就是了解各种操作的时间复杂度即可 , 为set 与 map 做铺垫 一、二叉搜索树 1.1 基本概念 相较与于堆…...
Spring Boot集成EasyExcel
1. 初始化Spring Boot项目 首先,使用Spring Initializr(https://start.spring.io/)生成一个基本的Spring Boot项目。选择以下依赖项: Spring WebLombok (用于减少样板代码)SLF4J (用于日志记录) 2. 添加依赖 在你的pom.xml文件…...
obeaver 连接oracle 库 模式乱码
下载orai18n-12.1.0.2.0.jar 库--添加文件--把提前下载好的jar 随便放在一个文件夹下--添加文件选中,然后点击找到类, 选择类,确定即可正常 下载地址:https://download.csdn.net/download/weixin_42845364/88368302...
ChatGPT 使用教程:深度探索AI常用功能技巧
文章目录 前言一、ChatGPT介绍1.1 人工智能与自然语言处理的发展1.2 ChatGPT 的诞生与意义 二、ChatGPT 基础入门2.1 注册与登录2.2 对话界面介绍2.3 基本提问方式 三、常用功能详解3.1 文本生成3.2 问题回答3.3 语言翻译3.4 代码生成与调试 四、高级使用技巧4.1 指令优化4.2 多…...
無人機的應用程序有那些可以部署在linux server 系統
Dronecode Project:由 Linux Foundation 主導的開源項目,提供無人機航空操作系統和導航工具的開發框架,適合開發者使用。 DeepSeek-R1:這是一個人工智能模型,適用於無人機的數據處理和分析,支持在 Linux 系…...
[HUBUCTF 2022 新生赛]messy_traffic
下载附件 看到文件类型直接用wireshark打开,对MySQL协议进行追踪流,并没有什么发现,后面对NO.437发现有用信息,http追踪流 发现**system(‘cat passwd.txt’);**这里是在打开查看passwd.txt,密码是"SignUpForHUBU…...
铁人三项(第五赛区)_2018_rop题解
先启动靶机连接看看。 直接ls,就给我输出句话,看来不能直接拿flag。 那走下流程。 查下位数和其他信息: 可以看到是32位的包,开了NX,但没开其他保护。 用ida32打开looklook。 主函数就是个这,看到了弹出的…...
package.json 依赖包约束及快速删除node_modules
文章目录 一、package.json版本约束1、初始项目安装2. 已有 yarn.lock 文件的项目安装3. 特殊情况手动修改 package.json 版本:使用 yarn upgrade 命令: 二、快速删除node_modules三、depcheck 检测npm未使用的依赖 一、package.json版本约束 1、初始项…...
Compose 实践与探索六 —— 动画的流程控制与 Transition
1、Block 参数:监听每一帧 animateTo() 与 animateDecay() 中都有一个函数类型的 block 参数: suspend fun animateDecay(initialVelocity: T,animationSpec: DecayAnimationSpec<T>,block: (Animatable<T, V>.() -> Unit)? null): An…...
虚拟机Contos7为啥不能被本机电脑访问?
1.查看防火墙是否开启 systemctl status firewalld.service 2.如果防火墙关闭就可以直接被访问 3.如果防火墙打开了我们需要开放端口(下面为防火墙一系列指令) # 关闭防火墙 systemctl stop firewalld.service# 打开防火墙 systemctl start firewalld.service# 关闭开启自启…...
【21】单片机编程核心技巧:if语句逻辑与真假判断
【21】单片机编程核心技巧:if语句逻辑与真假判断 七律 条件分野 if语句判真假,括号条件定乾坤。 非零为真零为假,大括号内藏玄门。 省略虽简风险在,代码规范护本根。 单片逻辑由心控,条件分支自成文。 注释…...
