uniapp 移动端canvas 签名组件

效果图

在这里插入图片描述

参数配置

参数配置

方法

方法名方法说明
confirm点击确认触发,返回canvas生成图片的图片路径
close组件关闭时触发

uniapp组件代码

<template>
	<view class="commRoot" :class="commonShow" :style="'z-index:'+zIndex+';'">

		<view class="commContentBox">
			<view class="titleBarBox ">
				<view class="w-25 d-flex justify-content-space-between">
					<view class="btn" @click="commonShow='hidden'">
						取消
					</view>
					<view class="btn" @click="clearRect()">
						清空
					</view>
				</view>
				<view class="w-50 d-flex  justify-content-center align-items-center"
					style="font-weight: bolder;font-size:40rpx;">
					{{title}}
				</view>
				<view class="w-25 d-flex justify-content-flex-end">
					<view @click="submit" class="btn" :style="{
						'background-color': confirmBtnBgColor,
						'color':confirmBtnColor 
					}">
						确定
					</view>
				</view>
			</view>
			<canvas @touchstart="canvasTouchStart" @touchmove="canvasTouchMove" @touchend="canvasTouchEnd"
				canvas-id="canvasTag" :style="{width:  canvasW+'px', height: canvasH+'px' }"></canvas>

		</view>
	</view>
</template>

<script>
	/*
	 * @ Author:  蛋炒贩炒蛋
	 * @ Des:  签名组件
	 * @ Date:  2022年10月20日15:38:40
	 */
	let ctx = null;
	let lastX, lastY; //坐标位置
	export default {
		name: "signComponentByDan",
		props: {
			zIndex: { //层级
				type: [String, Number],
				default: 10086
			},
			title: {
				type: String,
				default: "合同签名"
			},
			show: {
				type: Boolean,
				default: false
			},
			lineW: { //线宽
				type: [String, Number],
				default: 1
			},
			lineColor: { //线颜色
				type: String,
				default: "#000000"
			},
			confirmBtnBgColor: {//确认按钮背景颜色
				type: String,
				default: "#307ECE"
			},
			confirmBtnColor: {//确认按钮字体颜色
				type: String,
				default: "#fff"
			}

		},
		watch: {
			show: function(v) {
				if (v) {
					this.commonShow = "show";
				}else{
					this.commonShow = "hidden";
				
				}
			},
			commonShow:function(v){
				if(v=='hidden'){
					console.log(v)
					this.$emit('close',this.commonShow)
				}
			}
		},
		computed: {
			windowHeight: function() {
				return uni.getSystemInfoSync().windowHeight;
			},
			windowWidth: function() {
				return uni.getSystemInfoSync().windowWidth;
			},
			canvasW: function() {
				return this.windowWidth - 50
			},
			canvasH: function() {
				return this.windowHeight
			}
		},
		data() {
			return {
				commonShow: "hidden",
				drawing: false,
				haveContent: false,
				// image: ""
			};
		},
		mounted() {
			ctx = uni.createCanvasContext('canvasTag', this)

		},
		methods: {
			loadFile(url) {
				return new Promise((resolve, reject) => {
					uni.downloadFile({
						url: url, 
						header: {
							'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'
						},
						success: (res) => {
							resolve(res)
						}
					});
				})
			},
	
			submit() {
				if (this.haveContent) {
					uni.showLoading({
						title:"保存中..",
					})
					uni.canvasToTempFilePath({
						canvasId: 'canvasTag',
						success: toTempFileRes => {
							uni.hideLoading()
							console.log(toTempFileRes)
							console.log(toTempFileRes.errMsg)
							this.image = toTempFileRes.tempFilePath;
							this.commonShow="hidden";
							this.$emit('confirm',this.image)
						}
					},this)
				} else {
					uni.showToast({
						title: "请签名!",
						icon: "none"
					})
				}
			},
			// 清除画布
			clearRect() {
				this.haveContent = false;
				ctx.clearRect(0, 0, this.canvasW, this.canvasH)
				ctx.draw()
			},

			// 手指触摸
			canvasTouchStart(e) {
				let x = e.touches[0].x;
				let y = e.touches[0].y;
				this.drawLine(x, y, false)

			},
			// 手指移动
			canvasTouchMove(e) {
				let x = e.touches[0].x;
				let y = e.touches[0].y;
				this.drawLine(x, y, true)
			},
			// 手指触摸结束
			canvasTouchEnd(e) {
				let x = e.changedTouches[0].x;
				let y = e.changedTouches[0].y;
				this.drawLine(x, y, false)
			},
			drawLine(x, y, isT) {

				if (isT) {
					ctx.beginPath();
					ctx.lineWidth = this.lineW; //设置线宽状态
					ctx.strokeStyle = this.lineColor; //设置线的颜色状态
					ctx.lineCap = 'round'
					ctx.lineJoin = "round";
					ctx.moveTo(lastX, lastY);
					ctx.lineTo(x, y);
					ctx.stroke();
					ctx.closePath();
					ctx.draw(true, () => {
						this.haveContent = true;
						
					})
				}

				// 每次移动都要更新坐标位置
				lastX = x;
				lastY = y;
			}
		}
	}
</script>

<style lang="less">
	page {
		height: 100vh;
		overflow: hidden;
	}

	.commRoot {
		width: 100vw;
		height: 100vh;
		position: fixed;
		left: 0rpx;
		transition: top 0.7s;
		background-color: white;
	}

	.show {
		top: 0vh;
	}

	.hidden {
		top: -100vh;
	}

	.titleBarBox {
		width: 100vh;
		display: flex;
		box-sizing: border-box;
		border-bottom: 1rpx solid #ddd;
		justify-content: space-between;
		padding: 0rpx 30rpx;
		height: 50px;
		align-items: center;
		background-color: #fff;
		transform-origin: 50% 50%;
		transform: rotate(90deg);
		right: calc((50px - 100vh) / 2);
		position: absolute;
		top: calc((100vh - 50px) / 2);
	}

	.commContentBox {
		width: 100vh;
		height: 100vw;
		background-color: white;
	}

	.w-25 {
		width: 25%;
	}

	.w-30 {
		width: 30%;
	}

	.w-50 {
		width: 50%;
	}

	.d-flex {
		display: flex;
	}

	.justify-content-space-between {
		justify-content: space-between;
	}

	.justify-content-center {
		justify-content: center;
	}

	.justify-content-flex-end {
		justify-content: flex-end;
	}

	.align-items-center {
		align-items: center;
	}

	.btn {
		padding: 15rpx 40rpx;
		border-radius: 10rpx;
		white-space: nowrap;
		border: 1rpx solid #ddd;
	}
</style>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蛋炒贩炒蛋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值