canvas 制作兼容 PC 和手机端签名插件

您所在的位置:网站首页 如何在手机上签字跟手写一样 canvas 制作兼容 PC 和手机端签名插件

canvas 制作兼容 PC 和手机端签名插件

2024-07-12 23:00| 来源: 网络整理| 查看: 265

1、首先我们来了解一下 canvas 的基本使用

在 canvas 标签中间写的内容会在浏览器不兼容的情况下显示

抱歉,您的浏览器不支持canvas元素

我们先来熟悉一下本次任务中 canvas 使用的API(其他 API 可参考 https://blog.csdn.net/Insist_bin/article/details/80282043)

const canvas = document.getElementQuerySelector('canvas'); // 获取 canvas 上下文 const cxt = canvas.getContext('2d'); // 设置 canvas 颜色 cxt.strokeStyle = '#000'; // 设置 canvas 线条宽度 cxt.lineWidth = 3; // 改变线条末端线帽的样式,为每个末端添加圆形线帽,减少线条的生硬感 cxt.lineCap = 'round'; // 指定条线交汇时为圆形边角 cxt.lineJoin = 'round'; // 绘制元素阴影的功能来模糊边缘出现的锯齿 cxt.shadowBlur = 1; cxt.shadowColor = '#000'; // 清除当前路径,开始新的路径 context.beginPath(); // 设置绘制起始坐标 cxt.moveTo(10, 10); // 就是从 x = 10, y = 10 的坐标开始绘制 // 设置直线到的位置 cxt.lineTo(10, 100); // 就是从 x = 10, y = 10 绘制到 x = 10, y = 100 的一条路径 // 绘制完路径之后需要描边 cxt.stroke(); // 注意点绘制的都是路径,需要通过 stroke 描边才能显示

 使用到的事件

mousedown:PC 端鼠标按下mousemove:PC 端鼠标移动mouseup:PC 端松起鼠标touchstart:当手指触摸屏幕时候触发touchmove:当手机在滑动屏幕的时候连续触发touchend:当手指从屏幕上离开的时候触发

下面我们开始在 Vue 项目中创建 signature 组件了

整体的思路是:鼠标点下去那一刻,记录点击那点的坐标,并开始监听移动事件,每次触发移动事件的时候,获取移动的坐标,然后把起始坐标到结束坐标绘制线,接着把移动的坐标再次作为起始坐标,由于移动事件会不断的触发,不断触发移动事件就能不断绘制一点一点,最终形成路径。当鼠标松开的时候记得取消监听移动事件,不然会一直绘制下去。

抱歉,您的浏览器不支持canvas元素 确定 重写 export default { name: "signature", // 可自定义宽高 props: { height: { type: Number, default: 150 }, width: { type: Number, default: 300 } }, data() { return { canvas: null, cxt: null, // 判断当前设备是手机还是电脑 device: ('ontouchstart' in window) ? 'phone' : 'computer', // 根据设备定义不同的事件组 events: ('ontouchstart' in window) ? ['touchstart', 'touchmove', 'touchend'] : ['mousedown', 'mousemove', 'mouseup'], startX: 0, startY: 0, lineWidth: 3, isDraw: false, // 表示canvas上是否已经签过名,哪怕是一个点 drawSuc: false // 点击签名成功 }; }, mounted() { // 因为需要操作 DOM 所以初始化 canvas 需要放在 mounted 中 this.initCanvas() }, methods: { // 初始化 canvas initCanvas() { const canvas = this.$refs.canvas; canvas.width = this.width; canvas.height = this.height; this.canvas = canvas; const cxt = canvas.getContext('2d'); this.rect = canvas.getBoundingClientRect(); this.cxt = cxt; cxt.strokeStyle = '#000'; cxt.lineCap = 'round'; cxt.lineWidth = this.lineWidth; cxt.lineJoin = 'round'; cxt.shadowBlur = 1; cxt.shadowColor = '#000'; // 为 canvas 监听第一个事件 canvas.addEventListener(this.events[0], this.startEventHandler, false) }, // 传入起始点和终点绘制 drawLine(context, startX, startY, moveX, moveY) { context.beginPath(); context.moveTo(startX, startY) context.lineTo(moveX, moveY) context.stroke(); context.closePath(); }, startEventHandler(e) { // 如果已经点击确认签名了则不能修改了,除非点击重写 if (this.drawSuc) return let ev = e || event; ev.preventDefault(); // offsetX/Y 是相对于带有定位的父盒子的x,y坐标 // 因为 offsetX 和 offsetY 在火狐不兼容 // 所以使用 clientX - rect.left // clientX/Y 鼠标相对于浏览器窗口可视区域的X,Y坐标的距离 // rect.left/top 元素距离页面左边和上边的距离 this.cxt.beginPath() // 记录起始点 if (this.device === 'computer') { let rect = this.canvas.getBoundingClientRect() this.startX = ev.clientX - rect.left; this.startY = ev.clientY - rect.top; } else { const touch = e.changedTouches[0]; this.startX = touch.pageX; this.startY = touch.pageY; } this.canvas.addEventListener(this.events[1], this.moveEventHandler, false); this.isDraw = true; }, moveEventHandler(e) { let ev = e || event; let moveX; let moveY; this.cxt.beginPath() if (this.device === 'computer') { let rect = this.canvas.getBoundingClientRect() moveX = ev.clientX - rect.left; moveY = ev.clientY - rect.top; } else { const touch = e.changedTouches[0]; moveX = touch.pageX; moveY = touch.pageY; } this.drawLine(this.cxt, this.startX, this.startY, moveX, moveY); this.startX = moveX; this.startY = moveY; this.canvas.addEventListener(this.events[2], this.endEventHandler, false); }, endEventHandler() { this.cxt.closePath(); this.canvas.removeEventListener(this.events[1], this.moveEventHandler) }, //重写 overwrite() { this.cxt.clearRect(0, 0, this.width, this.height); this.isDraw = false; this.drawSuc = false }, //确认签名 surewrite() { // 确认签名后把 canvas 转换成图片 const imgBase64 = this.canvas.toDataURL(); console.log("保存签名成功" + imgBase64); this.drawSuc = true if (this.isDraw) { alert("签名成功!"); // 把图片通过回调方式返回给外部 this.$emit("surewrite", imgBase64); } else { alert("请签名后再确认!"); } } } } .canvas { border: 1px solid #000; } .signature { box-sizing: border-box; overflow: hidden; z-index: 100; display: flex; } .button-box { padding: 5px; text-align: center; display: flex; flex-direction: column; } .btnBox { display: flex; flex-direction: column; padding: 5px; text-align: center; line-height: 30px; } .button-box button { border: 1px solid dodgerblue; background: dodgerblue; color: #fff; border-radius: 4px; padding: 1px 25px; width: 80px; margin: 10px 15px; font-size: 14px; }

这张图表示的是client,screen,offset 的区别

下面是效果图



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3