1、签名自定义组件代码示例:
qianMing.vue
<template>
<!-- 容器,包含画布和清除按钮 -->
<div class="signature-pad-container">
<!-- 画布元素,用于用户签名 -->
<canvas
ref="canvas" <!-- 用于获取canvas DOM元素的引用 -->
class="signature-pad" <!-- 自定义类名,便于样式控制 -->
@mousedown="startDrawing" <!-- 鼠标按下时开始绘图 -->
@mousemove="draw" <!-- 鼠标移动时持续绘图 -->
@mouseup="stopDrawing" <!-- 鼠标抬起时停止绘图 -->
@mouseleave="stopDrawing" <!-- 鼠标离开画布时停止绘图 -->
@touchstart.prevent="startDrawing" <!-- 触摸屏幕开始绘图,阻止默认行为 -->
@touchmove.prevent="draw" <!-- 触摸滑动时绘图,阻止默认行为 -->
@touchend="stopDrawing" <!-- 触摸结束时停止绘图 -->
></canvas>
<!-- 清除画布按钮 -->
<button @click="clearCanvas">Clear</button>
</div>
</template>
<script>
export default {
// 数据属性定义
data() {
return {
isDrawing: false, // 绘制状态标志,true为正在绘制
context: null, // 2D渲染上下文,用于操作画布
lastX: 0, // 上一次鼠标或触摸点的X坐标
lastY: 0 // 上一次鼠标或触摸点的Y坐标
};
},
// 挂载后执行,用于初始化画布
mounted() {
const canvas = this.$refs.canvas; // 获取canvas元素
canvas.width = canvas.offsetWidth; // 设置画布宽度为元素显示宽度
canvas.height = canvas.offsetHeight; // 设置画布高度为元素显示高度
this.context = canvas.getContext('2d'); // 获取2D渲染上下文
this.context.strokeStyle = '#000'; // 设置线颜色为黑色
this.context.lineWidth = 2; // 设置线条宽度为2
},
// 方法集合
methods: {
// 开始绘图的处理函数
startDrawing(event) {
this.isDrawing = true; // 设置绘制状态为true
// 获取事件坐标
const { offsetX, offsetY } = this.getEventCoords(event);
this.lastX = offsetX; // 记录起始点X坐标
this.lastY = offsetY; // 记录起始点Y坐标
this.context.beginPath(); // 开始一条新的路径
this.context.moveTo(this.lastX, this.lastY); // 移动到起始点
},
// 绘图过程中的处理函数
draw(event) {
// 如果不是绘制状态则返回
if (!this.isDrawing) return;
// 获取当前坐标
const { offsetX, offsetY } = this.getEventCoords(event);
// 从上一点画直线到当前位置
this.context.lineTo(offsetX, offsetY);
this.context.stroke(); // 绘制路径
// 更新最后的位置坐标
this.lastX = offsetX;
this.lastY = offsetY;
},
// 停止绘图的处理函数
stopDrawing() {
this.isDrawing = false; // 设置绘制状态为false
this.context.closePath(); // 结束当前路径
},
// 清除画布的方法
clearCanvas() {
const canvas = this.$refs.canvas; // 获取canvas元素
// 清除整个画布
this.context.clearRect(0, 0, canvas.width, canvas.height);
},
// 获取事件坐标的方法,兼容触控和鼠标事件
getEventCoords(event) {
// 如果是触控事件,则计算相对于canvas的位置
if (event.touches && event.touches.length > 0) {
const rect = this.$refs.canvas.getBoundingClientRect(); // 获取canvas元素的边界信息
return {
offsetX: event.touches[0].clientX - rect.left, // 触摸点相对画布左边界的X坐标
offsetY: event.touches[0].clientY - rect.top // 触摸点相对画布上边界的Y坐标
};
} else { // 否则是鼠标事件
return {
offsetX: event.offsetX, // 鼠标事件直接提供相对于元素内部的坐标
offsetY: event.offsetY
};
}
}
}
};
</script>
<style scoped>
/* 容器样式 */
.signature-pad-container {
position: relative; /* 使子元素可以绝对定位 */
width: 100%; /* 宽度充满父容器 */
height: 100px; /* 高度固定 */
border: 1px solid #ccc; /* 边框样式 */
border-radius: 15px; /* 边框圆角 */
}
/* 画布样式 */
.signature-pad {
width: 100%; /* 宽度充满容器 */
height: 100%; /* 高度充满容器 */
cursor: crosshair; /* 鼠标指针为十字准星 */
touch-action: none; /* 禁止浏览器对触摸事件的默认处理 */
}
/* 清除按钮样式 */
button {
position: absolute; /* 绝对定位 */
top: 10px; /* 距离顶部距离 */
right: 10px; /* 距离右侧距离 */
z-index: 10; /* 确保按钮在最上层 */
}
</style>
2、在script中引入自定义组件
<script>
import qianMing from "@/components/qianMing.vue";
export default {
name: 'App',
data() {
return {
}
},
methods: {
},
components: {
qianMing
}
}
</script>
完成上述步骤即可实现网页签名效果。
效果图: