<template>
<view>
<view class="sign-box">
<canvas class="mycanvas" :style="{width: curWidth + 'px', height: curHeight +'rpx'}" canvas-id="mycanvas"
@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
</canvas>
</view>
<view class="sign-btn">
<button class="btn" @click="handleReturn">撤销</button>
<button class="btn" @click="handleReset">重写</button>
<button class="btn" @click="handleConfirm">确认</button>
</view>
<image :src="failPath" mode=""></image>
</view>
</template>
<script>
import { pathToBase64 } from 'image-tools'
export default {
data() {
return {
curWidth: null,
curHeight: 600,
ctx: null,
pointsList: [], // 路径点
startPointsList: [], // 开始点
allPointsList: [], // 所有点
failPath: null // 文件路径
};
},
onLoad() {
this.initCanvas()
},
methods: {
// 初始化
initCanvas() {
uni.getSystemInfo({
success: (res) => {
this.curWidth = res.windowWidth
}
})
this.ctx = uni.createCanvasContext('mycanvas', this)
this.ctx.lineWidth = 4 // 设置线粗细
this.ctx.lineCap = 'round' // 设置线圆角
this.ctx.lineJoin = 'round' // 设置线交叉处圆角
},
// 画线
drawLine(startPoint, endPoint) {
this.ctx.moveTo(startPoint.X, startPoint.Y)
this.ctx.lineTo(endPoint.X, endPoint.Y)
this.ctx.stroke() // 绘制轮廓线
this.ctx.draw(true) // 将绘制的内容显示到画布
},
// 触摸开始
touchstart(e) {
const startPoint = {
PointType: 1,
X: e.changedTouches[0].x,
Y: e.changedTouches[0].y
}
this.pointsList.unshift(startPoint)
this.startPointsList.push(startPoint)
this.allPointsList.push(startPoint)
this.ctx.beginPath() // 开始画线
},
// 触摸移动
touchmove(e) {
const movePoint = {
PointType: 2,
X: e.changedTouches[0].x,
Y: e.changedTouches[0].y
}
this.pointsList.unshift(movePoint)
this.allPointsList.push(movePoint)
if (this.pointsList.length >= 2) this.drawLine(this.pointsList[1], this.pointsList[0])
},
// 触摸结束
touchend() {
this.pointsList = []
},
// 撤销
handleReturn() {
// 清除画布内容
if(!this.allPointsList.length) return
this.ctx.clearRect(0, 0, this.curWidth, this.curHeight)
this.ctx.draw(true)
this.startPointsList = []
const startPointIndex = []
this.allPointsList.forEach((item,index) => {
if(item.PointType == 1) {
startPointIndex.push(index)
}
})
// 判断存在几条线
if(startPointIndex.length > 1) {
// 删除上一条线 并重新绘制剩余的线
this.allPointsList.splice(startPointIndex[startPointIndex.length - 1])
this.allPointsList.forEach((item,index) => {
if(item.PointType == 1) {
this.ctx.beginPath()
} else {
this.drawLine(this.allPointsList[index - 1], item)
}
})
} else {
this.allPointsList = []
}
},
// 重写
handleReset() {
this.ctx.clearRect(0, 0, this.curWidth, this.curHeight) // 清除画布内容
this.ctx.draw(true)
this.startPointsList = []
this.allPointsList = []
},
// 确认
handleConfirm() {
if (!this.allPointsList.length) return uni.showToast({
title: '请您先签名',
icon: 'none',
mask: true
})
uni.canvasToTempFilePath({
canvasId: 'mycanvas',
success: (res) => {
// WX: 临时文件 H5: base64 APP: 本地
// #ifdef MP-WEIXIN
// 方式1:
const fs = uni.getFileSystemManager()
fs.readFile({
filePath: res.tempFilePath,
encoding: 'base64',
success: res => {
this.failPath = 'data:image/png;base64,' + res.data
}
})
// 方式2:
// pathToBase64(res.tempFilePath).then(res => {
// this.failPath = res
// })
console.log(res, 'wx');
// #endif
// #ifdef H5
this.failPath = res.tempFilePath
console.log(res, 'h5');
// #endif
// #ifdef APP
pathToBase64(res.tempFilePath).then(res => {
this.failPath = res
})
console.log(res, 'app');
// #endif
}
})
}
}
}
</script>
<style lang="scss">
.sign-btn {
display: flex;
justify-content: space-between;
margin-top: 80rpx;
}
.mycanvas {
background-color: #fff; // 画布颜色
}
</style>
Uniapp实现手写签名(兼容APP、微信小程序、H5)
于 2024-02-29 14:39:21 首次发布