canvas手写电子签名 上传服务器 下载图片
首先展示(show)一下
来啦来啦
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手写签名</title>
</head>
<body>
<!--
大白话就是canvas是一个可以在上面通过javaScript画图的标签,
通过其提供的context(上下文)及Api进行绘制,在这个过程中canvas充当画布的角色
-->
<canvas id="canvas">当前浏览器不支持此功能,请升级浏览器或更换Chrome浏览器</canvas>
<div>
<button id="cancel">取消</button>
<button id="save">保存</button>
</div>
</body>
<script>
const cbtn = document.getElementById('cancel')
const sbtn = document.getElementById('save')
/** @type {HTMLCanvasElement} */
// 获取canvas实例
const canvas = document.getElementById("canvas")
// 配置信息
const config = {
width:400,
height:200,
lineWidth:5, // 线宽
strokeStyle:'red', // 线条颜色
lineCap:'round', // 线条两端圆点
lineJoin:'round' // 线条交汇处圆角
}
canvas.width = config.width
canvas.height = config.height
canvas.style.border = '1px solid #000'
// canvas.style.backgroundColor = 'yellow'
// 创建画布
let ctx = canvas.getContext('2d')
// 可加可不加
// ctx.fillStyle = '#ededed'
// ctx.fillRect(0,0,400,200)
// 记录上一次绘制的路径结束坐标点以及偏移量,为啥需要保存偏移量呢,因为鼠标和画布上的距离是存在一定的偏移距离,在我们绘制的过程中需要减去这个偏移量,才是我们实际的绘制坐标。
// 但我发现chrome中不需要减去这个偏移量,拿到的就是实际的坐标,之前在微信小程序中使用就需要减去偏移量,需要在小程序中使用的朋友需要注意这一点哦。
let client = {
offsetX:0,
offsetY:0, // 偏移量
endX:0,
endY:0 // 坐标
}
// 判断是否为移动端
const mobileStatus = (/Mobile|Android|iPhone/i.test(navigator.userAgent))
// 鼠标按下或触摸开始的回调,主要操作为获取当前鼠标按下/触摸开始的偏移量和坐标,进行起点绘制,web端可以直接通过event中取到,而移动端则需要在event.changedTouches[0]中取到
const init = (event) => {
const { offsetX,offsetY,pageX,pageY } = mobileStatus ? event.changedTouches[0] : event
client.offsetX = offsetX
client.offsetY = offsetY
client.endX = pageX
client.endY = pageY
// 开始绘制(清除以上一次beginPath之后的所有路径,进行绘制)
ctx.beginPath()
ctx.lineWidth = config.lineWidth
ctx.strokeStyle = config.strokeStyle
ctx.lineCap = config.lineCap
ctx.lineJoin = config.lineJoin
ctx.moveTo(client.endX,client.endY)
// 同时监听鼠标或者手势的移动事件
window.addEventListener(mobileStatus ? 'touchmove' : 'mousemove',draw)
}
// 鼠标或者手势的移动的回调
const draw = (e) => {
// 获取当前坐标点位
const { pageX, pageY } = mobileStatus ? event.changedTouches[0] : event
client.endX = pageX
client.engY = pageY
ctx.lineTo(pageX,pageY)
ctx.stroke()
}
// 手势离开或者鼠标弹起(结束本次绘制)的回调
const closeDraw = () => {
// 结束绘制
ctx.closePath()
window.removeEventListener(mobileStatus ? 'touchmove' : 'mousemove',draw)
}
// 取消
const cancel = () => {
// 清除指定矩形内的像素
ctx.clearRect(0,0,config.width,config.height)
// 防止背景变白(与上文呼应)
// ctx.fillStyle = '#ededed'
// ctx.fillRect(0,0,400,200)
}
const save = () => {
console.log(canvas.toDataURL())
// 保存图片或文件的方式有很多种,但主要的有两种,一种是利用blob,另一种则是利用toDataURL,优先使用blob
canvas.toBlob( blob => {
// 获取时间转成字符串作为文件名
// 此处如需上传至服务器可将blob传给服务器,类似于e.target.files[0]
console.log(blob,'blob')
const date = Date.now().toString()
const a = document.createElement('a')
a.download = `${date}.png`
const url = URL.createObjectURL(blob)
a.href = url
a.click()
URL.revokeObjectURL(url)
a.remove()
})
}
// 初始化
window.addEventListener(mobileStatus ? 'touchstart' : 'mousedown',init)
// 结束绘制
window.addEventListener(mobileStatus ? 'touchend' : 'mouseup',closeDraw)
// 取消(清除画布)
cbtn.addEventListener('click',cancel)
// 保存图片
sbtn.addEventListener('click',save)
</script>
</html>