话不多说,上代码
<view>
<view class="canvas-dia" v-if="show">
<canvas :canvas-id="canvasId" :class="['canvas-content',className]" @touchstart="touchstart"
@touchmove="touchmove" @touchend="touchend" disable-scroll="true"></canvas>
<view class="canvas-btns">
<button @click="cancleCanvas">取消</button>
<button @click="clearCanvas">清除签名</button>
<button @click="saveCanvas">保存签名</button>
</view>
</view>
</view>
props:{
canvasId:{
type:String,
default:'signature-pad'
},
className:{
type:String,
default:'canvas-box'
}
},
data(){
return{
canvasCtx: '', //绘图图像
points: [], //路径点集合
hasSign: false,
isInit: false,
show:false,
}
},
openFuc(){
let that = this;
this.show = true;
this.$nextTick(()=>{
that.initCanvas()
that.clearCanvas();
})
},
initCanvas() {
this.canvasCtx = uni.createCanvasContext(this.canvasId, this) //创建绘图对象
console.log(this.canvasCtx);
//设置画笔样式
this.canvasCtx.lineWidth = 6
// 设置线条的端点样式
this.canvasCtx.lineCap = 'round'
// 设置线条的交点样式
this.canvasCtx.lineJoin = 'round'
},
touchstart: function(e) {
if (!this.isInit) {
this.isInit = true
this.clearCanvas();
}
let startX = e.changedTouches[0].x
let startY = e.changedTouches[0].y
let startPoint = {
X: startX,
Y: startY
}
this.points.push(startPoint)
//每次触摸开始,开启新的路径
this.canvasCtx.beginPath()
},
touchmove: function(e) {
let moveX = e.changedTouches[0].x
let moveY = e.changedTouches[0].y
let movePoint = {
X: moveX,
Y: moveY
}
this.points.push(movePoint) //存点
let len = this.points.length
if (len >= 2) {
this.draw() //绘制路径
}
},
touchend: function() {
this.points = []
this.canvasCtx.draw(true)
},
draw: function() {
let point1 = this.points[0]
let point2 = this.points[1]
this.points.shift()
this.canvasCtx.moveTo(point1.X, point1.Y)
this.canvasCtx.lineTo(point2.X, point2.Y)
this.canvasCtx.stroke()
this.canvasCtx.draw(true)
this.hasSign = true
},
//清除画布
clearCanvas(){
let that = this;
//清空画布
this.hasSign = false
uni.getSystemInfo({
success: function(res) {
that.$nextTick(() => {
let canvas = uni.createSelectorQuery().in(that).select('.canvas-content')
console.log(canvas);
canvas.boundingClientRect(function(data) {
console.log('canvas', data)
console.log('canvas wh:' + data.width + 'X' + data.height)
let canvasw = Math.ceil(data.width)
let canvash = Math.ceil(data.height)
that.canvasCtx.fillStyle = '#fff'
that.canvasCtx.fillRect(0, 0, canvasw, canvash)
that.canvasCtx.draw(true)
}).exec()
})
}
})
},
//保存签名
saveCanvas(){
let that = this;
if (!this.hasSign) {
uni.showToast({
title: '签名不能为空',
icon: 'none',
duration: 2000
})
return
}
uni.getSystemInfo({
success: function(res) {
let canvas = uni.createSelectorQuery().in(that).select('.'+that.className)
canvas.boundingClientRect(function(data) {
console.log('canvas saveSign:', data.width + 'X' + data.height)
let canvasw = Math.ceil(data.width)
let canvash = Math.ceil(data.height)
uni.canvasToTempFilePath({
destWidth: canvasw,
destHeight: canvash,
fileType: 'jpg',
canvasId: that.canvasId,
success: function(res) {
console.log('图片导出成功:', res)
let path = res.tempFilePath;
that.uploadPic(path)
// 预览图片
// uni.previewImage({
// urls: [path]
// })
},
fail: (err) => {
// http://tmp/2LVQyvzddk2R820a9009dff43323d8e7fc9ef7a8d076.jpg
console.log('图片导出失败:', err)
}
},that)
}).exec()
}
})
},
// 图片上传处理
uploadPic(tempFile) {
let that = this;
// 转换文件为Base64
uni.getFileSystemManager().readFile({
filePath: tempFile,
encoding: 'base64',
success: res => {
// 成功获取Base64字符串
let base64Data = res.data;
yourApi({base64:base64Data,type:'2'}).then(r=>{
that.show = false;
that.$emit('save',r.url)
})
},
fail: err => {
// 转换失败的处理
console.error(err);
}
});
},
//取消
cancleCanvas(){
this.show = false;
this.$emit('cancle');
}
.canvas-dia{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
display: flex;
flex-direction: row;
z-index: 99999;
background-color: #ffffff;
.canvas-content{
width: 100%;
height: 100%;
background-color: #f5f5f5;
border-radius: 24rpx;
overflow: hidden;
}
.canvas-btns{
margin-top: 16rpx;
display: flex;
align-items: center;
flex-wrap: wrap;
width: 120rpx;
button{
min-width: 220rpx;
white-space: nowrap;
color: #ffffff;
background-color: #4285F4;
font-size: 28rpx;
line-height: 42rpx;
padding: 24rpx 32rpx;
border-radius: 48rpx;
transform: rotate(-90deg);
margin-left: -50rpx;
&::after{
display: none;
}
}
}
}
引用示例
<signature ref="signatureOneRef" canvasId="signature-pad" className="canvas-box" @cancle="cancleFuc" @save="saveSignSup"></signature>
//打开签名组件
signatureFuc(){
this.$refs.signatureOneRef.openFuc()
}
//取消签名
cancleFuc(){
},
//保存签名
saveSignSup(url){
this.supervisorSign = url
},