安装 signature_pad 插件
npm install --save signature_pad
根据api文档封装一个Sign组件
<template>
<div v-safeHeaderTop class="page">
<Header :isBack="false" title="手写签名"> </Header>
<canvas ref="signaturePadCanvas" class="canvas"></canvas>
<div v-safeBottom class="button-view">
<div v-for="(x, i) in ['取消', '重写', '确认']" :key="i" class="item" @click="itemClick(i)">{{ x }}</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import SignaturePad from "signature_pad";
import { uploadFile } from "@api/home/index";
import { getToken } from "@/utils/auth";
@Component({
name: "Sign",
})
export default class Sign extends Vue {
signaturePad: any = null;
mounted() {
// 屏幕旋转
if (this.$API) {
this.$API.setScreenOrientation({
orientation: "landscape_left",
});
}
// 初始化写字板
const canvas = this.$refs.signaturePadCanvas;
this.signaturePad = new SignaturePad(canvas as any);
window.addEventListener("resize", this.resizeCanvas);
this.resizeCanvas();
}
destroyed() {
if (this.$API) {
this.$API.setScreenOrientation({
orientation: "auto",
});
}
}
itemClick(i: number) {
switch (i) {
case 0:
this.signaturePad.clear();
this.$emit("cancel");
break;
case 1:
this.signaturePad.clear();
break;
case 2:
if (this.signaturePad.isEmpty()) {
console.log("签名为空");
return;
}
var data = this.signaturePad.toDataURL();
var fd = new FormData();
var blob = this.dataURItoBlob(data);
fd.append("file", blob);
fd.append("token", getToken() || "");
this.uploadFile(fd);
break;
}
}
// 上传生成的签名图片
async uploadFile(fd: any) {
const { order_id } = this.$route.query;
const loading = this.$toast.loading("生成中...");
const { data } = await uploadFile(fd, {
params: {
ext: "png",
type: 1,
order_uid: order_id,
},
});
const url = data.file_path;
this.$emit("confirm", url);
loading.clear();
}
// base64转Blob
dataURItoBlob(dataURI: string) {
var byteString = window.atob(dataURI.split(",")[1]);
var mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0];
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: mimeString });
}
// 重置写字板
resizeCanvas() {
const canvas: any = this.$refs.signaturePadCanvas;
const ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
this.signaturePad.clear();
}
}
</script>
<style lang="scss" scoped>
.canvas {
height: calc(100% - 65px);
width: 100%;
}
.button-view {
height: 60px;
display: flex;
align-items: center;
justify-content: flex-end;
background: #fff;
.item {
padding: 6px 20px;
background: #3a5be4;
border-radius: 8px;
color: #fff;
margin-right: 10px;
}
}
</style>
页面调用即可
<van-popup v-model="show" position="right" get-container="body" :overlay="false">
<Sign @cancel="show = false" @confirm="confirm" />
</van-popup>