Vue3 + vue-web-screen-shot 前端实现页面截图64编码转图片文件上传
Vue3 + vue-web-screen-shot 浏览器-在网页中使用自定义截图功能,并将64编码转图片文件上传
·
最近项目遇到的要求是弹出框上传文件,需要用到页面截图,由于使用的是Vue3的框架于是选择用vue-web-screen-shot组件进行操作。(由于插件是Vue3编写的,所以只适用于Vue3的项目,如果是Vue2的项目,截图组件可以使用js-web-screen-shot)
需要实现的效果如下:
点击截图后弹窗消失,用户可随意在页面中截图等操作
确认后在弹窗中显示截图列表,上传表格
整个操作步骤实现如下:
- 在项目中添加vue-web-screen-shot组件
- 在项目入口文件中导入组件
- 在需要使用的页面使用组件
- 在页面截图后使用获得的64编码转为图片文件形式进行上传
1.在项目中添加vue-web-screen-shot组件
//使用以下代码添加插件
yarn add vue-web-screen-shot
# or
npm install vue-web-screen-shot --save
2.在main.js中导入组件
// 导入截屏插件
import screenShort from "vue-web-screen-shot";
const app = createApp(App);
// 使用截屏插件
app.use(screenShort, { enableWebRtc: false })
3.在需要的页面导入截图组件
<template>
<div v-show="showScreenShort">
<el-dialog>
//省略弹框其他部分
...
<el-button @click="jietu">快捷截图</el-button>
</el-dialog>
</div>
//直接使用组件即可,不用在该页面继续添加
<screen-short
v-if="screenshotStatus"
@get-image-data="getImg"
@destroy-component="destroyComponent"
>
</screen-short>
</template>
如果将screen-short组件放在弹出框内部,则隐藏弹出框时会连同截屏组件一起隐藏,所以建议放在外部,并给dialog弹出框单独加一个div,用showScreenShort控制弹出框显示和隐藏
参数说明
如示例代码所示,在template中直接使用
screen-short
插件,绑定组件需要的事件处理函数即可。接下来就跟大家讲下组件中每个属性的意义:
- screenshotStatus 用于控制组件是否出现在dom中
- @destroy-component 用于接收截图组件传递的销毁消息,我们需要在对应的函数中销毁截图组件
- @get-image-data 用于接收截图组件传递的框选区域的base64图片信息,我们需要为他提供一个函数来接收截图组件传递的消息
可选参数
截图插件有一个可选参数,它接受一个对象,对象每个key的作用如下:
enableWebRtc
是否启用webrtc,值为boolean类型,值为false则使用html2canvas来截图level
截图容器层级,值为number类型。clickCutFullScreen
单击截全屏启用状态,值为boolean
类型, 默认为false
hiddenToolIco
需要隐藏的截图工具栏图标,值为{ save?: boolean; undo?: boolean; confirm?: boolean }
类型,默认为{}
。传你需要隐藏的图标名称,将值设为true
即可。enableCORS
html2canvas截图模式下跨域的启用状态,值为boolean
类型,默认为false
proxyAddress
html2canvas截图模式下的图片服务器代理地址,值为string
类型,默认为undefined
截图功能实现代码如下:
<script>
function jietu() {
showScreenShort.value = false;//隐藏弹框
screenshotStatus.value = true;//显示截图插件
}
//截图按了√以后生成64编码
async function getImg(base64) {
var image = new Image();
image.src = base64;
image.onload = () => {
var canvas = convertImageToCanvas(image);
var url = canvas.toDataURL('image/jpeg');
var name = guid();
uploadlist.value.push({ image: url, name: name });
};
//截图完成后显示弹框
showScreenShort.value = true;
}
//生成文件唯一编码作为name 方便后续删除图片时查找对象
function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
//取消截图 显示弹窗 隐藏截图插件
function destroyComponent() {
screenshotStatus.value = false;
showScreenShort.value = true;
}
</script>
接下来制作截图的列表框,循环的是js代码中64编码uploadlist表,由于用户可能需要对图片进行查看、删除等操作,加入点击事件
//在之前的弹窗快捷截图后边
<div v-if="uploadlist.length > 0" class="imglist">
<div v-for="(item, index) in uploadlist" class="picBox">
<img
:src="item.image"
title="点击查看大图"
alt="item.name"
@click="handlePictureCardPreview(item.image)"/>
<span style="float: right">
<i class="iconfont icon-guanbi" @click="deleteImg(item.name)"></i>
</span>
</div>
</div>
//查看大图也是一个弹出框的形式
<el-dialog v-model="dialogVisible" class="dialogSmall">
<template #header>
<div class="dialogHeader">
<div>查看大图</div>
</div>
</template>
<img w-full :src="dialogImageUrl" alt="Preview Image" style="width: 100%" />
</el-dialog>
//涉及语法
// 查看图片大图
<script>
function handlePictureCardPreview(url) {
dialogImageUrl.value = url;
dialogVisible.value = true;
}
</script>
删除截图代码:
function deleteImg(name) {
console.log(name);
uploadlist.value.forEach((value, index, array) => {
if (name == value.name) {
array.splice(index, 1);
}
});
}
4.确定上传时将64编码转成文件形式上传
因为之前可能会涉及到文件的删除,所以考虑在最后上传的时候再将所有的截图64编码进行数据转换。
async function submitForm(formEl) {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
//上述是绑定了表格验证
//下面开始上传文件
let formData = new FormData();
formData.append('description', servicesForm.value['description']);
//这里是关于截图部分的64base转码
if (uploadlist.value.length > 0) {
uploadlist.value.forEach((e) => {
//通过atob将base64进行编码
var bytes = window.atob(e.image.split(',')[1]);
//处理异常,将ASCII码小于0的转换为大于0,进行二进制转换
var buffer = new ArrayBuffer(bytes.length);
//生成一个8位数的数组
var uint = new Uint8Array(buffer);
//根据长度返回相对应的Unicode 编码
for (var i = 0; i < bytes.length; i++) {
uint[i] = bytes.charCodeAt(i);
}
//Blob对象,type为图片的格式
var imageFile = new Blob([buffer], { type: 'image/jpeg' });
//最后将转换的文件放入要上传的数组中
imageFilelist.push(imageFile);
});
//将已转换好的文件进行上传
for (var i = 0; i < imageFilelist.length; i++) {
formData.append('picFiles', imageFilelist[i], guid() + '.jpg');
}
}
//上传接口,上传formData数据,关闭弹出框
addFeedback(formData).then((data) => {
closeDialog();
emit('updateData', '');
});
}
});
}
以上。
更多推荐
已为社区贡献2条内容
所有评论(0)