uniapp实现微信小程序的电子签名

news/2024/11/25 15:39:27/

签名页的效果如图下所示:

封装的组件代码如下所示:

<template><view><view class="wrapper"><view class="handBtn"><button @click="handleReset" class="delBtn">清除</button><button @click="handleSubmit" class="saveBtn">保存</button><button @click="handleBack" class="subBtn">返回</button></view><view class="handCenter"><canvas class="handWriting" :disable-scroll="true" @touchstart="touchstart" @touchmove="touchmove"@touchend="touchend" canvas-id="myCanvas" :style="{width:width +'px',height:height +'px'}"></canvas><!--用于旋转图片的canvas容器--><canvas style="position: absolute" :style="{ width: height+'px', height: width+'px' }"canvas-id="myCanvas2"></canvas></view><view class="handRight"><view class="handTitle">请签名</view></view></view></view>
</template><script>export default {data() {return {ctx: '', //绘图图像points: [], //路径点集合,width: 0, //绘图宽度height: 0, //绘图高度hasSign: false, //是否已签名isInit: false, //是否已触摸};},mounted() {const _self = this;this.ctx = uni.createCanvasContext('myCanvas', this); //创建绘图对象//设置画笔样式this.ctx.lineWidth = 4;this.ctx.lineCap = 'round';this.ctx.lineJoin = 'round';uni.getSystemInfo({success: function(res) {_self.width = res.windowWidth - 95;_self.height = res.windowHeight - 30;}});},methods: {/*** 触摸开始,获取到起点			 */touchstart: function(e) {if (!this.isInit) {this.isInit = true;this.handleReset();};let startX = e.changedTouches[0].x;let startY = e.changedTouches[0].y;let startPoint = {X: startX,Y: startY};this.points.push(startPoint);//每次触摸开始,开启新的路径this.ctx.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.ctx.draw(true);},/*** 绘制笔迹* 1.为保证笔迹实时显示,必须在移动的同时绘制笔迹* 2.为保证笔迹连续,每次从路径集合中区两个点作为起点(moveTo)和终点(lineTo)* 3.将上一次的终点作为下一次绘制的起点(即清除第一个点)*/draw: function() {let point1 = this.points[0];let point2 = this.points[1];this.points.shift();this.ctx.moveTo(point1.X, point1.Y);this.ctx.lineTo(point2.X, point2.Y);this.ctx.stroke();this.ctx.draw(true);this.hasSign = true;},//清空画布handleReset: function() {this.ctx.clearRect(0, 0, this.width, this.height);this.ctx.draw(true);this.hasSign = false;},/***保存签名*/handleSubmit() {const _self = this;if (!this.hasSign) {uni.showToast({title: '签名不能为空',icon: 'none',duration: 2000})return;}uni.canvasToTempFilePath({fileType: 'png',quality: 1, //图片质量canvasId: 'myCanvas',success(res) {uni.getImageInfo({// 获取图片的信息src: res.tempFilePath,success: (res1) => {// 将canvas1的内容复制到canvas2中let canvasContext = uni.createCanvasContext('myCanvas2', _self);canvasContext.translate(0, _self.width);canvasContext.rotate((-90 * Math.PI) / 180);canvasContext.drawImage(res.tempFilePath, 0, 0, _self.width, _self.height);canvasContext.draw(false, () => {// 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中uni.canvasToTempFilePath({// 把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。								fileType: 'png',quality: 1, //图片质量canvasId: 'myCanvas2',complete(res2) {//此处是将图片文件传给父级组件上传至后台_self.$emit("submitSignature", res2.tempFilePath);}}, _self)})}})}}, this)},//返回上级handleBack() {this.handleReset();this.$emit("close");},}};
</script><style>page {background: #fbfbfb;height: auto;overflow: hidden;}.wrapper {width: 100%;height: 95vh;margin: 15px 0;overflow: hidden;display: flex;align-content: center;flex-direction: row;justify-content: center;font-size: 28rpx;}.handWriting {background: #fff;width: 100%;height: 95vh;}.handRight {display: inline-flex;align-items: center;width: 45x;}.handCenter {border: 4rpx dashed #e9e9e9;flex: 1;overflow: hidden;box-sizing: border-box;}.handTitle {transform: rotate(90deg);flex: 1;color: #666;line-height: 100%;}.handBtn button {font-size: 28rpx;}.handBtn {height: 95vh;width: 50px;display: inline-flex;flex-direction: column;justify-content: space-between;align-content: space-between;}.delBtn {position: absolute;top: 250rpx;left: 0rpx;transform: rotate(90deg);color: #666;}.subBtn {position: absolute;bottom: 52rpx;left: -3rpx;display: inline-flex;transform: rotate(90deg);background: #008ef6;color: #fff;margin-bottom: 30rpx;text-align: center;justify-content: center;}.saveBtn {position: absolute;top: 375rpx;left: 0rpx;transform: rotate(90deg);color: #666;}
</style>

最后保存的图片是经过旋转后的。


http://www.ppmy.cn/news/83501.html

相关文章

版图设计工具解析-virtuoso的display.drf文件解析

1. display.drf文件解析 virtuoso的版图颜色定义分析 下图为virtuoso的版图颜色&#xff0c;包括填充&#xff0c;轮廓&#xff0c;彩点&#xff0c;线形 本文以smic18mmrf的display.drf文件进行解析 smic18的PDK包下存在display.drf文件 打开文件display.drf文件后看到如下…

Python学习之pygame模块介绍并制作代码雨

前言 对Python游戏有所了解的朋友都知道&#xff0c;在2D的游戏制作中&#xff0c;经常会用到一个模块pygame&#xff0c;他能帮助我们实现很多方便使用的功能&#xff0c;例如绘制窗口&#xff0c;反馈键盘鼠标信息&#xff0c;播放音频文件&#xff0c;渲染图片文字等等功能…

AI智能照片编辑:AI Photo for Mac

AI Photo是一款Mac平台上的智能照片编辑软件&#xff0c;它基于人工智能技术&#xff0c;可以帮助用户快速、轻松地对照片进行编辑和美化。AI Photo提供了多种智能修复和美化功能&#xff0c;包括自动调整色彩、对比度、亮度、清晰度等&#xff0c;使得照片的质量得到有效提升。…

「OceanBase 4.1 体验」|连续多年支撑双11的国产原生分布式数据库

目录 前言 正文 1. OceanBase 4.1发布 2.部署oceanbase 安装环境 2.1下载 all-in-one 安装包 2.2解压安装包 2.3执行安装脚本 2.4设置环境变量 2.5查看文件位置 2.6快速启动demo环境 2.7访问数据库 3.oceanbase的优点 4.oceanbase与 Oracle 兼容性 5.oceanbase与…

“小白也能玩转Python数据分析,快速掌握技巧!

最近收到好几条私信&#xff0c;想要了解数据分析方面的学习教程。 Python如今势头很猛&#xff0c;但是结合市场环境来说&#xff0c;Python开发岗位的需求还是要低于其他后端语言&#xff0c;但是Python爬虫和数据分析的技能确是实实在在可以用到很多工作中去&#xff0c;所…

亚马逊,速卖通,国际站卖家在做测评时如何将风险降到最低呢?

测评是亚马逊卖家提升产品可信度和销售表现的重要手段 现在的测评市场遭到卖家们的极力吐槽&#xff0c;想要找到靠谱的资源也越来越难。据了解&#xff0c;去年很多骗子&#xff0c;中介都涌进测评市场&#xff0c;随意报价&#xff0c;导致整个市场鱼龙混杂&#xff0c;卖家…

Scala学习(三)---函数式编程

文章目录 1.面向对象编程2. 函数式编程是什么3.函数定义4.函数参数的特殊用法5.函数至简原则6.匿名函数6.1 匿名函数化简原则 7.高阶函数7.1 函数可以作为值进行传递7.2 函数可以作为参数进行传递7.3 函数可以作为返回值进行传递7.4 柯里化写法 1.面向对象编程 Scala语言是一个…

【案例教程】R语言在生态环境领域中的实践技术应用

R语言作为新兴的统计软件&#xff0c;以开源、自由、免费等特点风靡全球。生态环境领域研究内容广泛&#xff0c;数据常多样而复杂。利用R语言进行多元统计分析&#xff0c;从复杂的现象中发现规律、探索机制正是R的优势。为此&#xff0c;本课程以鱼类、昆虫、水文、地形等多样…