目录
需求:
在指定区域可以手写签名,点击重新签名,清除手写区域
点击提交签名,将手写签名保存为一张图片上传至oss并将地址传给服务端保存
再次进入时,如果已经保存过签名,则显示上次的签名图片
效果:
template:
html
<template>
<view class="container">
<image class="sign-img" v-if="!isShowSignCanvas" :src="signUrl" mode="aspectFill"></image>
<canvas v-show="isShowSignCanvas" class="canvas" id="canvas" canvas-id="canvas" disable-scroll="true" @touchstart="canvasStart" @touchmove="canvasMove" @touchend="canvasEnd" @touchcancel="canvasEnd" @error="canvasIdErrorCallback"></canvas>
<view class="tips">请在框内签字</view>
<view class='addBtn'>
<AtButton @click="cleardraw" class="zs-btn-plain AtButton" type='primary' >重新签名</AtButton>
<AtButton @click="getImg" class="zs-btn-primary AtButton" type='primary' >提交签字</AtButton>
</view>
</view>
</template>
data:
javascript
import Taro from "@tarojs/taro";
import { ref } from "vue";
const signUrl = ref('') // 签名图片url
const isShowSignCanvas = ref(true) // 是否展示手写区域,有图片不展示,无图片展示
let isButtonDown = false;
let arrx = [];
let arry = [];
let arrz = [];
let canvasw = 0;
let canvash = 0;
let signFlag = ref(false)
let context = Taro.createCanvasContext('canvas'); // 使用 wx.createContext 获取绘图 下文 context
context.setFillStyle('#fff')
context.fillRect(0, 0, canvasw, canvash)
context.draw(true)
context.beginPath()
context.setStrokeStyle('#000000');
context.setLineWidth(4);
context.setLineCap('round');
context.setLineJoin('round');
methods:
手写绘制:
javascript
const canvasIdErrorCallback = (e) => { console.log(e) }
//开始
const canvasStart = (event) => {
isButtonDown = true;
arrz.push(0);
arrx.push(event.changedTouches[0].x);
arry.push(event.changedTouches[0].y);
}
//过程
const canvasMove = (event) => {
if (isButtonDown) {
arrz.push(1);
arrx.push(event.changedTouches[0].x);
arry.push(event.changedTouches[0].y);
};
signFlag.value = true
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.setStrokeStyle('#000000');
context.setLineWidth(4);
context.setLineCap('round');
context.setLineJoin('round');
context.stroke();
context.draw(true);
}
const canvasEnd = (event) => {
isButtonDown = false;
}
const cleardraw = () => {
isShowSignCanvas.value = true
//清除画布
arrx = [];
arry = [];
arrz = [];
context.clearRect(0, 0, canvasw, canvash);
context.draw(true);
}
图片保存:
javascript
const getImg = () => {
if (!isShowSignCanvas.value) {
Taro.navigateBack();
return false
}
if (arrx.length == 0 || !signFlag.value) {
Taro.showToast({
title: `签名内容不能为空`,
icon: 'none',
duration: 2000
})
return false
}
Taro.canvasToTempFilePath({
x: 0,
y: 0,
canvasId: 'canvas',
success(res) {
Taro.uploadFile({
url: `xxxx`,
filePath: res.tempFilePath,
name: 'file',
fileName: '签名',
success: function (ress) {
if (JSON.parse(ress.data).code == 0) {
imgUrl = JSON.parse(ress.data).data.res.url
// 图片已经上传至oss,此处是把图片地址传给服务端
} else {
Taro.showToast({
title: `上传失败,请稍后再试`,
icon: 'none',
duration: 2000
})
}
},
fail: console.error
})
}
})
}
css:
css
.container {
width: 95%;
position: absolute;
height: 95%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-sizing: border-box;
background: #fff;
border-radius: 5px;
}
.sign-img {
width: 100%;
height: 80%;
}
.canvas {
width: 100%;
height: 70%;
border: 1px dashed #aaa;
box-sizing: border-box;
}
.tips {
height: 10%;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: #aaa;
}
.addBtn {
display: flex;
align-items: center;
justify-content: center;
height: 18%;
position: fixed;
bottom: 0;
width: 100%;
background: #fff;
z-index: 100;
}
.addBtn .AtButton {
height: 80%;
font-size: 16px;
width: 40%;
}