Files
ylst-pc/src/components/VueSignature.vue
2022-10-14 22:04:16 +08:00

274 lines
8.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<canvas class="canvas" id="canvas" ref="canvas" v-bind="$attrs"></canvas>
</template>
<script>
import SignaturePad from 'signature_pad';
import { onMounted, ref } from '@vue/runtime-core';
import common from '@/api/common.js';
import { useRoute } from 'vue-router';
import { message } from 'ant-design-vue';
import { date } from 'is-type-of';
export default {
props: {
url: {
type: String,
default: () => ''
},
disabled: {
type: Boolean,
default: () => false
}
},
setup(props, content) {
// // 以数据 URL 的形式返回签名图像(请参阅 https://mdn.io/todataurl 了解可能的参数列表)
// signaturePad.toDataURL(); // save image as PNG
// signaturePad.toDataURL("image/jpeg"); // save image as JPEG
// signaturePad.toDataURL("image/svg+xml"); // save image as SVG
// // 从数据 URL 中绘制签名图像。
// // 注意:此方法不会填充表示绘制签名的内部数据结构。因此,使用#fromDataURL 后,#toData 将无法正常工作。
// signaturePad.fromDataURL("data:image/png;base64,iVBORw0K...");
// // 以点组数组的形式返回签名图像
// const data = signaturePad.toData();
// // 从点组数组中绘制签名图像
// signaturePad.fromData(data);
// // 从点组数组中绘制签名图像,而不清除现有图像(如果未提供,则清除默认为 true
// signaturePad.fromData(data, { clear: false });
// // 清除画布
// signaturePad.clear();
// // 如果 canvas 为空,则返回 true否则返回 false
// signaturePad.isEmpty();
// // 取消绑定所有事件处理程序
// signaturePad.off();
// // 重新绑定所有事件处理程序
const canvas = ref();
const signaturePad = ref();
const isErase = ref(false);
const imgList = ref([]);
const isSave = ref(false);
const options = ref();
const route = useRoute();
//用于画完图后的显示在抬起时添加来自于allPoints的所有点的数据
// const List<List> allList = new ArrayList<>();
onMounted(() => {
if (props.url) {
let image = new Image();
//解决跨域问题
image.crossOrigin = '*';
image.src = props.url + '?v=' + Math.random();
image.onload = () => {
var canvas = document.createElement('canvas');
canvas.width = 316;
canvas.height = 191;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0, 316, 191, 0, 0, 316, 191);
var quality = 1;
//这里的dataurl就是base64类型
var dataURL = canvas.toDataURL('image/jpg', quality); //使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png因为压缩成png后base64的字符串可能比不转换前的长
signaturePad.value.fromDataURL(dataURL);
if (props.disabled) {
signaturePad.value.off();
}
};
}
// dotSize default = (minWidth + maxWidth/2)
// //number或函数(取返回值),作用为点击画布的时候,绘制一个半径为dotSize的圆
// //注意事项,从input 获取的值为string,而dotSize 为数值,如果通过input设置画笔大小,需要转number,不然就成了字符串拼接,就会出现超级大的点.
// minWidth default 0.5
// number画笔的笔锋
// maxWidth default 2.5
// number画笔的粗细
// throttle default 16
// number每秒绘制的次数,越大越耗性能,越细腻
// backgroundColor default null
// 画布背景色,可以为 green 字符串,#FFFFFF rgb(0,0,0)格式
// penColor default #000000
// 画笔颜色,可以为 green 字符串,#FFFFFF rgb(0,0,0)格式
// velocityFilterWeight default 0.7
// number 用于根据先前的速度修改新速度的重量
// onBegin
// 回调函数,落笔时候的回调
// onEnd
// 回调函数,收笔时候的回调
// const aa = new SignaturePad(canvas.value, {
// minWidth: 1,
// maxWidth: 1,
// onBegin: function() {
// console.log('sss')
// }
// });
signaturePad.value = new SignaturePad(canvas.value, {
minWidth: 2,
maxWidth: 2,
backgroundColor: '#fafafa'
});
signaturePad.value.width = 318;
signaturePad.value.height = 192;
signaturePad.value.addEventListener('beginStroke', (e) => {
content.emit('begin', e);
});
signaturePad.value.addEventListener('endStroke', (e) => {
content.emit('end', e);
console.log('end', e, signaturePad.value.toData());
});
if (props.disabled) {
signaturePad.value.off();
}
});
const base64ToFile = (dataUrl, name) => {
var arr = dataUrl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], name + '.jpg', { type: 'image/jpg' });
};
//保存
const save = async () => {
if (signaturePad.value.isEmpty()) {
message.error('签名不能为空');
return;
}
let base64 = signaturePad.value.toDataURL();
let file = base64ToFile(base64, new Date().getTime());
const data = await common.cosUpload(file, file.name, '', () => {});
console.log(route.query.sn, file, data);
return data.url;
};
//清除
const clear = () => {
signaturePad.value.clear();
// setTimeout(() => {
// isErase.value = isErase2;
// erase();
// });
setTimeout(() => {
var ctx = canvas.value.getContext('2d');
ctx.globalCompositeOperation = 'source-over';
if (isErase.value) {
signaturePad.value.minWidth = 18;
signaturePad.value.maxWidth = 212;
signaturePad.value.penColor = '#fafafa';
signaturePad.value.velocityFilterWeight =
signaturePad.value.velocityFilterWeight + 0.1;
} else {
signaturePad.value.minWidth = 2;
signaturePad.value.maxWidth = 2;
signaturePad.value.penColor = '#000000';
signaturePad.value.velocityFilterWeight =
signaturePad.value.velocityFilterWeight + 0.1;
}
}, 100);
};
//撤回
const revoke = () => {
signaturePad.value.minWidth = 18;
signaturePad.value.maxWidth = 18;
const data = signaturePad.value.toData();
const newData = data.slice(0, data.length - 1);
signaturePad.value.fromData(newData, {
clear: true
});
// newData.forEach(async (s) => {
// await setTimeout(() => {
// signaturePad.value.fromData([s], {
// clear: false
// });
// });
// });
console.log(newData);
// console.log(newData);
// data = newData;
// signaturePad.value.fromData(newData, {
// clear: false
// });
setTimeout(() => {
var ctx = canvas.value.getContext('2d');
ctx.globalCompositeOperation = 'source-over';
if (isErase.value) {
signaturePad.value.minWidth = 18;
signaturePad.value.maxWidth = 18;
signaturePad.value.penColor = '#fafafa';
// ctx.globalCompositeOperation = 'destination-out';
} else {
signaturePad.value.minWidth = 2;
signaturePad.value.maxWidth = 2;
signaturePad.value.penColor = '#000000';
// ctx.globalCompositeOperation = 'source-over';
}
}, 100);
};
//擦除
const erase = () => {
console.log(isErase.value);
var ctx = canvas.value.getContext('2d');
ctx.globalCompositeOperation = 'source-over';
if (!isErase.value) {
signaturePad.value.minWidth = 18;
signaturePad.value.maxWidth = 18;
signaturePad.value.penColor = '#fafafa';
//ctx.globalCompositeOperation = 'destination-out';
isErase.value = true;
} else {
signaturePad.value.minWidth = 2;
signaturePad.value.maxWidth = 2;
signaturePad.value.penColor = '#000000';
isErase.value = false;
}
return isErase;
};
const onMousedown = (e) => {
console.log(e);
if (!isSave.value) {
isSave.value = true;
}
};
const onMouseleave = (e) => {
if (!isSave.value) {
isSave.value = false;
imgList.value.push(save());
}
};
const onMouserup = (e) => {
if (!isSave.value) {
isSave.value = false;
imgList.value.push(save());
}
};
return {
canvas,
signaturePad,
erase,
revoke,
clear,
save,
onMousedown,
onMouseleave,
onMouserup,
options
};
}
};
</script>
<style>
.canvas {
background: rgba(0, 0, 0, 0.02);
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.15);
}
</style>