uniapp 使用canvas实现签字功能(兼容h5,app,小程序)

uniapp 使用canvas实现签字功能(兼容h5,app,小程序)


前言

一套代码实现兼容性,主要的区别在于拿到图片地址之后,如何转成base64给后端。


提示:以下是本篇文章正文内容,下面案例可供参考

html
<template>
	<view class="signa">
		<view class="btn">
			<view class="hand-title">手写签名</view>
			<view @click="clear" class="rewrite-btn">重写</view>
			<view @click="save" class="save-btn">使用</view>
		</view>
		<view class="canvas-wrap">
			<canvas class="canvas" disable-scroll="true" canvas-id="canvasId" @touchstart="starts" @touchmove="moves" @touchend="end"></canvas>
		</view>
		<Message ref="Message"></Message>
	</view>
</template>
css

根据自己的需求调整样式和html,主要代码在js上

<style scoped lang="scss">
	.signa {
    
    
		position: relative;
		overflow: hidden;
		height: 100vh;
		width: 100vw;
		z-index: 1;
		.canvas-wrap {
    
    
			display: flex;
			justify-content: center;
			align-items: center;
			width: calc(100vw - 180rpx);
			height: 100vh;
		}
		.canvas {
    
    
			width: 100%;
			height: 100vh;
			background-color: #f4f8fb;
			position: absolute;
			z-index: 9999;
		}
		.btn {
    
    
			width: 160rpx;
			right: 0;
			position: fixed;
			font-size: 40rpx;
			.cancel-btn {
    
    
				position: fixed;
				top: 30rpx;
				right: 0;
				color: $uni-text-color-blue;
				transform: rotate(90deg);
			}
			.hand-title {
    
    
				position: fixed;
				top: 45%;
				right: -40rpx;
				transform: rotate(90deg);
			}
			.rewrite-btn {
    
    
				position: fixed;
				top: 80%;
				right: 0;
				color: #666666;
				font-size: 36rpx;
				transform: rotate(90deg);
			}
			.save-btn {
    
    
				position: fixed;
				bottom: 60rpx;
				right: -10rpx;
				padding: 0 10rpx;
				color: #fff;
				background: #f43e3c;
				border-radius: 7rpx;
				transform: rotate(90deg);
				font-size: 36rpx;
			}
		}
	}
</style>
js

使用 // #ifdef MP-WEIXIN || APP-PLUS|| H5 // #endif 来实现当前处于哪个端,走什么方法

<script>
	/*
	 *	已兼容h5,小程序端,app端 
	 */
	import boboMessage from "@/landlord/signContract/components/bobo-message/bobo-message.vue";
	export default {
    
    
		data() {
    
    
			return {
    
    
				dom: null,
				line: [],
				radius: 0,
				isMove: false,
				main: {
    
    },
				pdfURl: '',
				showCanvas: false,
				ctx: '', //绘图图像
				points: [], //路径点集合 
				signature: '',
				content: '',
				base64: '',
				sureForm: {
    
    } //上一页带过来的数据
			};
		},
		components: {
    
    
			Message: boboMessage,
		},
		created() {
    
    
			this.dom = uni.createCanvasContext("canvasId", this);
		},
		onLoad: function(options) {
    
    
			//接收上一页的数据
			let item = JSON.parse(options.tranform)
			this.sureForm = item
		},
		methods: {
    
    
			end(e) {
    
    },
			distance(a, b) {
    
    
				let x = b.x - a.x;
				let y = b.y - a.y;
				return Math.sqrt(x * x + y * y);
			},
			starts(e) {
    
    
				this.line.push({
    
    
					points: [{
    
    
						time: new Date().getTime(),
						x: e.touches[0].x,
						y: e.touches[0].y,
						dis: 0,
					}, ],
				});
				let currentPoint = {
    
    
					x: e.touches[0].x,
					y: e.touches[0].y,
				};
				this.currentPoint = currentPoint;
				this.drawer(this.line[this.line.length - 1]);
			},
			moves(e) {
    
    
				this.isMove = true;
				let point = {
    
    
					x: e.touches[0].x,
					y: e.touches[0].y,
				};
				(this.lastPoint = this.currentPoint), (this.currentPoint = point);
				this.line[this.line.length - 1].points.push({
    
    
					time: new Date().getTime(),
					x: e.touches[0].x,
					y: e.touches[0].y,
					dis: this.distance(this.currentPoint, this.lastPoint),
				});
				this.drawer(this.line[this.line.length - 1]);
			},
			drawer(item) {
    
    
				let x1,
					x2,
					y1,
					y2,
					len,
					radius,
					r,
					cx,
					cy,
					t = 0.5,
					x,
					y;
				var time = 0;
				if (item.points.length > 2) {
    
    
					let lines = item.points[item.points.length - 3];
					let line = item.points[item.points.length - 2];
					let end = item.points[item.points.length - 1];
					x = line.x;
					y = line.y;
					x1 = lines.x;
					y1 = lines.y;
					x2 = end.x;
					y2 = end.y;
					var dis = 0;
					time = line.time - lines.time + (end.time - line.time);
					dis = line.dis + lines.dis + end.dis;
					var dom = this.dom;
					var or = Math.min(
						(time / dis) * this.linePressure + this.lineMin,
						this.lineMax
					);
					cx =
						(x - Math.pow(1 - t, 2) * x1 - Math.pow(t, 2) * x2) /
						(2 * t * (1 - t));
					cy =
						(y - Math.pow(1 - t, 2) * y1 - Math.pow(t, 2) * y2) /
						(2 * t * (1 - t));
					dom.setLineCap("round");
					dom.beginPath();
					dom.setStrokeStyle("black");
					dom.setLineWidth(5);
					dom.moveTo(x1, y1);
					dom.quadraticCurveTo(cx, cy, x2, y2);

					dom.stroke();
					dom.draw(true);
				}
			},
			clear() {
    
    
				this.dom.clearRect(0, 0, 1000, 1000);
				this.dom.draw();
				this.isMove = false;
			},
			
			// 以上方法可拿去直接用,接下来是重点
			
			save() {
    
    
				uni.showLoading({
    
    
					title: "加载中",
					mask: true
				});
				if (!this.isMove) return this.$refs.Message.error("尚未进行签名!");
				// 小程序拿到图片转base64方法
				// #ifdef MP-WEIXIN
				uni.canvasToTempFilePath({
    
    
					canvasId: "canvasId",
					fileType: 'png',
					quality: 1, //图片质量
					success: (res) => {
    
    
						var baseAddress;
						uni.getFileSystemManager().readFile({
    
    
							filePath: res.tempFilePath, //选择图片返回的相对路径
							encoding: 'base64', //编码格式
							success: res => {
    
    
								// 成功的回调
								this.baseAddress = 'data:image/jpeg;base64,' + res.data
								// ... 后端接口的地方
							}
						})
					}
				});
				// #endif
				// h5的方法
				// #ifdef H5
				uni.canvasToTempFilePath({
    
    
					canvasId: "canvasId",
					fileType: 'png',
					quality: 1, //图片质量
					success: (res) => {
    
    
						var baseAddress;
						uni.request({
    
    
							url: res.tempFilePath,
							method:'GET',
							responseType:'arraybuffer',
							success: ress => {
    
    
								// 成功的回调
								this.baseAddress = 'data:image/jpeg;base64,' + uni.arrayBufferToBase64(ress.data)
								// ... 后端接口的地方
							}
						})
						
					}
				});
				// #endif
				// app的方法
				// #ifdef APP-PLUS
				uni.canvasToTempFilePath({
    
    
					canvasId: 'canvasId',
					success: function(res) {
    
    
						var path = res.tempFilePath;
						var base64;
						return new Promise((resolve, reject) => {
    
    
							plus.io.resolveLocalFileSystemURL(path, function(entry) {
    
    
								entry.file(function(file) {
    
    
									var AppReader = new plus.io.FileReader();
									AppReader.onloadend = function(e) {
    
    
										that.base64 = e.target.result
										// 拿到bade64调接口
										that.saveForm(that.base64)
										resolve(base64.split(",")[1])
									};
									AppReader.onerror = function(err) {
    
    
										reject(err)
									};
									AppReader.readAsDataURL(file);
								}, function(e) {
    
    
									reject(e)

								});
						 });
						})
					}
				})
				// #endif
			},
			// #ifdef APP-PLUS
			saveForm(val) {
    
    
				let params = {
    
    
					
				}
				*****(params).then(req => {
    
    
					if (req.data.code == 0) {
    
    
						this.$u.toast(req.data.message)
						uni.navigateBack({
    
    
							delta:2
						})
					} else {
    
    
						this.$u.toast(res.data.message);
					}
				})
			}
			// #endif
		}
	};
</script>

效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_56144469/article/details/128232052