刚刚接触小程序,因为项目需求,有签名功能研究了很久,网上也找了不少资料,最终实现了canvas签名功能,并封装成可用组件
canvas组件代码
返回
.wrapper{
position: fixed;
top:0;
bottom: 0;
right: 0;
left: 0;
box-sizing: border-box;
background-color: #fff;
}
.back{
width: 160rpx;
background: #008ef6;
margin: 20rpx;
padding: 10rpx 0;
color:#fff;
border-radius:16rpx;
text-align: center;
}
.handCenter{
box-sizing: border-box;
width: 100%;
}
canvas {
width:100%;
height: 800rpx;
margin:auto;
}
.overImg{
width: 200rpx;
height: 200rpx;
}
.handCenter {
box-sizing: border-box;
}
.handBtn {
height: 100rpx;
display: flex;
align-content: space-between;
align-items: center;
margin-top:40rpx;
}
.delBtn {
width: 40%;
color: #666;
}
.subBtn {
width: 40%;
background: #008ef6;
color: #fff;
}
button{
font-size: 28rpx;
}
// pages/component/signature/signature.js
var cxt = null;// 使用 wx.createContext 获取绘图上下文 cxt
var arrx = [];//所有点的X轴集合
var arry = [];//所有点的Y轴集合
var canvasw = 0;//画布的宽
var canvash = 0;//画布的高
// var canvasTop=0;
// var canvasLeft=0;
Component({
/**
* 组件的属性列表
*/
properties: {
can:Boolean,//用于显示隐藏canvas
},
/**
* 组件的初始数据
*/
data: {
src:""
},
/**
* 组件的方法列表
*/
methods: {
//显示隐藏组件
back(){
//子组件传递给父组件一个方法canvasDis,并传递一个参数src给父组件
this.triggerEvent("canvasDis",{src:this.data.src})
},
//创建canvas上下文
createdCanvas(){
wx.showLoading({
title: '加载中...',
mask: true
})
// 使用 wx.createContext 获取绘图上下文 cxt
//创建 canvas 的绘图上下文,因为这里是封装成组件,所有需要加this
cxt = wx.createCanvasContext('canvas',this);
cxt.beginPath();
//封装成组件,所有需要in(this),如果不加无法创建画布
var query = wx.createSelectorQuery().in(this).select('.handCenter');
query.boundingClientRect(rect => {
// canvasTop = rect.top;
// canvasLeft = rect.left;
canvasw = rect.width;
canvash = rect.height;
wx.hideLoading()
}).exec();
},
//canvas发生错误时触发
canvasIdErrorCallback(e){
console.error(e.detail.errMsg)
},
//canvas触摸开始
canvasStart(e){
arrx.push(e.changedTouches[0].x);
arry.push(e.changedTouches[0].y);
},
//canvas触摸过程中
canvasMove(e){
let len = arrx.length;
cxt.moveTo(arrx[len - 1], arry[len - 1]);//把路径移动到画布中指定的点,第一个参数为x轴,第二个参数为y轴
arrx.push(e.changedTouches[0].x);//手指移动过程中canvas的横坐标存入到全局数组变量arrx中
arry.push(e.changedTouches[0].y);//手指移动过程中canvas的纵坐标存入到全局数组变量arry中
cxt.lineTo(e.changedTouches[0].x, e.changedTouches[0].y);//moveTo坐标到lineTo坐标的
cxt.setLineWidth(4);//设置线条的宽度
cxt.setLineCap('round');//设置结束时 点的样式
cxt.stroke();//画线
cxt.draw(true);//设置为true时,会保留上一次画出的图像,false则会清空(方式二设置为false,一为true)
},
getimg() {
if (arrx.length == 0) {
wx.showModal({
title: '提示',
content: '签名内容不能为空!',
showCancel: false
});
return false;
};
wx.showLoading({
title: '签名生成中..',
mask:true
})
let that = this;
wx.canvasToTempFilePath({
canvasId: 'canvas',
success: function (res) {
that.setData({
src: res.tempFilePath
})
wx.hideLoading();
//子组件传递给父组件一个方法canvasDis,并传递一个参数src给父组件
that.triggerEvent("canvasDis",{src:res.tempFilePath})
}
},this)
},
cleardraw() {
//清除画布
arrx = [];
arry = [];
cxt.clearRect(0, 0, canvasw, canvash);
cxt.draw();
this.setData({src:''});
},
canvasEnd(e){}
},
ready(){
this.createdCanvas()
}
})
父组件调用canvas签名功能,在子组件的json文件夹中,"component": true,
父json文件中,给子组件定义一个名称,并引入路径
父中wxml中使用,因为我这里定义的名称是signature,所以可以直接signature来使用子组件
显示canvas签名功能
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
can:false,
src:"",
},
//handlChangeCanvasShow自定义事件,子组件传递过来的方法和数据
handlChangeCanvasShow(e){
//显示隐藏canvas
this.setData({
can:(!this.data.can),
src:e.detail.src
})
}
})
以上便是canvas签名功能组件的封装和使用,小程序官方文档建议使用canvas-2d,就版本的canvas已经不维护和更新了,后期有时间再补更!