在这里插入图片描述

这是个页面哦。记得配置pages.json

<template>
	<view class="container">
		<view class="sigh-btns">
			<button class="btn" @tap="goBack">返 回</button>
			<button class="btn" @tap="resetWrite" :disabled="tempPoint.length===0">重 写</button>
			<button class="btn" @tap="handleConfirm" :disabled="tempPoint.length===0" type="primary"
				style="background-color: #0081ff;">确 认</button>
		</view>
		<canvas class="sign-board" canvas-id="sign-canvas" :style="{width:width +'px',height:height +'px'}"
			@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas>
	</view>
	<canvas canvas-id="board-rotate" :style="{width:height +'px',height: width+'px'}"></canvas>
</template>
<script setup lang="ts">
	/**
		 * @author        							全易
		 * @time          							2024-10-18 14:10:00
		 * @description   							签名板
		 * @param {number} = [lineWidth] https://uniapp.dcloud.net.cn/api/canvas/CanvasContext.html#canvascontextsetlinewidth
		 * @param {string} = [lineCap]   https://uniapp.dcloud.net.cn/api/canvas/CanvasContext.html#canvascontextsetlinecap
		 * @param {string} = [lineJoin]  https://uniapp.dcloud.net.cn/api/canvas/CanvasContext.html#canvascontextsetlinejoin
		 * @use													父页面这样跳:
																		uni.navigateTo({
																			url: "/components/sign-board",
																			events: {
																				emits(data) {
																					console.log("签名图片:", data)
																				}
																			}
																		})
	 */



	const ctx = ref({}) //绘图上下文
	const points = ref([]) //路径点集合
	const width = ref(0)
	const height = ref(0)
	const tempPoint = ref([]); // 存放当前画纸上的轨迹点
	const props = ref({
		lineWidth: 4,
		lineCap: 'round',
		lineJoin: 'round'
	});
	const instance = getCurrentInstance();


	onLoad((option) => {
		ctx.value = uni.createCanvasContext('sign-canvas', instance.proxy);
		setPenStyles(option);
		uni.getSystemInfo({
			success: function (res) {
				width.value = res.windowWidth * 0.8;
				height.value = res.windowHeight * 0.8;
			}
		});
	});

	// 设置画笔样式
	function setPenStyles(option) {
		for (const prop in props.value) {
			ctx.value[prop] = option[prop] || props.value[prop];
		}
	}

	// 触摸开始,获取到起点
	function touchstart(e) {
		let startX = e.changedTouches[0].x;
		let startY = e.changedTouches[0].y;
		let startPoint = {
			X: startX,
			Y: startY
		};

		/* **************************************************
				#由于uni对canvas的实现有所不同,这里需要把起点存起来
		 * **************************************************/
		points.value.push(startPoint);

		// 每次触摸开始,开启新的路径
		ctx.value.beginPath();
	}

	// 触摸移动,获取到路径点
	function touchmove(e) {
		let moveX = e.changedTouches[0].x;
		let moveY = e.changedTouches[0].y;
		let movePoint = {
			X: moveX,
			Y: moveY
		};
		points.value.push(movePoint); //存点
		let len = points.value.length;
		if (len >= 2) {
			draw(); //绘制路径
		}
		tempPoint.value.push(movePoint);
	}

	// 触摸结束,将未绘制的点清空防止对后续路径产生干扰
	function touchend() {
		points.value = [];
	}

	/* ***********************************************	
	#   绘制笔迹
	#   1.为保证笔迹实时显示,必须在移动的同时绘制笔迹
	#   2.为保证笔迹连续,每次从路径集合中区两个点作为起点(moveTo)和终点(lineTo)
	#   3.将上一次的终点作为下一次绘制的起点(即清除第一个点)
	************************************************ */
	function draw() {
		let point1 = points.value[0];
		let point2 = points.value[1];
		points.value.shift();
		ctx.value.moveTo(point1.X, point1.Y);
		ctx.value.lineTo(point2.X, point2.Y);
		ctx.value.stroke();
		ctx.value.draw(true);
	}

	function goBack() {
		uni.navigateBack();
	}

	// 清空画布
	function resetWrite() {
		ctx.value.clearRect(0, 0, width.value, height.value);
		ctx.value.draw(true);
		tempPoint.value = []
	};


	function handleConfirm() {
		if (tempPoint.value.length === 0) { return };
		uni.canvasToTempFilePath({
			canvasId: 'sign-canvas',
			success: function (res) {
				const canvasContext = uni.createCanvasContext('board-rotate', instance.proxy)
				const rate = height.value / width.value;
				canvasContext.translate(width.value, width.value / rate);
				canvasContext.rotate(-90 * Math.PI / 180);
				const x = -width.value / 2, y = -height.value / 2;
				canvasContext.drawImage(res.tempFilePath, x, y, width.value, height.value);
				canvasContext.draw();
				report();
			}
		});
	};

	// 上报父页面
	function report() {
		uni.canvasToTempFilePath({
			canvasId: 'board-rotate',
			success: function (e) {
				goBack()
				const eventChannel = instance.proxy.getOpenerEventChannel();
				eventChannel.emit('emits', {
					image: e.tempFilePath
				});
			}
		});
	}
</script>

<style lang="scss" scoped>
	.container {
		height: 100vh;
		padding: 15px;
		display: flex;
		align-items: flex-end;
	}

	.sigh-btns {
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: flex-end;
		width: 60px;
		height: inherit;
	}

	.btn {
		margin: 20px 0;
		width: 80px;
		transform: rotate(90deg);
	}

	.sign-board {
		background-color: #ffffff;
		border: 2px dotted #8d8d8d;
		border-radius: 8px;
		margin-bottom: 30px;
	}
</style>

更多推荐