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

Posted 瓜子三百克

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用uniapp实现微信小程序的电子签名效果相关的知识,希望对你有一定的参考价值。

✅作者简介:大家好我是瓜子三百克,励志成为全栈工程师的一枚程序猿,也是喜欢在学习和开发中记录笔记的小白博主!
📃个人主页:瓜子三百克的主页
🔥系列专栏:uniapp前端
💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博主哦🤞

让我们一起卷起来吧!!!


画布可以做很多事情,比如可以绘图,也可以做海报。在这里只是想拿它来的实现亲笔签名,开启不一样的亲笔签名姿势。

开发框架:uniapp
开发语言:vue2
展示平台:微信小程序(实际可以兼容多个平台)

标签和样式没什么好说的,这里绘制了简单的页面,见下图:

1、标签和样式

<template>
	<view class="page-content">
		<view class="form">
			<view class="form-content">
				<canvas class="form-content__canvas" canvas-id="canvas_sign" @touchstart="touchstart"
					@touchmove="touchmove" @touchend="touchend" disable-scroll="true"></canvas>
			</view>

			<view class="form-footer">
				<button class="form-footer__reset" @click="autographClick(1)">重置</button>
				<button class="form-footer__save" @click="autographClick(2)">保存</button>
				<button class="form-footer__preview" @click="autographClick(3)">预览</button>
			</view>
		</view>

	</view>
</template>


<style lang="scss" scoped>
	/*
	* 横屏后的适配方案
	* @param $rpx为需要转换的字号
	* @参考 https://blog.csdn.net/sdfsfsdscd/article/details/91375066
	**/
	@function tovmin($rpx) 
		@return #$rpx * 100 / 750vmin;
	

	.page-content 
		width: 100vw;
		height: 100vh;

		.form 
			display: flex;
			flex-direction: column;
			width: 100%;
			height: 100%;

			.form-content 
				width: 100%;
				height: 100%;

				&__canvas 
					height: calc(100vh - tovmin(20) - tovmin(120) - constant(safe-area-inset-bottom));
					height: calc(100vh - tovmin(20) - tovmin(120) - env(safe-area-inset-bottom));
					width: 100vw;
				
			

			.form-footer 
				padding-top: tovmin(20);
				height: calc(tovmin(120) + constant(safe-area-inset-bottom));
				height: calc(tovmin(120) + env(safe-area-inset-bottom));
				width: 100%;

				display: flex;
				flex-direction: row;

				background: #FFFFFF;
				box-shadow: 0 tovmin(4) tovmin(20) tovmin(2) rgba(183, 183, 183, 0.20);


				button 
					width: 20vw;

					height: tovmin(88);
					line-height: tovmin(88);
					border-radius: tovmin(48);
					text-align: center;
					font-size: tovmin(36);
					font-weight: bold;
				

				button::after 
					border: none;
				

				&__reset 
					color: #008AFE;
					border: tovmin(1) solid #008AFE;
				

				&__save 
					background-image: linear-gradient(135deg, #1BC5FF 0%, #008AFE 100%);
				

				&__preview 
					color: #008AFE;
					border: tovmin(1) solid #008AFE;
				
			
		
	
</style>

2、横屏切换

到【pages.json】文件中添加横屏切换配置
注意:不同的平台横屏切换将有所不一样。这里是针对微信小程序的横屏适配


	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		
			"path": "pages/index/index",
			"style": 
				"navigationBarTitleText": "亲笔签名",//导航栏标题
				"pageOrientation": "landscape",//切换横屏
				"enablePullDownRefresh": false,//关闭下拉刷新
				"disableScroll": true // 整体页面禁止上下滑动
			
		
	],
	"globalStyle": 
		"navigationBarTextStyle": "black",
		"navigationBarBackgroundColor": "#FFFFFF",
		"backgroundColor": "#f5f5f5",
		"navigationStyle": "default", // default/custom。custom即取消默认的原生导航栏
		"mp-alipay": 
			"transparentTitle": "always",
			"titlePenetrate": "YES"
		
	

然后是绘制逻辑处理,注意点在代码中备注:

3、绘图

3.1、初始化数据会吧?

		data() 
			return 
				canvasCtx: '', //绘图图像
				points: [], //路径点集合
				hasSign: false,
				isInit: false,
			
		,
		onLoad(query) 
			this.canvasCtx = uni.createCanvasContext('canvas_sign', this) //创建绘图对象
			//设置画笔样式
			this.canvasCtx.lineWidth = 6
			// 设置线条的端点样式
			this.canvasCtx.lineCap = 'round'
			// 设置线条的交点样式
			this.canvasCtx.lineJoin = 'round'
		,

3.2、触摸开始时获取起点,会吧?

			touchstart: function(e) 
				if (!this.isInit) 
					this.isInit = true
					this.autographClick(1);
				
				let startX = e.changedTouches[0].x
				let startY = e.changedTouches[0].y
				let startPoint = 
					X: startX,
					Y: startY
				
				this.points.push(startPoint)
				//每次触摸开始,开启新的路径
				this.canvasCtx.beginPath()
			,

3.3、触摸移动获取路径点,会吧?

			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() //绘制路径
				

			,

3.4、触摸结束,将未绘制的点清空防止对后续路径产生干扰,简单吧?

			touchend: function() 
				this.points = []
				this.canvasCtx.draw(true)
			,

3.5、绘制笔迹,没得问题吧?

这里有几个注意点:

1.为保证笔迹实时显示,必须在移动的同时绘制笔迹
2.为保证笔迹连续,每次从路径集合中区两个点作为起点(moveTo)和终点(lineTo)
3.将上一次的终点作为下一次绘制的起点(即清除第一个点)

			draw: function() 
				let point1 = this.points[0]
				let point2 = this.points[1]
				this.points.shift()
				this.canvasCtx.moveTo(point1.X, point1.Y)
				this.canvasCtx.lineTo(point2.X, point2.Y)
				this.canvasCtx.stroke()
				this.canvasCtx.draw(true)
				this.hasSign = true
			,

4、扫尾处理

上面的实现了,说明就可以签下你大名了。这里扫尾工作(按钮点击功能实现)只是景上添花。根据实际情况不一定要做。

<script>
	export default 
		methods: 
			// 底部按钮点击操作
			autographClick(type) 
				let that = this
				if (type === 1) 
					//清空画布
					this.hasSign = false
					uni.getSystemInfo(
						success: function(res) 
							let canvas = uni.createSelectorQuery().select('.form-content__canvas')
							canvas.boundingClientRect().exec(function(data) 
								console.log('canvas', data)
								console.log('canvas wh:' + data[0].width + 'X' + data[0].height)
								let canvasw = Math.ceil(data[0].width)
								let canvash = Math.ceil(data[0].height)
								that.canvasCtx.fillStyle = '#fff'
								that.canvasCtx.fillRect(0, 0, canvasw, canvash)
								that.canvasCtx.draw(true)
							)
						
					)

				 else 
					if (!this.hasSign) 
						uni.showToast(
							title: '签名不能为空',
							icon: 'none',
							duration: 2000
						)
						return
					
					uni.getSystemInfo(
						success: function(res) 
							let canvas = uni.createSelectorQuery().select('.form-content__canvas')
							canvas.boundingClientRect().exec(function(data) 
								console.log('canvas saveSign:', data[0].width + 'X' + data[0].height)
								let canvasw = Math.ceil(data[0].width)
								let canvash = Math.ceil(data[0].height)
								uni.canvasToTempFilePath(
									destWidth: canvasw,
									destHeight: canvash,
									fileType: 'jpg',
									canvasId: 'canvas_sign',
									success: function(res) 
										console.log('图片导出成功:', res)
										let path = res.tempFilePath

										// 保存图片
										if (type === 2) 
											that.uploadPic(path)
										 else if (type === 3) 
											// 预览图片
											uni.previewImage(
												urls: [path]
											)
										
									,
									fail: (err) => 
										// http://tmp/2LVQyvzddk2R820a9009dff43323d8e7fc9ef7a8d076.jpg
										console.log('图片导出失败:', err)
									
								)
							)
						
					)
				
			,

			// 图片上传处理
			uploadPic(tempFile) 
				// 1、将本地图片上传到服务器(假装是七牛云服务器)
				// 2、将七牛云返回的链接,上传到我们的服务器平台
				console.log("------:", tempFile);
				uni.showLoading(
					title: '正在上传中...'
				)
				setTimeout(() => 
					uni.showToast(
						title: '假装签名上传成功',
						duration: 2000,
						icon: 'none'
					);
				, 1000);
			
		
	
</script>

demo地址:
1、CSDN资源库地址:https://download.csdn.net/download/weixin_38633659/85343244
2、gitee地址:https://gitee.com/chenzm_186/autograph-mini.git


**🏆结束语🏆 **

🌹🌹:以上功能已全部实现,那么你想已怎么样的姿势开启你的亲笔签名模式呢?欢迎留言评论!
🌹🌹:最后如果觉得我写的文章对您有帮助的话,欢迎点赞✌,收藏✌,加关注✌哦,谢谢谢谢!!

以上是关于用uniapp实现微信小程序的电子签名效果的主要内容,如果未能解决你的问题,请参考以下文章

uniapp开发微信小程序富文本编辑器(样式仿腾讯文档)

nodejs+koa+uniapp实现微信小程序登陆获取用户手机号及openId

uni-k如何连接微信

Uniapp-微信小程序实现全局事件监听并进行数据埋点

微信小程序(或uniapp)引入腾讯视频插件播放视频

uniapp中$refs不支持(微信小程序)