uniapp canvas实现电子签名
·

这是个页面哦。记得配置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>
更多推荐

所有评论(0)