微信小程序canvas实现简易手写签名版(uni-app)

这篇具有很好参考价值的文章主要介绍了微信小程序canvas实现简易手写签名版(uni-app)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

微信小程序可以通过canvas实现手写签名的效果,本文中使用的是微信小程序Canvas 2D接口
本示例中绘制的是横屏签名的效果,效果图如下:
微信小程序实现手写签名,JS,微信小程序,小程序,前端
这里我们需要调整canvas的物理宽高,默认物理宽高为300*150px,物理宽高调整通过css样式即可,本文中需要根据屏幕高度进行动态调整,使用的是行内样式
页面布局:

<template>
	<view class="sign-page" :style="{paddingTop: top + 'px'}">
		<view class="canvas-box">
			<view class="left-pane">
				<view class="f28 text-gray6 left-text">请签字确认</view>
				<view class="right-box">
					<view class="left-button" @click="clearContext">
						<text class="ic ic-delete text-gray6"></text>
						<text class="f30 text-gray6 ml5">清空</text>
					</view>
					<button class="right-button" @click="confirm">完成</button>
				</view>
			</view>
			<!-- canvas的物理宽高可通过样式调整 -->
			<canvas
				class="canvas"
				disable-scroll 
				type="2d" 
				id="myCanvas"
				@touchstart="handleTouchstart"
				@touchmove="handleTouchmove"
				:style="{
					width: canvasWidth + 'px', 
					height: canvasHeight + 'px'}">
			</canvas>
			
			<view class="right-pane">
				<view class="dis-flex back-button" @click="back">
					<text class="ic ic-left text-gray6"></text>
					<text class="text-gray6 ml15">取消</text>
				</view>
				<view class="title">
					<text class="text text-gray6">{{title || '检测人员'}}</text>
				</view>
			</view>
		</view>
		<canvas
			class="canvas2"
			disable-scroll 
			type="2d" 
			id="myCanvas2"
			:style="{
				width: canvasHeight + 'px', 
				height: canvasWidth + 'px'}">
		</canvas>
	</view>
</template>

js代码:canvas的物理宽高调整后,canvas的逻辑宽高也需要进行调整,默认逻辑宽高是300*150px,(小程序Canvas 2D接口支持修改逻辑宽高),具体参考本文中的initCanvas方法


<script>
	export default {
		data() {
			return {
				canvasWidth: 300,
				canvasHeight: 150,
				top: 0,
				canvas: null,
				title: ''
			}
		},
		onLoad() {
			const menuData = uni.getMenuButtonBoundingClientRect()
			uni.getSystemInfo({
			  success: (res) => {
			    let navPadding = menuData.top - res.statusBarHeight
			    // 顶部高度 = 状态栏高度 + 胶囊按钮行高度 + 胶囊按钮上下的padding
			    let navHeight = res.statusBarHeight + navPadding * 2 + menuData.height
			    // 设置canvas的物理宽高
			    this.canvasWidth = res.windowWidth - 100
				this.canvasHeight = res.windowHeight - navHeight - 20
				this.top = navHeight
			  }
			})
		},
		onReady() {
			this.initCanvas()
		},
		methods: {
			initCanvas() {
				uni.createSelectorQuery()
					.select('#myCanvas')
					.fields({ node: true, size: true })
					.exec((res) => {
						// 修改canvas的逻辑宽高
						// 如果不修改canvas的逻辑宽高,仅通过样式修改canvas的宽高,会导致绘图时比例不对,
						// 如将物理宽度改为600,但逻辑宽度还是300,假设画图时的起点x是100,那么实际看到的绘图起点是200
						const canvas = res[0].node
						this.canvas = canvas
						this.ctx = canvas.getContext('2d')
						// canvas.width = this.canvasWidth
						// canvas.height = this.canvasHeight
						// 注意:按照上面方式调整,虽然逻辑宽高和物理宽高保持一致了,但是会发现画出来的线会有锯齿不够清晰
						// 因为不同设备上物理像素与逻辑像素是不一致的
						// 因此canvas的逻辑宽高等于物理宽高分别*dpr
						const dpr = wx.getSystemInfoSync().pixelRatio
						canvas.width = this.canvasWidth * dpr
						canvas.height = this.canvasHeight * dpr
						// 假设dpr等于2,,那么canvas的物理宽度是600,逻辑宽度就是1200,
						// 假设画图时的起点x是100,那么实际看到的绘图起点是50,此时只需要将绘图内容进行等比例放大即可
						this.ctx.scale(dpr, dpr)
					})
			},
			handleTouchstart(e) {
				this.lineBegin(e.touches[0].x, e.touches[0].y)
			},
			handleTouchmove(e) {
				this.lineTo(e.touches[0].x, e.touches[0].y)
			},
			lineBegin(x, y) {
				this.ctx.beginPath()
				// 新版Canvas 2D接口,直接修改属性即可
				this.ctx.lineCap = 'round'
				this.ctx.lineWidth = 5
				this.startX = x
				this.startY = y
				this.ctx.moveTo(this.startX, this.startY)
			},
			lineTo(x, y) {
				this.ctx.lineTo(x, y)
				this.ctx.stroke()
				this.ctx.moveTo(x, y)
			},
			clearContext() {
				this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
			},
			confirm() {
				uni.canvasToTempFilePath({
					canvas: this.canvas, 
					success: (res) => {
						this.rotateImage(res.tempFilePath)
					}
				})
			},
			// 横屏签名,但是canvas的方向是垂直的,导出的图片也是竖屏,需要将图片进行旋转
			rotateImage(filePath) {
				uni.createSelectorQuery()
					.select('#myCanvas2')
					.fields({ node: true, size: true })
					.exec((res) => {
						// 首先绘制一个宽高与上面canvas相反的canvas
						const canvas = res[0].node
						this.canvas2 = canvas
						this.ctx2 = canvas.getContext('2d')
						
						const dpr = wx.getSystemInfoSync().pixelRatio
						canvas.width = this.canvasHeight * dpr
						canvas.height = this.canvasWidth * dpr
						this.ctx2.scale(dpr, dpr)
						// 绘制上述导出的签名图片到新的canvas上
						const img = this.canvas2.createImage()
						img.src = filePath
						img.onload = () => {
							// 签名图片旋转绘画解析在下方
							this.ctx2.translate(0, this.canvasWidth);
							this.ctx2.rotate(270 * Math.PI / 180)
							this.ctx2.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight)
							
							uni.canvasToTempFilePath({
								canvas: this.canvas2, 
								success: (res) => {
									this.handleUploadFile(res.tempFilePath)
								}
							}) 
						}						
					})
			},
			handleUploadFile(filePath) {
				uni.uploadFile({
		  			url: config.requestUrl + '/biz/file/upload/annex', 
			        filePath,
	  		        name: 'file',
					header: {
						'Authorization': getToken()
					},
				  	success: (res) => {
						// 调用接口成功
						if(res.statusCode == 200) {
							// 解析服务器返回数据
							const data = JSON.parse(res.data)
							if(data.code == 200) {
								const responseUrl = config.requestUrl + data.filePath
								const eventChannel = this.getOpenerEventChannel()
								eventChannel.emit('getSignImage', {filePath: responseUrl, fileId: data.fileId});
								this.back()
							}
						} else {
							uni.hideLoading()
						}
				  },
				  fail: (res) => {
				    uni.hideLoading()
				  }
				})
			},
			back() {
				uni.navigateBack()
			}
		}
	}
</script>	

由于签名的方向是横向的,但是canvas本身是竖向,导出的签名图片也为竖向,那么我们需要将导出的图片旋转为横向后重新绘制到canvas上然后导出。签名图旋转绘制的效果图如下:

图中黑色部分为canvas区域,竖向的签名图片为刚刚我们导出的图片,绘制到canvas上的效果如下图,如果我们要将其横向绘制到面板上,此时需要将绘画内容沿左上角顺时针旋转270deg,此时可以发现旋转后图片的覆盖区域在canvas向上移动canvasWdth的位置,那么旋转前将canvas的绘画起点重置到(0,canvasWidth)即可保证绘画内容旋转后刚好覆盖在canvas上
微信小程序实现手写签名,JS,微信小程序,小程序,前端
需要注意的点是,后面绘画旋转后的canvas在实际页面中我们是不需要看到的,需要通过样式将其隐藏,如果需要使用canvasToTempFilePath方法导出图片的话,不能使用display:none的隐藏canvas,否则会报错no image found,
可以通过定位和visiblity(opacity)属性隐藏。

页面样式:文章来源地址https://www.toymoban.com/news/detail-519113.html

<style lang="scss" scoped>
	.sign-page {
		min-height: 100vh;
		background-color: #f5f5f5;
		.canvas-box {
			position: relative;
			width: 100%;
		}
		.left-pane {
			width: 100rpx;
			.left-text {
				position: absolute;
				top: 0;
				line-height: 100rpx;
				transform: translateX(100rpx) rotate(90deg) ;
				transform-origin: 0 0;
			}
			.right-box {
				position: absolute;
				display: flex;
				align-items: center;
				bottom: 0;
				transform: translateX(100rpx) rotate(90deg)  translateX(-100%) translateX(100rpx);
				transform-origin: 0 0;
				.left-button {
					line-height: 100rpx;
					margin-right: 30rpx;
				}
				.right-button {
					font-size: 30rpx;
					color: #fff;
					width: 140rpx;
					height: 60rpx;
					line-height: 60rpx;
					background-color: green;
				}
			}
		}
		
		.canvas {
			margin: 0 auto;
			background-color: #fff;
			border: 2rpx dashed #d9d9d9;
			transform-origin: center center;
		}
		.canvas2 {
		/*设置display:none会导致wx.canvasToTempFilePath报错no image found*/
			/*display: none;*/
			position: absolute;
			opacity: 0;
		}
		.right-pane {
			position: absolute;
			width: 100rpx;
			height: 100%;
			right: 0;
			top: 0;
			.back-button {
				position: relative;
				z-index: 5;
				white-space: nowrap;
				line-height: 100rpx;
				align-items: center;
				transform: translateX(100rpx) rotate(90deg);
				transform-origin: 0 0;
			}
			.title {
				position: absolute;
				top: 0;
				z-index: 4;
				width: 100rpx;
				height: 100%;
				white-space: nowrap;
				display: flex;
				justify-content: center;
				align-items: center;
				line-height: 100rpx;
				text-align: center;
				.text {
					display: inline-block;
					transform: rotate(90deg);
				}
			}
		}
	}
</style>

到了这里,关于微信小程序canvas实现简易手写签名版(uni-app)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序手写签名

    wxml js wxss 开启横屏 json

    2024年02月08日
    浏览(41)
  • uni-app微信小程序-利用canvas给图片添加水印

    选择图片 → 将图片绘制到 canvas 中并绘制水印 →将添加水印的图片绘制到 canvas 中 → 将 canvas 画布转换为图片地址 → 上传/展示操作 注意:微信小程序在选择照片或者唤起相机之前需要获取相应的 权限 利用 uni.getSetting 查看用户是否调用相机的权限(有就选择图片,没有就

    2024年02月06日
    浏览(55)
  • uni-app 微信小程序 图文生成图片 wxml-to-canvas

    在做的小程序要增加一个将文字与图片生成图片不可修改的功能,第一次做,在网上找了不少资料。参考了wxml-to-canvas | 微信开放文档  ,又看了一些相关事例,尝试写了一下。   需要准备的文件及配置项: 1、先把代码片段下载到本地 2、创建wxcomponents目录,把代码片段中的

    2024年02月09日
    浏览(46)
  • uni-app+vue2 微信小程序 使用canvas绘制折线图/波形图

      接口返回一个数组,每一项均是一个数字,代表着y坐标,x坐标需自己处理。 我的数据是1024个浮点数,在-10到10之间 波形图需要xy轴缩放功能,用c3的 transform: scale()是不行的,至少会失真。 然后背景的格子,我这里是每个格子要求100个点,初始缩放下是11个格子,10条线(

    2024年04月26日
    浏览(80)
  • 微信小程序实现canvas画圆形微信头像

    1.需要获取用户信息,拿到用户头像图片 2.实例化一个canvas对象,绘制出圆形并将头像固定到圆形中心位置 3.实现效果      

    2024年02月15日
    浏览(37)
  • 微信小程序--canvas画布实现图片的编辑

    上传图片,编辑图片大小,添加文字,改变文字颜色等 微信小程序--canvas画布实现图片的编辑 软件环境:微信开发者工具 官方下载地址:微信开发者工具下载地址与更新日志 | 微信开放文档 1、基本需求。 实现上传图片 实现图片编辑 实现添加文字 实现导出图片 2、案例目录

    2024年02月05日
    浏览(48)
  • 微信小程序使用 canvas 2d 实现签字板组件

    本文是在微信小程序中使用 canvas 2d 来实现签字板功能; 效果图: 代码: 1、wxml 2、js 3、总结 canvas 的宽度和高度可以写死,也可以根据当前可是区域动态计算;需要注意的是 res[0].node 的宽度和高度的计算是当前 canvas 元素上的宽度和高度乘设备的 pixelRatio ;

    2024年02月09日
    浏览(44)
  • uniapp写微信小程序实现电子签名

    写电子签名一定要注意的是一切全部按照手机上的适配来,为啥这么说呢,因为你在微信开发者工具中调试的时候认为是好的,正常的非常nice,当你发布版本的时候你会发现问题出来了。我下边的写法你可以直接用很简单。就是要记住canvas的几个属性和用法。 直接上干货 1.签

    2024年01月18日
    浏览(48)
  • 微信小程序实现输入内容生成二维码(canvas)

    1.封装好的QRcode的js文件 2.在我们需要使用的页面的js文件中引入该文件  效果如下:  3.首先在wxml中书写 canvas标签 4.先声明一个方法来解决中文乱码的问题 5.当我们文本域的值发生改变时,也要渲染到视图层 需求: 当我们文本框输入内容时,点击以下的生成二维码按钮,下

    2024年02月16日
    浏览(63)
  • 微信小程序canvas画图案列,实现生成头像并保存,小程序新版canvas变化,小程序中canvas注意事项

    你一定见过很多制作头像的小程序,无论是国庆的红旗,圣诞的帽子,还是疫情的口罩,都可以用小程序生成应景的头像,那么具体的代码是怎么实现的呢?前些天帮别人做了一个生成姓氏头像的功能,里面的实现原理基本一致,都是通过Canvas实现,以生成姓氏头像为例,记录一下小程序的

    2024年02月09日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包