Uniapp实现手写签名(兼容APP、微信小程序、H5)

<template>
	<view>
		<view class="sign-box">
			<canvas class="mycanvas" :style="{width: curWidth + 'px', height: curHeight +'rpx'}" canvas-id="mycanvas"
				@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
			</canvas>
		</view>
		<view class="sign-btn">
			<button class="btn" @click="handleReturn">撤销</button>
			<button class="btn" @click="handleReset">重写</button>
			<button class="btn" @click="handleConfirm">确认</button>
		</view>
		<image :src="failPath" mode=""></image>
	</view>
</template>

<script>
	import { pathToBase64 } from 'image-tools'
	
	export default {
		data() {
			return {
				curWidth: null,
				curHeight: 600,
				ctx: null,
				pointsList: [], // 路径点
				startPointsList: [], // 开始点
				allPointsList: [], // 所有点
				failPath: null // 文件路径
			};
		},

		onLoad() {
			this.initCanvas()
		},

		methods: {
			// 初始化
			initCanvas() {
				uni.getSystemInfo({
					success: (res) => {
						this.curWidth = res.windowWidth
					}
				})
				this.ctx = uni.createCanvasContext('mycanvas', this)
				this.ctx.lineWidth = 4 // 设置线粗细
				this.ctx.lineCap = 'round' // 设置线圆角
				this.ctx.lineJoin = 'round' // 设置线交叉处圆角
			},

			// 画线
			drawLine(startPoint, endPoint) {
				this.ctx.moveTo(startPoint.X, startPoint.Y)
				this.ctx.lineTo(endPoint.X, endPoint.Y)
				this.ctx.stroke() // 绘制轮廓线
				this.ctx.draw(true) // 将绘制的内容显示到画布
			},

			// 触摸开始
			touchstart(e) {
				const startPoint = {
					PointType: 1,
					X: e.changedTouches[0].x,
					Y: e.changedTouches[0].y
				}
				this.pointsList.unshift(startPoint)
				this.startPointsList.push(startPoint)
				this.allPointsList.push(startPoint)
				this.ctx.beginPath() // 开始画线
			},

			// 触摸移动
			touchmove(e) {
				const movePoint = {
					PointType: 2,
					X: e.changedTouches[0].x,
					Y: e.changedTouches[0].y
				}
				this.pointsList.unshift(movePoint)
				this.allPointsList.push(movePoint)
				if (this.pointsList.length >= 2) this.drawLine(this.pointsList[1], this.pointsList[0])
			},

			// 触摸结束
			touchend() {
				this.pointsList = []
			},

			// 撤销
			handleReturn() {
				// 清除画布内容
				if(!this.allPointsList.length) return 
				this.ctx.clearRect(0, 0, this.curWidth, this.curHeight)
				this.ctx.draw(true)
				this.startPointsList = []
				
				const startPointIndex = []
				this.allPointsList.forEach((item,index) => {
					if(item.PointType == 1) {
						startPointIndex.push(index)
					}
				})
				// 判断存在几条线
				if(startPointIndex.length > 1) {
					// 删除上一条线 并重新绘制剩余的线
					this.allPointsList.splice(startPointIndex[startPointIndex.length - 1])
					this.allPointsList.forEach((item,index) => {
						if(item.PointType == 1) {
							this.ctx.beginPath()
						} else {
							this.drawLine(this.allPointsList[index - 1], item)
						}
					})
				} else {
					this.allPointsList = []
				}
			},

			// 重写
			handleReset() {
				this.ctx.clearRect(0, 0, this.curWidth, this.curHeight) // 清除画布内容
				this.ctx.draw(true)
				this.startPointsList = []
				this.allPointsList = []
			},

			// 确认
			handleConfirm() {
				if (!this.allPointsList.length) return uni.showToast({
					title: '请您先签名',
					icon: 'none',
					mask: true
				})
				uni.canvasToTempFilePath({
					canvasId: 'mycanvas',
					success: (res) => {
						// WX: 临时文件 H5: base64 APP: 本地
						// #ifdef MP-WEIXIN
						// 方式1:
						const fs = uni.getFileSystemManager()
						fs.readFile({
							filePath: res.tempFilePath,
							encoding: 'base64',
							success: res => {
								this.failPath = 'data:image/png;base64,' + res.data
							}
						})
						// 方式2:
						// pathToBase64(res.tempFilePath).then(res => {
						// 	this.failPath = res
						// })
						console.log(res, 'wx');
						// #endif
						// #ifdef H5
						this.failPath = res.tempFilePath
						console.log(res, 'h5');
						// #endif
						// #ifdef APP
						pathToBase64(res.tempFilePath).then(res => {
							this.failPath = res
						})
						console.log(res, 'app');
						// #endif
					}
				})
			}
		}
	}
</script>

<style lang="scss">
	.sign-btn {
		display: flex;
		justify-content: space-between;
		margin-top: 80rpx;
	}

	.mycanvas {
		background-color: #fff; // 画布颜色
	}
</style>

uni-app微信小程序H5、支付宝小程序等统一平台)中创建手写轮播图,可以利用uni-app提供的组件库,结合自定义滚动效果实现。以下是一个简单的步骤说明: 1. 引入所需组件:首先需要引入uni-app的`swiper`组件,它自带了轮播功能,同时也支持一些基本样式定制。 ```html <view class="swiper-container"> <!-- 轮播图容器 --> </view> ``` 2. 定义样式:为了模拟手写效果,你可以通过CSS调整`swiper-item`之间的距离,使其看起来像是手动切换的。例如: ```css .swiper-container { height: 200px; /* 根据需求设置高度 */ } .swiper-item { width: 100%; transition: transform 0.3s ease; /* 添加过渡效果 */ } ``` 3. 实现手写动画:使用JavaScript监听用户的手势事件(如touchstart、touchmove、touchend),手动改变`swiper-item`的位置,模拟翻页效果。这需要借助uni-app的`pageScroll`方法和定时器。 ```javascript Page({ data: { current: 0, intervalTime: 2000 // 切换时间间隔 }, touchStart(e) { this.startY = e.touches[0].clientY; }, touchMove(e) { const curPosY = e.touches[0].clientY; if (curPosY > this.startY) { // 滑动向上 // 可以为每个item添加特定动画,然后切换到下一页 } else if (curPosY < this.startY) { // 滑动向下 // 同理,切换到上一页 } }, touchEnd() { // 结合当前滑动位置计算新的索引,更新swiper }, onReady() { this.createSwiper(); }, createSwiper() { let swiper = this.selectComponent('#swiper'); swiper.createSwiper({ ... // 设置其他swiper选项 }); } }) ``` 4. 自定义界面元素:根据设计需求,可以在每个`swiper-item`里放入你想显示的内容,比如文字、图片等。 注意:虽然这种方法能实现一定的“手写”感觉,但实际操作起来可能会比较复杂,并非真正的手写交互体验。如果你想要更接近原生的手写效果,可能需要借助第三方插件或者开发更为复杂的交互组件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值