uniapp实现签名板效果

本插件是基于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>

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BUG_Jia

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

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

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

打赏作者

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

抵扣说明:

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

余额充值