基于 無苼 大佬的代码修改并添加了注释
- 新增hasDrawn变量,避免保存空白画布的情况。
- 默认图片保存格式从PNG改为JPG
- 将线头端点改为了圆角
小程序横屏签字板
json
{
"navigationBarTitleText": "签字板",
"pageOrientation": "landscape",
"usingComponents": {}
}
wxml
<canvas type="2d" id="canvas" disable-scroll="true" bindtouchmove="handleMove" bindtouchstart="handleStart" binderror="handleError" style="width:{{width}}px;height:{{height}}px;"></canvas>
<view class="btn">
<button class="clear" bindtap="clearClick">重签</button>
<button class="confirm" bindtap="saveClick">确认</button>
</view>
wxss
page {
background-color: #fff;
}
canvas {
border: 1px solid #00000014;
background-color: #F5F7FB;
}
.btn {
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
box-sizing: border-box;
padding-right: 30rpx;
height: 60px;
}
.btn button {
margin: 0;
border-radius: 0;
width: 85rpx;
height: 30rpx;
font-size: 13rpx;
color: #006ec7;
}
.btn .clear {
margin-right: 12rpx;
color: #3670F5;
background-color: #6795ff33;
}
.btn .confirm {
color: #fff;
background-color: #3670F5;
}
js
Page({
data: {
canvas: '', // 画布节点
ctx: null, // 画布上下文
pr: 0, // 像素比
width: 0, // 画布宽度
height: 0, // 画布高度
preX: 0, // 上一个触碰点的X坐标
preY: 0, // 上一个触碰点的Y坐标
hasDrawn: false, // 是否已经绘制过
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function () {
this.getSystemInfo(); // 获取系统信息
this.initCanvas(); // 初始化画布
},
onShow() {
this.listenToWindowResize(); // 监听窗口尺寸变化
},
// 监听窗口尺寸变化
listenToWindowResize() {
const that = this;
// 监听器,当窗口尺寸改变时更新画布尺寸并重新初始化画布
wx.onWindowResize((res) => {
const {
windowWidth,
windowHeight
} = res.size;
that.updateCanvasSize(windowWidth, windowHeight);
that.initCanvas(); // 重新初始化画布
});
},
// 获取系统信息
getSystemInfo() {
const that = this;
// 获取系统信息
wx.getSystemInfo({
success: ({
pixelRatio,
windowWidth,
windowHeight
}) => {
that.updateCanvasSize(windowWidth, windowHeight); // 更新画布尺寸
that.setData({
pr: pixelRatio // 设备像素比
});
}
});
},
// 更新画布尺寸
updateCanvasSize(width, height) {
this.setData({
width, // 窗口宽度
height: height - 60, // 窗口高度减去底部导航栏高度,
});
},
// 触摸开始事件处理
handleStart(e) {
const {
changedTouches
} = e; // 获取触控事件中的触摸点信息
if (changedTouches.length > 0) {
const touch = changedTouches[0]; // 获取第一个触摸点
this.data.ctx.beginPath(); // 开始新的路径
this.data.preX = touch.x; // 更新前一个X坐标
this.data.preY = touch.y; // 更新前一个Y坐标
this.setData({
hasDrawn: true // 设置hasDrawn为true,表示已经开始绘制
});
}
},
// 触摸移动事件处理
handleMove(e) {
const {
changedTouches
} = e; // 获取触控事件中的触摸点信息
if (changedTouches.length > 0) {
const touch = changedTouches[0]; // 获取第一个触摸点
const {
preX,
preY
} = this.data; // 获取前一个X和Y坐标
this.data.ctx.moveTo(preX, preY); // 移动到前一个坐标
this.data.ctx.lineTo(touch.x, touch.y); // 绘制一条线到当前坐标
this.data.ctx.stroke(); // 执行绘制
this.data.preX = touch.x; // 更新前一个X坐标
this.data.preY = touch.y; // 更新前一个Y坐标
}
},
// 错误处理
handleError(e) {
console.log("画布触摸错误" + e);
},
// 初始化画布
initCanvas() {
const {
width,
height,
pr
} = this.data; // 获取数据中的宽度、高度和像素比
const query = wx.createSelectorQuery().in(this); // 创建选择器查询对象
query.select('#canvas').fields({ // 选择id为canvas的元素并获取其节点和尺寸信息
node: true,
size: true
}).exec(([res]) => {
const canvas = res.node; // 获取canvas节点
const ctx = canvas.getContext('2d'); // 获取2D绘图上下文
canvas.width = width * pr; // 设置canvas宽度
canvas.height = height * pr; // 设置canvas高度
ctx.scale(pr, pr); // 根据像素比缩放绘图上下文
ctx.lineGap = 'round'; // 设置线条间隙样式为圆角
ctx.lineJoin = 'round'; // 设置连接两条线段的拐角样式为圆角
ctx.lineWidth = 4; // 设置线条宽度
ctx.font = '40px Arial'; // 设置字体样式
ctx.fillStyle = '#ecf0ef'; // 设置填充颜色
ctx.lineCap = 'round'; // 设置线条端点样式为圆角
this.setData({
ctx, // 设置绘图上下文
canvas // 设置canvas节点
});
});
},
//清除画布
clearClick() {
const {
width,
height
} = this.data; // 获取数据中的宽度和高度
this.data.ctx.clearRect(0, 0, width, height); // 清除画布上的内容
this.setData({
hasDrawn: false // 设置hasDrawn为false,表示未开始绘制
});
},
//保存图片
saveClick: function () {
// 如果尚未开始绘制
if (!this.data.hasDrawn) {
wx.showToast({
title: '请先在画布上绘制内容',
icon: 'none'
});
return; // 结束函数执行
}
// 将画布转换为临时文件
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: this.data.width,
height: this.data.height,
destWidth: this.data.width * this.data.pr,
destHeight: this.data.height * this.data.pr,
canvasId: 'canvas',
canvas: this.data.canvas,
fileType: 'jpg',
success(res) {
// 保存图片到相册
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: '保存成功',
icon: 'success'
})
}
})
}
})
},
})