使用Vue3封装实现支持Base64导出的电子签名组件
作者:脆
这篇文章主要为大家详细介绍了使用Vue3封装实现支持Base64导出的电子签名组件的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以了解下
默认支持签字回显,base64压缩,内存释放
传参支持禁用签字也就是查看,组件大小内置'small', 'default', 'large'三个大小
效果图
准备工作
组件内用到elementPlus,vue-esign
组件,使用前提前安装好。
组件代码
<template> <!-- 签名容器 --> <div class="sign-container" > <div class="sign-preview" :class="[sizeClass, { 'has-sign': base64Img }]" @click="openDialog"> <img v-if="base64Img" :src="base64Img" class="preview-image" /> <div v-else class="placeholder"> <el-icon><EditPen /></el-icon> <span>点击签名</span> </div> </div> <!-- 签字弹窗 --> <el-dialog v-model="dialogVisible" title="电子签名" width="800px"> <vue-esign ref="esignRef" :width="800" :height="300" :lineWidth="4" :lineColor="'#000000'" :bgColor="'#ffffff'" :id="uuid" /> <template #footer> <el-button @click="dialogVisible = false">取消</el-button> <el-button @click="handleReset">清空</el-button> <el-button type="primary" @click="handleConfirm">确认</el-button> </template> </el-dialog> </div> </template> <script setup> import { ref } from 'vue'; import { useMessage, useMessageBox } from '/@/hooks/message'; import { generateUUID } from '/@/utils/other'; import vueEsign from 'vue-esign'; // 生成组件唯一id const uuid = ref('id-' + generateUUID()); // 组件尺寸 const sizeClass = computed(() => `sign-size--${props.size}`); const emit = defineEmits(['update:modelValue']); const props = defineProps({ modelValue: String, // v-model绑定 disabled: { type: Boolean, default: false, }, size: { type: String, default: 'default', validator: (v) => ['small', 'default', 'large'].includes(v), }, }); const dialogVisible = ref(false); const esignRef = ref(null); const base64Img = ref(props.modelValue); // 打开弹窗时重置画布 const openDialog = () => { if (props.disabled) return; dialogVisible.value = true; // handleReset(); }; // 清空画布(保留二次确认) const handleReset = async () => { try { await useMessageBox().confirm('此操作将清空签名,确定吗?'); esignRef.value?.reset(); } catch {} }; // 生成签名后压缩 const compressBase64 = (base64) => { return new Promise((resolve, reject) => { const img = new Image(); img.src = base64; img.onload = () => { // 创建canvas并设置缩放尺寸 const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // 计算压缩后尺寸(取原图50%) const targetWidth = img.width * 0.5; const targetHeight = img.height * 0.5; // 设置画布尺寸 canvas.width = targetWidth; canvas.height = targetHeight; // 绘制压缩图像 ctx.drawImage(img, 0, 0, targetWidth, targetHeight); // 生成新base64(自动处理格式) const mimeType = base64.match(/data:(.*?);/)[1]; canvas.toBlob( (blob) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.readAsDataURL(blob); }, mimeType, 0.6 ); // 质量参数生效于JPEG/WebP格式 }; img.onerror = (e) => reject('图片加载失败'); }); }; // 确认签名 const handleConfirm = async () => { esignRef.value .generate() .then(async (res) => { base64Img.value = await compressBase64(res); // 验证压缩效果 const originalSize = Math.round((res.length * 3) / 4 / 1024); const compressedSize = Math.round((base64Img.value.length * 3) / 4 / 1024); console.log(` 尺寸变化:${originalSize}KB → ${compressedSize}KB`); emit('update:modelValue', base64Img.value); dialogVisible.value = false; }) .catch(() => { base64Img.value = ''; emit('update:modelValue', ''); dialogVisible.value = false; }); }; // watch同步 watch( () => props.modelValue, async (val) => { if (!val) { base64Img.value = ''; esignRef.value?.reset(); } console.log(val); base64Img.value = await compressBase64(val); } ); onBeforeUnmount(() => { // 释放canvas内存 const canvas = esignRef.value?.$el.querySelector('canvas'); canvas.width = 0; canvas.height = 0; URL.revokeObjectURL(base64Img.value); // 释放Blob URL }); </script> <style scoped lang="scss"> .sign-container { display: inline-block; cursor: pointer; } .sign-preview { border: 1px solid #dcdfe6; background: #fff; border-radius: 4px; &.sign-size--small { width: 120px; height: 60px; } &.sign-size--default { width: 180px; height: 90px; } &.sign-size--large { width: 240px; height: 120px; } &.has-sign { border-color: var(--el-color-primary); } .preview-image { width: 100%; height: 100%; object-fit: contain; } .placeholder { height: 100%; display: flex; align-items: center; justify-content: center; color: #909399; .el-icon { margin-right: 8px; font-size: 18px; } } } </style>
使用组件
<el-form ref="dataFormRef" :model="form" inline :rules="dataRules"> <el-form-item label="经办人签字" prop="signatureHandler" label-width="8em"> <!-- 签名组件 --> <signature-component v-model="form.signatureHandler" /> </el-form-item> </el-form>
注意事项
使用时将组件内的提示框替换为elementPlus官方的
generateUUID方法自行修改为生成UUID的方法,也可以去掉。
到此这篇关于使用Vue3封装实现支持Base64导出的电子签名组件的文章就介绍到这了,更多相关Vue3电子签名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!