原理
实现在线签名功能,主要是依托canvas技术。
首先生成画布、初始画笔对象,然后为画布添加touch事件监听,通过事件触发绘制文字。保存时通过canvas的toDataURL方法生成base64图片文件进行下一步操作。
基于vue的demo实现
<template>
<div class="page-content">
<header title="用户需求签名">
<button slot="right" @click="handelClearEl()" type="danger">清除</button>
<button slot="right" @click="saveImage()" type="danger">保存</button>
</header>
<div class="sign-content">
<div class="div_canvas_container">
<canvas id="signCanvas"></canvas>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
body {
position: initial;
height: auto;
}
.div_canvas_container {
width: 100vw;
height: 80vh;
overflow: hidden;
}
#signCanvas {
width: 100%;
height: 100%;
background: #fff;
border: none;
box-sizing: border-box;
overflow: hidden;
}
</style>
<script>
export default {
//数字签名
name: 'digitaSign',
data() {
return {
imgsrc: '',
}
},
mounted() {
let vm = this
vm.digitaSignType = vm.$route.query.type
this.$nextTick(() => {
setTimeout(() => {
vm.initCanvas()
}, 100)
})
},
methods: {
initCanvas() {
let rate = 1
let oCanvas = document.getElementById('signCanvas')
oCanvas.width = oCanvas.offsetWidth * rate
oCanvas.height = oCanvas.offsetHeight * rate
let cxt = oCanvas.getContext('2d')
cxt.fillStyle = '#fff'
cxt.fillRect(0, 0, oCanvas.width, oCanvas.height)
cxt.lineWidth = 2 * rate
cxt.strokeStyle = '#101010'
let posX = 0 //x坐标
let posY = 0 //y坐标
let position = null
let parentPosintin = oCanvas.getBoundingClientRect()
//手指触摸屏幕可记录此时的位置作为起点
oCanvas.addEventListener('touchstart', function (event) {
posX = event.changedTouches[0].clientX
posY = event.changedTouches[0].clientY - parentPosintin.top + 0.5
cxt.beginPath()
cxt.moveTo(posX * rate, posY * rate)
})
//手指屏滑动画线
oCanvas.addEventListener('touchmove', function (event) {
optimizedMove(event)
})
let requestAnimationFrame = window.requestAnimationFrame
let optimizedMove = requestAnimationFrame
? function (e) {
requestAnimationFrame(function () {
move(e)
})
}
: move
function move(event) {
posX = event.changedTouches[0].clientX + 0.5
posY = event.changedTouches[0].clientY - parentPosintin.top + 0.5
cxt.lineTo(posX * rate, posY * rate)
cxt.stroke()
}
},
// 清除画板
handelClearEl() {
console.log(111)
let oCanvas = document.getElementById('signCanvas')
let cxt = oCanvas.getContext('2d')
cxt.clearRect(0, 0, oCanvas.width, oCanvas.height)
},
//保存为图片
saveImage() {
let oCanvas = document.getElementById('signCanvas')
let imgBase64 = oCanvas.toDataURL()
this.imgsrc = imgBase64
console.log(imgBase64)
if (this.digitaSignType == 'partyA') {
this.$store.commit('SET_PAERT_A_IMG', imgBase64)
} else {
this.$store.commit('SET_PAERT_B_IMG', imgBase64)
}
},
},
}
</script>
在PC端运行这段代码基本上没有问题了,但在真正完成功能部署后你会发现,在微信公众号打开或是其他移动端浏览器打开时都会出现和浏览器原生滑动事件冲突的现象,例如微信公众号里写‘丨’的时候会造成浏览器页面下拉,所写笔画会出现中断,严重影响用户体验,那么你需要添加如下代码:
<script>
document.body.addEventListener('touchmove', function (e) {
e.preventDefault();
}, { passive: false });
</script>
以上代码阻止了touchmove事件的默认行为,从而防止了浏览器页面的滑动。