#遇到一个需求 需要一键复制把当前数据内的 图片(多个) 以及文本全部写入剪贴板#
前言:考虑到部分浏览器可能不支持 navigator.clipboard.write
方法,我们可以采用一个兼容性的解决方案,即利用 document.execCommand('copy')
方法。但是,直接复制图片到剪贴板在Web端是一个复杂的问题,特别是通过旧方法,因为它主要设计用于文本。对于图片,我们可以先将其转换为Data URL(Base64编码的图片),然后尝试复制这个字符串到剪贴板。尽管这样用户粘贴时得到的是图片的Base64编码文本而非直接的图片,但可以在某些场景下作为一种变通方案。
本文遇到不兼容的情况就直接弹框提醒复制失败了不做兼容处理了
先上代码
<div class="copy-box">
<div class="copy-box-text-box">
<span class="copy-box-number">{{ scope.row.verbalTemp }}</span>
<el-tooltip placement="top" content="复制">
<el-icon color="#409EFF" @click="copyImgText(scope.row)"><CopyDocument />
</el-icon>
</el-tooltip>
</div>
<div v-if="scope.row.attachmentList && scope.row.attachmentList.length>0">
<el-image v-for="(item,index) in scope.row.attachmentList" :key="index"
:src="item.fullUrl" style="width: 60px;"></el-image>
</div>
</div>
当点击复制图标的时候触发事件copyImgText 代码如下
// 复制事件
function copyImgText(row:any) {
copyText(row.verbalTemp);//先把文本复制到剪贴板
if (!navigator.clipboard || !navigator.clipboard.write) {
// 处理不支持剪贴板写入图片的情况
ElMessage.warning('当前浏览器不支持自动复制图片到剪贴板功能!')
return;
}
if(row.attachmentList && row.attachmentList.length>0){
for(let i=0;i<row.attachmentList.length;i++){
copyToBoard(row.attachmentList[i].fullUrl,i);
}
}
}
// 根据图片url 复制图片到剪切板
const copyToBoard = (url: string,i:number) => {
let path = url.split('?')[0]; // 去除查询字符串部分
const extension = path.split('.').pop()?.toLowerCase(); // 获取文件扩展名并转换为小写
const makeImage = async () => {
let res;
if(extension !== 'png'){
res = await convertImageUrlToPngBlob(url);
}else{
res = await fetch(url).then(response => response.blob());
}
return res;
}
setTimeout(() => {
navigator.clipboard.write([
new ClipboardItem({ 'image/png': makeImage() }),
]).then(() => {
console.log('success');
}).catch((e) => {
console.error(e);
})
}, (i+1)*400);
}
// 不是png格式的图片转出png图片的blob
async function convertImageUrlToPngBlob(imageUrl:string) {
// Fetch the image as a Blob
const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error('Failed to fetch image');
}
const blob = await response.blob();
// Create an Image object
const img = new Image();
img.src = URL.createObjectURL(blob);
await new Promise(resolve => img.onload = resolve); // Wait for the image to load
// Create a canvas and draw the image to it
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx?.drawImage(img, 0, 0, img.width, img.height);
// Convert the canvas to a PNG Blob
return new Promise(resolve => {
canvas.toBlob(function(blob) {
URL.revokeObjectURL(img.src); // Release the object URL
resolve(blob);
}, 'image/png');
});
}
该事件中 先吧文本复制到剪贴板 然后再处理图片写入到剪贴板的功能
当不兼容的时候直接弹框提示 如果支持write那么先根据图片的url获取图片的类型
如果是png的写入到剪贴板没有什么问题 目前write不支持写入非png的会报错 我的方法是如果判断不是png的图片 就想办法把图片转成png的然后再写入剪贴板
代码中为什么要使用到setTimeout 因为如果写入剪贴板的间隔很近 那么会被认为是用一个ClipboardItem操作 会覆盖之前复制到剪贴板中的内容
以上就是我实现一键复制多张图片和文本到剪贴板的具体实现方法了