uniapp实现签名板效果

本文详细介绍了如何基于zwp-draw-pad插件封装一个手绘插件,包括在模板和脚本中实现触摸事件处理、画布操作、数据管理以及插件的使用方法。在页面中引入插件并设置交互功能,如清除和保存手写内容为图片。此外,还提供了样例代码和样式以供参考。
摘要由CSDN通过智能技术生成

本插件是基于zwp-draw-pad插件来实现的

首先第一步封装插件

<template>
	<canvas canvas-id="myCanvas" disable-scroll :style="drawPadStyles" @touchstart="onTouchStart"
		@touchmove="onTouchMove" @touchend="onTouchEnd" />
</template>

<script>

	function deepClone(data) {
		return JSON.parse(JSON.stringify(data))
	}

	export default {
		props: {
			width: {
				type: Number,
				required: true
			},
			height: {
				type: Number,
				required: true
			},
			color: {
				type: String,
				default: '#000'
			},
			size: {
				type: Number,
				default: 3
			},
			disabled: {
				type: Boolean,
				default: false
			}
		},

		computed: {
			drawPadStyles({
				width,
				height
			}) {
				return `width: ${width}px;height: ${height}px`
			}
		},

		methods: {
			onTouchStart(e) {
				const {
					disabled,
					points,
					originData
				} = this
				if (disabled) return
				const {
					x,
					y
				} = e.changedTouches[0]
				points.push([x, y])
				originData.push([
					[x, y]
				])
			},
			onTouchMove(e) {
				const {
					disabled,
					points,
					originData,
					draw
				} = this
				if (disabled) return
				const {
					x,
					y
				} = e.changedTouches[0]
				points.push([x, y])
				originData[originData.length - 1].push([x, y])
				draw()
			},
			onTouchEnd() {
				this.points = []
			},
			draw() {
				const {
					ctx,
					points
				} = this
				if (points.length < 2) return
				ctx.moveTo(...points.shift())
				ctx.lineTo(...points[0])
				ctx.stroke()
				ctx.draw(true)
			},
			/**
			 * 清空画布
			 */
			init() {
				const {
					ctx,
					width,
					height
				} = this
				ctx.clearRect(0, 0, width, height)
				ctx.draw()
				this.originData = []
			},
			/**
			 * 回退到上一笔
			 */
			back() {
				const {
					originData,
					drawByData
				} = this
				originData.pop()
				drawByData(originData)
			},
			/**
			 * 根据传入的数据绘制
			 * @param {Array} data
			 */
			drawByData(data) {
				const {
					init,
					ctx
				} = this
				if (!data || !data.length) return init()
				const tempData = deepClone(data)
				while (!!tempData.length) {
					const lineData = tempData.shift()
					ctx.moveTo(...lineData.shift())
					while (!!lineData.length) ctx.lineTo(...lineData.shift())
				}
				ctx.stroke()
				ctx.draw()
			},
			/**
			 * 临时保存画布上的数据
			 * @param {Any} key 用于访问的key
			 * @param {Boolean} isInit 保存完毕后是否清空画布,默认为true
			 */
			saveCache(key, isInit = true) {
				const {
					cache,
					originData,
					init
				} = this
				const temp = deepClone(originData)
				cache.set(key, temp)
				if (isInit) init()
			},
			/**
			 * 用缓存的key恢复画布
			 * @param {Any} key 用于访问的key
			 */
			restoreCache(key) {
				const {
					drawByData,
					cache
				} = this
				this.originData = cache.get(key)
				drawByData(this.originData)
			},
			/**
			 * 清空缓存数据
			 */
			clearCache() {
				this.cache.clear()
			},
			save(options) {
				return new Promise((success, fail) => {
					const {
						width,
						height,
						canvasId
					} = this
					uni.canvasToTempFilePath({
							x: 0,
							y: 0,
							width,
							height,
							...options,
							canvasId: 'myCanvas',
							success,
							fail
						},
						this
					)
				})
			}
		},

		created() {
			const {
				color,
				size
			} = this
			const ctx = uni.createCanvasContext('myCanvas', this)
			ctx.setStrokeStyle(color)
			ctx.setLineWidth(size)
			ctx.setLineCap('round')
			ctx.setLineJoin('round')
			this.ctx = ctx
			this.points = []
			this.originData = []
			this.cache = new Map()
		}
	}
</script>

封装好插件以后我们把他放到公共文件夹

然后在需要使用的页面script引入

import QM from "@/common/qianming.vue" //具体名字,路径根据自己创建的来

然后在template标签内引入

<template>
    <view class="qmb">
		<QM ref="drawview" :width="600" :height="300" />		
		<view class="button">
			<view class="clearbtn" @click="padinit()">清除</view>
			<view class="surebtn" @click="padsave()">确定</view>
		</view>
	</view>
</template>

在method执行方法,下面列举一部分有需要可以根据自身情况来自己添加

具体用法参考清除按钮,在上面封装的文件里都有标注

// 清除按钮
padinit() {
			this.$refs.drawview.init()
			},
// 保存手写内容为图片(base64)
padsave() {
	        var that = this;
			this.$refs.drawview.save().then(res => {
			console.log('保存图片的地址', res.tempFilePath)
			},

下面是样式,根据自己需求更改

<style lang="less">
	.button {
		width: 100%;
		height: 60px;
		color: #27408B;
		position: fixed;
		bottom: 0px;
		left: 0;
	}

	.clearbtn {
		background-color: #FFFFFF;
		width: 50%;
		height: 40px;
		color: #27408B;
		float: left;
		border: 2px solid #0390ff;
		font-size: 15px;
		font-family: '黑体';
		line-height: 40px;
		text-align: center;
	}

	.surebtn {
		background-color: #0390ff;
		width: 50%;
		height: 40px;
		color: #fff;
		float: left;
		font-size: 15px;
		font-family: '黑体';
		line-height: 40px;
		text-align: center;
	}

	.clearbtn:hover {
		background-color: #D8D8D8;
	}

	.surebtn:hover {
		background-color: #D8D8D8;
	}
</style>

有不明白或者更好的建议欢迎在下方评论

uniapp签名是一个在基于微信小程序框架UniApp构建的应用组件,主要用于收集用户的电子签名。它结合了微信小程序的优点,并提供了丰富的功能,如手写识别、预览、保存以及发送等,非常适合应用于需要用户签署文件的场景。 ### 主要特点: 1. **直观的手写体验**:提供流畅的手写笔触模拟,让用户可以像在纸上书写一样自然地操作。 2. **精准的手写识别**:能够捕捉并转换成标准的字体或图片形式,便于后续处理和存储。 3. **自定义界面**:允许开发者调整颜色、大小以及其他视觉元素,以匹配应用的整体设计风格。 4. **便捷的数据导出**:支持将生成的签名以图片或特定格式数据的形式导出,便于集成到其他系统中使用。 5. **安全的存储机制**:通常会采用加密技术保护用户信息的安全,防止数据泄露。 ### 使用场景: 签名常用于各种需要电子签名的场合,比如但不限于: - 法律文件签署:合同、协议、声明等法律文档的电子签名。 - 商业交易:订单确认、发票签署、客户同意书等商业文件的电子认证。 - 教育领域:学生作业提交、家长签字等。 - 医疗健康:病历签署、患者同意书等医疗文件。 ### 实现步骤概览: 1. **引入组件库**:通过npm或Yarn等方式安装适合的签名组件库。 2. **配置环境**:初始化UniApp项目,并设置好运行环境及服务器。 3. **引入签名组件**:在页面模中添加签名组件的引用。 4. **事件绑定**:通过JavaScript监听用户在画上的操作,比如开始绘制、结束绘制或清空画布等事件。 5. **结果处理**:当用户完成签名后,获取签名结果,可以是原始图像还是经过转换的文本,然后进行下一步的操作,如保存至本地或上传至服务器。 6. **优化用户体验**:根据实际需求调整组件样式和交互流程,提升用户的操作便利性和舒适度。 ### 相关问题 - 1. 如何选择合适的签名组件库? 2. 在UniApp中如何高效地集成第三方服务以进一步利用签名数据? 3. 面对复杂的签名应用场景,如何优化签名的性能和安全性?
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BUG_Jia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值