找的插件,自己写要做一堆兼容麻烦死了
使用的这个插件vue-signature-pad,看下载量很多
npm i vue-signature-pad
import { VueSignaturePad } from 'vue-signature-pad'; components: { VueSignaturePad, UseDetailDailog }, <VueSignaturePad class="sign-box" :width="signWidth + 'px'" :height="signHeight + 'px'" ref="signaturePad" :options="options" />
options: { backgroundColor: 'rgba(0,0,0,0)', penColor: 'rgba(0,0,0,1)', velocityFilterWeight: 0.7, onBegin: () => { (this.$refs.signaturePad as any).resizeCanvas() }, // 手动初始化 }, mounted() { this.checked = false; const { width, height } = document.getElementById('pad-box')?.getBoundingClientRect() as any; this.signWidth = width - 10; this.signHeight = height; nextTick(() => { (this.$refs.signaturePad as any).resizeCanvas(); this.setSignBg(); // this.setSignWatermark(); }) },
应为要使用撤销的功能,所以水印是自己做背景做的假货,但是上传的时候需要带上水印,拿到插件给的数据是base64,所以要自己再画一遍加上水印
async setSignWatermark(base64: string) { const canvas = document.createElement('canvas') as HTMLCanvasElement; const ctx = canvas?.getContext("2d") as CanvasRenderingContext2D;//获取画笔 canvas.width = this.signWidth; canvas.height = this.signHeight; canvas.style.display = "none"; const width = 130; const height = 120; const numberLine = Math.ceil(this.signWidth / width) + 10; const numberHeight = Math.ceil(this.signHeight / height) + 10; ctx.font = "16px"; ctx.fillStyle = "rgba(0,0,0,.3)"; ctx.save(); ctx.rotate(-0.4); for (let i = -10, l = numberLine; i < l; i++) { for (let j = -10, h = numberHeight; j < h; j++) { ctx.fillText("eefit会员项目使用凭证", (200 / 6) + (i * width), (160 / 2) + (j * height)); ctx.translate(5, 0); } }; ctx.restore(); const img = await this.createImg(base64); ctx.drawImage(img, 0, 0, this.signWidth, this.signHeight); return canvas; },
createImg(url: string): Promise<any> {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = url;
img.onload = () => {
resolve(img);
};
img.onerror = () => {
reject();
};
});
},
最后一步,校验并提交获取url
async upSign() { try { await this.checkedInfo(); this.loading = true; const { data } = (this.$refs.signaturePad as any).saveSignature(); const canvas = await this.setSignWatermark(data); const dataURL = canvas.toDataURL('image/png'); this.ossConfig = await commonService.getOssConfig(); this.client = new OSS({ accessKeyId: this.ossConfig.access_key_id, accessKeySecret: this.ossConfig.access_key_secret, region: this.ossConfig.region, bucket: this.ossConfig.bucket, }); let fileName = `${new Date().getTime()}${Math.ceil(Math.random() * 1e5)}.png`; const file = this.base64ToFile(dataURL, fileName); let url = ''; await this.client.put(`${this.ossConfig.object}/${fileName}`, file, { headers: { 'x-oss-security-token': this.ossConfig.security_token, } }).then((res: any) => { url = `${this.ossConfig.domain}/${this.ossConfig.object}/${fileName}`; }).catch((err: any) => { }); console.log('url->', url); } catch (error) { ElMessage.error(this.$t('提交签名失败')) } finally { this.loading = false; } }, base64ToFile(base64String: any, fileName: string) { const arr = base64String.split(','); const mime = arr[0].match(/:(.*?);/)[1]; const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], fileName, { type: mime }); }
搞定,拿到url。
成功上传。