使用Taro小程序开发框架中的canvas组件实现电子签名功能,实现签名时屏幕自动横屏,可清空签名重签,可保存导出图片的64位码。
注意,width和height必须写着canvas的属性里边,如果使用style样式来设置宽高会造成偏移等问题,分析原因应该是属性是改变的canvas的内部宽高,style只是改变了canvas的外部样式宽高,造成canvas拉伸发生偏移。
布局部分代码:
ts代码:
onMounted(() => {
eventCenter.once((getCurrentInstanceTaro() as any).router.onReady, () => {
Taro.createSelectorQuery()
.select(".sbcanvas")
.fields(
{
node: true,
size: true,
},
function(res) {
const dpr = Taro.getSystemInfoSync().pixelRatio;
const canvas = res.node;
const ctx = canvas.getContext("2d");
ctx.strokeStyle = props.strokeStyle;
ctx.lineWidth = props.lineWidth;
canvas.width = res.width * dpr;
canvas.height = res.height * dpr;
ctx.scale(dpr, dpr);
state.canvas = canvas;
state.ctx = ctx;
state.dpr = dpr;
state.ctx.font = "10px Arial";
state.canvasWidth = canvas.width;
state.canvasHeight = canvas.height;
}
)
.exec();
Taro.createSelectorQuery()
.select(".sbcanvas")
.boundingClientRect()
.exec(res => {
state.canvasRect = res[0];
})
});
});
使用选择Tora选择器获取vanvas实例,通过scale消除锯齿
canvas.width = res.width * dpr;
canvas.height = res.height * dpr;
ctx.scale(dpr, dpr);
const startEventHandler = (event) => {
state.isButtonDown = true;
state.arrz.push(0);
state.arrx.push(event.changedTouches[0].x);
state.arry.push(event.changedTouches[0].y);
};
const moveEventHandler = (event) => {
if (state.isButtonDown) {
state.arrz.push(1);
state.arrx.push(event.changedTouches[0].x);
state.arry.push(event.changedTouches[0].y);
};
state.ctx.beginPath();
for (let i = 0; i < state.arrx.length; i++) {
if (state.arrz[i] == 0) {
state.ctx.moveTo(state.arrx[i], state.arry[i])
} else {
state.ctx.lineTo(state.arrx[i], state.arry[i])
};
};
state.ctx.stroke();//绘制已定义的路径。
};
const endEventHandler = (event) => {
state.isButtonDown = false;
};
通过touchstart,touchmove,touchend事件完成画布上写字的功能
state.ctx.moveTo() 落笔到起点、
state.ctx.lineTo()到终点划线。
state.ctx.stroke()完成绘制路径。
const signClear = () => {
state.arrx = [];
state.arry = [];
state.arrz = [];
state.ctx.clearRect(0,0,state.canvasWidth,state.canvasHeight);
};
擦除签名重签
const signOk = () => {
let image: any;
Taro.createSelectorQuery()
.select('.sbcanvas')
.fields({
node: true,
size: true,
})
.exec((res) => {
const canvas = res[0].node
image = canvas.toDataURL("image/png");
if(image){
emits('callLossSignDoc',image);
};
});
}
通过选择器获取canvas组件,然后使用toDataURL方法获取图像的base64位码。
// setTimeout(() => {
// let imgData = state.ctx.getImageData(0, 0, state.canvasWidth, state.canvasHeight);
// console.log(imgData);
// //state.ctx.putImageData(imgData,60,60);
// let newdata = imgData.data.buffer;
// console.log(newdata);
// let base64 = Taro.arrayBufferToBase64(newdata);
// console.log(base64);
// },500);
//使用Taro的api提示"canvasGetImageData: fail canvas is empty
// setTimeout(() => {
// Taro.canvasGetImageData({
// canvasId: "godCanvas",
// x: 0,
// y: 0,
// width: state.canvasWidth,
// height: state.canvasHeight,
// success(res){
// console.log(res);
// }
// }, state.canvas)
// },300);
//
// setTimeout(() => {
// Taro.canvasToTempFilePath({
// x: 0,
// y: 0,
// canvas:state.canvas,
// height:state.canvasHeight,
// canvasId: 'godCanvas',
// fileType: 'png',
// success(res) {
// console.log(res);
// let imgBase64 = Taro.getFileSystemManager().readFileSync(res.tempFilePath, 'base64');
// console.log(imgBase64);
// setTimeout(() => {
// Taro.saveImageToPhotosAlbum({
// filePath: res.tempFilePath,
// success() {
// console.log('已保存到本地相册' + res.tempFilePath);
// }
// });
// }, 300);
// }
// },state.canvas);
// },300);
尝试使用getImageData和canvasToTempFilePath图片路径方法都无法获取签名的图片。使用js原生选择器选择canvas组件,无法获取canvas实例。