常用函数之js复制图片至剪切板

news2024/11/19 17:49:40

背景

最近在工作中遇到了一个需求,点击按钮将Echart图复制到剪切板,然后按Ctrl(command)+V可以直接复制到聊天软件&文档编辑器中。本以为这是一个比较简单的需求,好像找了一圈资料,发现事情并不简单,故写下此文记录并分享。

常见方案

比较常见且有效的方案肯定是Clipboard API,不多说,直接上代码(手敲,如错误之处请指正):

const copyToBoard1 = (url: string) => {
    const img = new Image();
    img.src = url;
    img.setAttribute('crossOrigin', 'Anonymous');
    img.onload = () => {
        const width = img.width;
        const height = img.height;
        const newCanvas = document.createElement('canvas');
        const ctx = newCanvas.getContext('2d');
        if(ctx) {
            newCanvas.drawImage(img, width, height);
            newCanvas.toBlob(blob => {
                navigator.clipboard.write([         
                    new ClipboardItem({           
                        'image/png': blob,         
                    }),       
                ]).then(() => {
                    console.log('success');
                }).catch((e) => {
                    console.error(e);
                })
            }, 'image/png')
        }
    }
}

上述函数可以直接用在chrome中,但是存在一些问题:

  • 1、clipboard API 只支持png格式;
  • 2、存在兼容性问题,兼容性如下图:

image.png

从兼容性上来看,clipboard API几乎支持除IE之外的所有浏览器。但是,从我本次经历来看,在Safari浏览器、QQ浏览器上也存在兼容性问题(环境:MAC电脑,其余浏览器未曾测试),Chrome浏览器则无任何问题。

为了解决以上的兼容性问题,最终找到解决方案,不多说,上代码:

const copyToBoard2 = (url: string) => {
    const makeImage = async () => {
        const res = await fetch(url);
        return res.blob();
    }
    navigator.clipboard.write([         
        new ClipboardItem({           
            'image/png': makeImage(),         
        }),       
    ]).then(() => {
        console.log('success');
    }).catch((e) => {
        console.error(e);
    })
}

完整代码

import UAParser from 'ua-parser-js';

const hasCompatibilityNameList = [
    'safari',
    'qqbrowser'
]
const getHasCompatibilityName = () => {
    const parser = new UAParser();
    const res = parser.getResult();
    const name = res?.browser.name.toLowerCase();
    
    return name ? hasCompatibilityNameList.includes(name) : false;
}
const makeImageMethod1 = async (url:string) => {
    try{
        const res = await fetch(url);
        return res.blob();
    } catch {
        return ''
    }
}

const makeImageMethod2 = (url: string) => {  
  return new Promise((resovle) => {  
    const img = new Image();  
    img.src = url;  
    img.setAttribute('crossOrigin', 'anonymous');  
    img.onload = () => {  
      const newCanvas = document.createElement('canvas');  
      newCanvas.width = img.width;  
      newCanvas.height = img.height;  
      const ctx = newCanvas.getContext('2d');  
      if (ctx) {  
        ctx.drawImage(img, 0, 0);  
        newCanvas.toBlob((blob) => {  
          navigator.clipboard  
            .write([  
              new ClipboardItem({  
                'image/png': blob || '',  
              }),  
            ])  
            .then(  
              () => {  
                resovle(true)  
              },  
              () => {  
                resovle(false)  
              }  
            );  
        }, 'image/png');  
      }  
    };  
    img.onerror = () => {  
      resovle(false)  
    };  
  })  
}

export const copyToBoard = async (url: string) => {  
  const isSafariOrQQ = getHasCompatibilityName();  
  let flag = true;
  if (isSafariOrQQ) {  
    navigator.clipboard.write([  
      new ClipboardItem({ 'image/png': makeImagePromise(url) }),  
    ]).then(() => {  
      console.log('复制成功')  
    }).catch(async () => {  
      const res = await makeImageMethod2(url);  
      if (!res) {  
        flag = false  
      }  
    })  
  } else {  
    const res = await makeImageMethod2(url);  
    if (!res) {  
      navigator.clipboard.write([  
        new ClipboardItem({ 'image/png': makeImagePromise(url) }),  
      ]).then(() => {  
        console.log('复制成功')  
      }).catch(() => {  
        flag = false  
      })  
    }  
  }  
  return flag;  
}

最终,选择了2种方案结合的形式:

  • 1、判断当前浏览器环境是否是Safari、QQ

    • 1、失败、异常,则调用方法2;
  • 2、其余环境

    • 1、失败、异常,则调用方法1;
  • 3、方法1、2都失败,则返回false;

抛出false则认为2种函数在当前浏览器环境均不可成功复制。

这里的逻辑就是考虑环境判断不完整,将2个函数都调用一遍,兜底作用。

实测上述方案可以正常在Safari、QQ、Chrome浏览器中正常复制图片到剪切板。

原文

常用函数之js复制图片至剪切板

注:原文也是作者所写。转载请注明出处,谢谢!

参考

JS复制图片到剪切板

如何在Safari中使用剪贴板API将图像写入剪贴板

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1313453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue 组件传参 emit

emit 属性:用于创建自定义事件,接收子组件传递过来的数据。 注意:如果自定义事件的名称,和原生事件的名称一样,那么只会触发自定义事件。 setup 语法糖写法请见:《Vue3 子传父 组件传参 defineEmits》 语…

『番外篇二』Swift “黑魔法”之动态获取类实例隐藏属性的值

概览 在 Swift 代码的调试中,我们时常惊叹调试器的无所不能:对于大部分“黑盒”类实例的内容,调试器也都能探查的一清二楚。 想要自己在运行时也能轻松找到 Thread 实例“私有”属性的值吗(比如 seqNum)? 在本篇博文中您将学到如下内容: 概览1. 借我,借我,一双慧眼吧…

MFC画折线图,基于x64系统

由于项目的需要,需要画一个折线图。 传统的Teechart、MSChart、HighSpeedChart一般是只能配置在x86系统下,等到使用x64系统下运行就是会报出不知名的错误,这个地方让人很苦恼。 我在进行配置的过程之中,使用Teechart将x86配置好…

让测试效率起飞的8款浏览器兼容性测试工具,你get了吗?

浏览器的兼容性问题,是指不同浏览器使用内核及所支持的 HTML 等网页语言标准不同,用户客户端的环境不同造成的显示效果不能达到理想效果。 对于用户而言,无论使用哪款浏览器,期望看到的效果是正常的统一的。市面上发布的浏览器版…

CentOS 防火墙管理及使用的redis基本常用命令

文章目录 防火墙管理使用systemctl管理防火墙启动、关闭使用firewalld-cmd配置访问防火墙策略firewalld配置文件修改限制来源IP docker使用 redis 防火墙管理 需要关闭防火墙或者开启对应端口 使用systemctl管理防火墙启动、关闭 启动防火墙: systemctl start fi…

微服务实战系列之ZooKeeper(上)

前言 历经1个多月的创作和总结,纵观博主微服务系列博文,大致脉络覆盖了以下几个方面: 数据方面(缓存&安全) 比如Redis、MemCache、Ehcache、J2cache(两级缓存框架)、RSA加密、Sign签名…传…

【LSM tree 】Log-structured merge-tree 一种分层、有序、面向磁盘的数据结构

文章目录 前言基本原理读写流程写流程读流程 写放大、读放大和空间放大优化 前言 LSM Tree 全称是Log-structured merge-tree, 是一种分层,有序,面向磁盘的数据结构。其核心原理是磁盘批量顺序写比随机写性能高很多,可以通过围绕这一原理进行…

Redis 的常见使用场景

01 缓存 作为 Key-Value 形态的内存数据库,Redis 最先会被想到的应用场景便是作为数据缓存。而使用 Redis 缓存数据非常简单,只需要通过 string 类型将序列化后的对象存起来即可,不过也有一些需要注意的地方: 必须保证不同对象的…

面对.mkp病毒:专业咨询,文件恢复,帮您应对.mkp病毒

引言: 近期,网络上出现了一种新型的勒索病毒,被称为.halo。这种威胁采用高度复杂的加密算法,将用户的数据文件锁定,并要求支付赎金以解锁。本文将介绍.halo勒索病毒的特征、应对方法,以及如何预防此类攻击…

RabbitMQ插件详解:rabbitmq_web_stomp【RabbitMQ 六】

欢迎来到我的博客,代码的世界里,每一行都是一个故事 《RabbitMQ Web STOMP:打破界限的消息传递之舞》 前言STOMP协议简介STOMP(Simple Text Oriented Messaging Protocol)协议简介STOMP与WebSocket的关系 WebSocket和R…

云原生之深入解析Kubernetes中服务的性能

一、Pyroscope 简介 ① 什么是 Pyroscope? 开发人员通常需要查看生产应用程序中的性能瓶颈以确定问题的原因,为此通常需要可以通过日志和代码工具收集的信息。不幸的是,这种方法通常很耗时,并且不能提供有关潜在问题的足够详细信…

PR模板,漂亮的文字帖子视频模板,方形标题PR项目工程文件下载

Premiere Pro模板,具有6个方形设计PR视频帖子标题文字PR项目工程文件。使用附带的颜色控制器调整和修改颜色,与您自己的品牌相匹配。使用这些效果来增强视频画面。包括视频教程。 适用软件:PR2019 | 分辨率:10801080(方…

Android APP 常见概念与 adb 命令

adb 的概念 adb 即 Android Debug Bridge 。在窗口输入 adb 即可显示帮助文档。adb 实际上就是在后台开启一个 server,会接收 adb 的命令然后帮助管理,控制,查看设备的状态、信息等,是开发、测试 Android 相关程序的最常用手段。…

第P7周:咖啡豆识别(VGG-16复现)

>- **🍨 本文为[🔗365天深度学习训练营](https://mp.weixin.qq.com/s/rbOOmire8OocQ90QM78DRA) 中的学习记录博客** >- **🍖 原作者:[K同学啊 | 接辅导、项目定制](https://mtyjkh.blog.csdn.net/)** 一、前期工作 import …

Linux 常用命令----mktemp 命令

文章目录 基本用法实例演示高级用法注意事项 mktemp 命令用于创建一个临时文件或目录,这在需要处理临时数据或进行安全性测试时非常有用。使用 mktemp 可以保证文件名的唯一性,避免因文件名冲突而导致的问题。 基本用法 创建临时文件: 命令 mktemp 默认…

【IC验证】perl脚本——分析前/后仿用例回归情况

目录 1 脚本名称 2 脚本使用说明 3 nocare_list文件示例 4 脚本执行方法 5 postsim_result.log文件示例 6 脚本代码 1 脚本名称 post_analysis 2 脚本使用说明 help:打印脚本说明信息 命令:post_analysis help 前/后仿结束后,首先填…

餐饮品牌小红书探店怎么做?建议收藏

对于餐饮行业来说,消费者的口味和选择越来越多样化,如何在众多竞争者中脱颖而出,成为消费者的心头好,探店活动便应运而生。小红书作为国内知名的社交电商平台,拥有庞大的用户群体,特别是年轻人和美食爱好者…

多域名https证书购买选择

多域名https证书是一种特殊的SSL证书,它允许一个证书同时保护多个域名,并且不限制域名的类型,可以保护多个域名和子域名,确保网站传输信息时不被窃取、篡改。那么我们该怎么选择符合需求的多域名https证书呢?今天就随S…

Python神器:快速删除文本文件中指定行的方法

1. 简介 文件操作是编程中的重要方面。Python作为强大的编程语言,提供了处理文件的能力。删除特定行是文件处理中常见的需求。 2. 打开文件和读取内容 当打开文件并读取其内容时,open()函数和with语句是Python中常用的工具。以下是展示如何使用它们的…

由@EnableWebMvc注解引发的Jackson解析异常

同事合了代码到开发分支,并没有涉及到改动的类却报错。错误信息如下: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.conv…