uniapp:手写签名,多张图合成一张图

要实现的内容:手写签名,协议内容。点击提交后:生成1张图片,有协议内容和签署日期和签署人。
实现的效果图如下:
在这里插入图片描述
在这里插入图片描述

1、签名页面

<template>
	<view class="index">
		<u-navbar title="电子协议" :is-back="false" :border-bottom="false" title-color="#333" :background="{background:''}">
		<view class="page_navbar_warp">
				<image src="../../static/icon/0.png" mode="" class="page_navbar_commonImg" @click="$go(1,1)"></image>
			</view>
		</u-navbar>
		<image src="https://www.*****/xieyi.png" mode="" class="banner"></image>
			<view class="signBox">
				<view class="title">签名区</view>
				<view style="width: 700rpx;height: 450rpx;">
					<l-signature disableScroll backgroundColor="rgba(255, 249, 238, .0)" ref="signatureRef" penColor="#333" :penSize="5" :openSmooth="true" ></l-signature>
				</view>
			</view>
		<view class="footer">
			<view class="btn1 t-c" @click="onClick('undo')">撤消</view>
			<u-button class="btn2 t-c" @click="onClick('save')" :loading="loading">提交</u-button>
		</view>
	</view>
</template>

<script>
	export default {
      
      
		data() {
      
      
			return {
      
      
				loading:false,
			}
		},
		methods:{
      
      
			onClick(type) {
      
      
				 if(type == 'openSmooth') {
      
      
					 this.openSmooth = !this.openSmooth
					 return
				 }
				if (type == 'save') {
      
      
					this.$refs.signatureRef.canvasToTempFilePath({
      
      
						success: (res) => {
      
      
							// 是否为空画板 无签名
							// 生成图片的临时路径
							// H5 生成的是base64
							let url = res.tempFilePath;
							console.log(res);
							if(res.isEmpty){
      
      
								this.$toast('请签名')
							}else{
      
      
								this.loading = true;
								this.$uploadImage('common/upload', url).then(res => {
      
      
									this.loading = false;
									if(res.code == 1){
      
      
										this.$go(2,'/pages/mine/canvas?signImg='+res.data.fullurl)
									}
								})
							}
						}
					})
					return
				}
				if (this.$refs.signatureRef) this.$refs.signatureRef[type]()
			}
		}
	}
</script>

<style scoped lang="scss">
	.index{
      
      
		min-height: 100vh;
		position: relative;
		.banner{
      
      
			display: block;
			width: 585rpx;
			height: 416rpx;
			margin: auto;
		}
		.signBox{
      
      
			border: 1rpx dashed #BF9350;
			width: 700rpx;
			height: 500rpx;
			margin: 32rpx auto;
			.title{
      
      
				padding-top: 32rpx;
				font-size: 40rpx;
				color: #BF9350;
				padding-left: 32rpx;
			}
		}
		.footer{
      
      
			position: fixed;
			left: 0;
			bottom: 0;
			width: 750rpx;
			height: 98rpx;
			background: #fff;
			box-shadow: 0rpx 3rpx 6rpx 1rpx rgba(0,0,0,0.32);
			padding: 0 50rpx;
			display: flex;
			align-items: center;
			justify-content: space-between;
			.btn1{
      
      
				width: 300rpx;
				height: 81rpx;
				border-radius: 41rpx 41rpx 41rpx 41rpx;
				border: 1rpx solid #BF9350;
				font-size: 32rpx;
				color: #BF9350;
			}
			.btn2{
      
      
				width: 300rpx;
				height: 81rpx;
				background: #BF9350;
				border-radius: 41rpx 41rpx 41rpx 41rpx;
				font-size: 32rpx;
				color: #fff;
			}
		}
	}
</style>

2、canvas页面,用来合成1张图

<template>
	<view class="demo">
		<u-navbar title="电子协议" :is-back="false" :border-bottom="false" title-color="#333" :background="{background:'#FFFAF3'}">
		<view class="page_navbar_warp">
				<image src="../../static/icon/0.png" mode="" class="page_navbar_commonImg" @click="$go(1,1)"></image>
			</view>
		</u-navbar>
		<canvas :style="{ width: canvasW + 'px', height: canvasH + 'px' }" canvas-id="myCanvas" id="myCanvas"></canvas>
		<view class="footer">
			<view class="btn1 t-c" @click="$go(1,1)">取消</view>
			<u-button class="btn2 t-c" @click="submit" :loading="loading" shape="circle" :ripple="true">提交</u-button>
		</view>
	</view>
</template>
<script>
	export default {
      
      
		components: {
      
      },
		data() {
      
      
			return {
      
      
				loading:false,
				canvasW:0, // 画布宽
				canvasH:0, // 画布高
				SystemInfo:{
      
      }, // 设备信息
				goodsImg: {
      
      }, // 协议图片
				signImg:{
      
      }, // 签名图片
				signW:120, // 签名图片大小
				bgImg:{
      
      },
				year:'',
				mon:'',
				date:'',
				tempFilePath:'',
			}
		},
		async onLoad(option) {
      
      
			var start = new Date();
			this.year = start.getFullYear();
			this.mon = start.getMonth() + 1;
			this.date = start.getDate();
			 // 获取设备信息,主要获取宽度,赋值给canvasW 也就是宽度:100%
			this.SystemInfo = await this.getSystemInfo();
			// 获取协议图片,签名二维码图片信息,APP端会返回图片的本地路径(H5端只能返回原路径)
			this.bgImg = await this.getImageInfo('https://www.*******/xieyi.png');
			this.goodsImg = await this.getImageInfo('https://www.*******/bg.png');
			this.signImg = await this.getImageInfo(option.signImg);
			this.canvasW = this.SystemInfo.windowWidth; // 画布宽度
			// #ifdef APP-PLUS
			this.canvasH = this.SystemInfo.windowHeight-94-uni.getSystemInfoSync().statusBarHeight;  // 画布高度 = 页面高度-(导航栏固定44px+footer的50px+APP内手机双跳栏的高度)
			// #endif
			// #ifdef H5
			this.canvasH = this.SystemInfo.windowHeight-94; 
			// #endif
			// 如果主图,二维码图片,设备信息都获取成功,开始绘制海报,这里需要用setTimeout延时绘制,否则可能会出现图片不显示。
			if(this.goodsImg.errMsg == 'getImageInfo:ok' && this.signImg.errMsg == 'getImageInfo:ok' && this.SystemInfo.errMsg == 'getSystemInfo:ok'){
      
      
				uni.showToast({
      
      
					icon:'loading',
					mask:true,
					duration:10000,
					title: '加载中,请稍后',
				});
				setTimeout(()=>{
      
      
					var ctx = uni.createCanvasContext('myCanvas', this);
					// 填充背景
					ctx.drawImage(this.bgImg.path, 0, 0, this.canvasW, this.canvasH) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
					
					// 绘制协议主图
					ctx.drawImage(this.goodsImg.path, 50, 60, this.canvasW-100, this.canvasW-180) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)

					// 签署日期
					ctx.setFontSize(16)
					ctx.setFillStyle('#333')
					ctx.fillText(`签署日期:${ 
        this.year}${ 
        this.mon}${ 
        this.date}`, 50, this.canvasH -this.signW-80);
					
					// 签署人
					ctx.setFontSize(14)
					ctx.setFillStyle('#333')
					ctx.fillText('签署人:', 50, this.canvasH -this.signW-40);
					// 签署人
					ctx.drawImage(this.signImg.path, 90, this.canvasH-this.signW-80, this.signW, this.signW) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度,二维码的宽,高)
					
					ctx.draw(true,(ret)=>{
      
       // draw方法 把以上内容画到 canvas 中。
						console.log(ret) 
						uni.showToast({
      
      
							icon:'success',
							mask:true,
							title: '绘制完成',
						});
						uni.canvasToTempFilePath({
      
       // 保存canvas为图片
							canvasId: 'myCanvas',
							quality: 1,
							complete: (res)=> {
      
      
								console.log(res)
								// 在H5平台下,tempFilePath 为 base64, // 图片提示跨域 H5保存base64失败,APP端正常输出临时路径
								if(res.tempFilePath){
      
      
									this.tempFilePath = res.tempFilePath;
								}
							},
						})
					});
				},1500)
			}else{
      
      
				console.log('err')
			}
		},
		methods: {
      
      
			submit(){
      
      
				this.loading = true;
				console.log('需要提交给后台的图片'this.tempFilePath)
			},
			// 获取图片信息
			getImageInfo(image) {
      
      
				return new Promise((req, rej) => {
      
      
					uni.getImageInfo({
      
      
						src: image,
						success: function(res) {
      
      
							req(res)
						},
					});
				})
			},
			
			// 获取设备信息
			getSystemInfo(){
      
      
				return new Promise((req, rej) => {
      
      
					uni.getSystemInfo({
      
      
					    success: function (res) {
      
      
					        req(res)
					    }
					});
				})
			},
		},
	}
</script>

<style scoped lang="scss">
	.footer{
      
      
		position: fixed;
		left: 0;
		bottom: 0;
		width: 750rpx;
		height: 50px;
		box-shadow: 0rpx 3rpx 6rpx 1rpx rgba(0,0,0,0.32);
		padding: 0 50rpx;
		display: flex;
		align-items: center;
		justify-content: space-between;
		background: #fff;
		.btn1{
      
      
			width: 300rpx;
			height: 40px;
			border-radius: 41rpx 41rpx 41rpx 41rpx;
			border: 1rpx solid #BF9350;
			font-size: 32rpx;
			color: #BF9350;
		}
		.btn2{
      
      
			width: 300rpx;
			height: 40px;
			background: #BF9350;
			border-radius: 41rpx 41rpx 41rpx 41rpx;
			font-size: 32rpx;
			color: #fff;
		}
	}
</style>

备注:
1、协议页面内用的l-signature来自于uniapp插件市场
2、canvas页面灵感来自于之前写过的一篇绘制海报文章
3、页面中用到的 xieyi.png(协议内容)、bg.png(底图)、以及签名后的option.signImg(签名图),都需要后台设置允许跨域。否则H5就会报错画布污染无法生成base64。
在这里插入图片描述
这个问题在APP内不存在,只有H5会出现。

猜你喜欢

转载自blog.csdn.net/qq_40745143/article/details/131957083