以上是效果图:
wxml:
<canvas class="canvas" id="canvas" canvas-id="canvas" disable-scroll="true" bindtouchstart="canvasStart" bindtouchmove="canvasMove" bindtouchend="canvasEnd" touchcancel="canvasEnd" binderror="canvasIdErrorCallback">
<cover-view class="controls" bindtouchstart='signature' wx:if="{{noData}}">签名栏</cover-view>
</canvas>
//这是生成整张页面的画布
<canvas canvas-id="shareCanvas" id='shareCanvas'></canvas>
wxss:
#shareCanvas{
width:100%;
height:1006rpx;
background:rgba(236, 236, 236, 1);
}
.canvas {
width: 100%;
height: 666rpx;
background:rgba(255,255,255,1);
border-radius:10rpx;
}
.controls{
width:175rpx;
font-size:60rpx;
font-family:PingFang-SC-Regular;
font-weight:400;
color:rgba(203,203,203,1);
position: relative;
top:50%;
left:50%;
transform: translate(-50%,-50%)
}
js:
var context = null;
var canvasCtx = null;
var isButtonDown = false;
var arrx = [];
var arry = [];
var arrz = [];
var canvasw = 0;
var canvash = 0;
Page({
canvasIdErrorCallback: function (e) {
console.error(e.detail.errMsg)
},
canvasStart: function (event) {
isButtonDown = true;
arrz.push(0);
arrx.push(event.changedTouches[0].x);
arry.push(event.changedTouches[0].y);
},
canvasMove: function (event) {
var that = this
that.setData({ noData:false})
if (isButtonDown) {
arrz.push(1);
arrx.push(event.changedTouches[0].x);
arry.push(event.changedTouches[0].y);
};
for (var i = 0; i < arrx.length; i++) {
if (arrz[i] == 0) {
context.moveTo(arrx[i], arry[i])
} else {
context.lineTo(arrx[i], arry[i])
};
};
context.clearRect(0, 0, 375, 333);
context.setStrokeStyle('#000000');
context.setLineWidth(4);
context.setLineCap('round');
context.setLineJoin('round');
context.stroke();
context.draw(false);
},
canvasEnd: function (event) {
isButtonDown = false;
},
//清除画布
cleardraw: function () {
let that = this;
arrx = [];
arry = [];
arrz = [];
context.draw(false);
},
onLoad: function (options) {
// 使用 wx.createContext 获取绘图上下文 context和canvasCtx
context = wx.createCanvasContext('canvas');
context.beginPath()
context.setStrokeStyle('#000000');
context.setLineWidth(4);
context.setLineCap('round');
context.setLineJoin('round');
context.setFillStyle('white');
context.draw();
canvasCtx = wx.createCanvasContext('shareCanvas');
context.draw();
},
// 点击保存签名
clickMe: function () {
let that = this;
wx.canvasToTempFilePath({
canvasId: 'canvas',
success: function (res) {
that.submitPreser(res.tempFilePath)//生成签名的临时路径
},
fail: function () {
wx.showToast({
title: '保存签名失败,请重新签名',
icon: 'none'
})
}
})
},
//保存生成临时路径后画图以便接下来的提交操作
submitPreser(resTempFilePath){
let resPhone = {};
try {
resPhone = wx.getSystemInfoSync()
} catch (e) {
resPhone = {
screenHeight: 667,
screenWidth: 375
}
}
let rpx = resPhone.screenWidth / 375; //计算不同型号手机的宽高以及位置适配
that.fillRoundRect(canvasCtx, 0, 0, 350 * rpx, 88 * rpx, 5 * rpx, '#FFFFFF', 4)
canvasCtx.setFillStyle('#333333');
canvasCtx.font = "bold 14px pingFang SC-Bold";
canvasCtx.setFontSize(14);
canvasCtx.fillText(`姓 名:${that.data.studentInfos.studentName}`, 9* rpx, 24 * rpx);
canvasCtx.drawImage(`http://xlrtimo.oss-cn-beijing.aliyuncs.com/HorseScoutData/teacher/primarySchool/${that.data.studentInfos.gender==1?'man3':'woman3'}.png`, 118 * rpx, 13.5 * rpx, 10 * rpx, 10 * rpx);
canvasCtx.fillText(`学 号:${that.data.studentInfos.registerCode}`, 9 * rpx, 51 * rpx);
canvasCtx.fillText(`班 级:${that.data.studentInfos.gradeName}${that.data.studentInfos.studentClass}班`, 9 * rpx, 75 * rpx);
that.fillRoundRect(canvasCtx, 0, 98 * rpx, 350 * rpx, 62 * rpx, 5 * rpx, '#FFFFFF', 4)
canvasCtx.font = "500 15px PingFang-SC-Medium";
canvasCtx.setFontSize(15);
canvasCtx.fillText('考试项目', 9 * rpx, 120 * rpx);
canvasCtx.setFontSize(13);
canvasCtx.setFillStyle('#8E8E8E');
canvasCtx.fillText(that.data.studentInfos.examItemName, 9 * rpx, 145 * rpx);
if (that.data.studentInfos.examUnit != '99'){
canvasCtx.fillText(that.data.studentInfos.resultValue + that.data.studentInfos.examUnit, 200 * rpx, 145 * rpx);
}
that.fillRoundRect(canvasCtx, 245 * rpx, 133.5 * rpx, 40 * rpx, 15 * rpx, 4 * rpx, '#209C7F', 4)
that.fillRoundRect(canvasCtx, 295 * rpx, 133.5 * rpx, 45 * rpx, 15 * rpx, 4 * rpx, '#CBCBCB', 4)
canvasCtx.setFillStyle('#FFFFFF');
canvasCtx.setFontSize(11);
canvasCtx.fillText(`${that.data.studentInfos.score < 100 ? ' ' +that.data.studentInfos.score :that.data.studentInfos.score}分`, 248 * rpx, 145 * rpx);
canvasCtx.fillText(`${that.data.studentInfos.scoreLevel == 1 ? ' 优秀' : that.data.studentInfos.scoreLevel == 2 ? ' 良好' : that.data.studentInfos.scoreLevel == 3 ? ' 及格' : '不及格'}`, 300 * rpx, 145 * rpx);
that.fillRoundRect(canvasCtx, 0, 170 * rpx, 350 * rpx, 333 * rpx, 5 * rpx, '#FFFFFF', 4)
canvasCtx.drawImage(resTempFilePath, 0 * rpx, 170 * rpx, 350 * rpx, 333 * rpx);
canvasCtx.draw(false,function(){
setTimeout(function () {
wx.canvasToTempFilePath({
canvasId: 'shareCanvas',
success: function (res) {
that.setData({ tempFilePath: res.tempFilePath })
arrx = [];
arry = [];
arrz = [];
context.draw(false);
that.subPreservation()
},
fail: function (data) {
wx.hideLoading()
},
})
}, 500)
});
},
//提交到后台
subPreservation: function(){
wx.uploadFile({
url: app.url + '/v1/file/upload',//服务器接口地址
header: {"token": ""},
filePath: that.data.tempFilePath,
name: 'muFiles',
formData: { 'type': 'teacher_img'},
success: function (re) {
let data = JSON.parse(re.data)
that.setData({imgUrl:data.response[0]})
},fail:function(data){
wx.showToast({
title: '提交失败,请重新签名提交',
icon:'none'
})
}
})
},
//这是绘制倒角的元素
fillRoundRect(cxt, x, y, width, height, radius, /*optional*/ fillColor, num) {
//圆的直径必然要小于矩形的宽高
if (2 * radius > width || 2 * radius > height) { return false; }
cxt.save();
cxt.translate(x, y);
//绘制圆角矩形的各个边
drawRoundRectPath(cxt, width, height, radius, num);
cxt.fillStyle = fillColor || "#000";
cxt.fill();
cxt.restore();
},
})
function drawRoundRectPath(cxt, width, height, radius, num) {
cxt.beginPath(0);
//从右下角顺时针绘制,弧度从0到1/2PI
cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
//矩形下边线
cxt.lineTo(radius, height);
//左下角圆弧,弧度从1/2PI到PI
cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
//矩形左边线
cxt.lineTo(0, radius);
//左上角圆弧,弧度从PI到3/2PI
cxt.arc(radius, num == 1 ? 0 : radius, radius, Math.PI, Math.PI * 3 / 2);
//上边线
cxt.lineTo(width - radius, 0);
//右上角圆弧
cxt.arc(width - radius, num == 1 ? 0 : radius, radius, Math.PI * 3 / 2, Math.PI * 2);
//右边线
cxt.lineTo(width, height - radius);
cxt.closePath();
}
写的比较乱,也是借鉴了网上的示例捣鼓出来的,哈哈,也算是第一次做签名功能的一次总结!不明白的地方欢迎留言,看到第一时间回复!