1.引言
在如今这个信息时代,电子签名已经成为了一种越来越流行的服务形式。它可以极大地提高工作效率,避免了传统签署方式带来的各种麻烦,比如快递费用、时间成本等。手写签名就是电子签名的一种方式,用户可以在移动端或电脑上直接在屏幕上手写签名,然后将签名保存在服务器上进行后续使用。
然而,实现手写签名并不是一件容易的事情,而Canvas就是制作手写签名和手势识别功能的最佳选择。在这篇文章中,我们将介绍如何使用Vue和Canvas实现手写签名和手势识别功能。
2.Web技术选型
在制作手写签名和手势识别功能的过程中,我们需要使用以下技术:
Vue:一种流行的前端JavaScript框架,用于创建单页应用程序。
Canvas:一种HTML元素,专门用于绘制二维图形和动画。
3.实现手写签名功能
3.1.设计界面
在界面设计上,我们需要使用HTML和Vue进行实现。我们可以在template标签中添加以下代码:
<div id="signature">
<canvas id="canvas" ref="canvas"></canvas>
<button @click="clear">清空</button>
</div>
在这段代码中,我们使用了canvas标签来实现手写签名的绘制,使用了ref属性来引用canvas元素。我们也添加了一个按钮,用于清空canvas元素。
3.2.绘制功能实现
现在,我们需要在Vue实例中添加以下代码,以实现手写签名绘制功能:
export default {
data() {
return {
isDrawing: false,
lastX: 0,
lastY: 0
};
},
computed: {
canvas: function() {
return this.$refs.canvas;
},
ctx: function() {
return this.canvas.getContext("2d");
}
},
mounted() {
this.canvas.addEventListener("mousedown", this.startDraw);
this.canvas.addEventListener("mousemove", this.draw);
this.canvas.addEventListener("mouseup", this.stopDraw);
this.canvas.addEventListener("mouseout", this.stopDraw);
},
methods: {
startDraw(e) {
this.isDrawing = true;
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
},
draw(e) {
if (!this.isDrawing) return;
this.ctx.beginPath();
this.ctx.moveTo(this.lastX, this.lastY);
this.ctx.lineTo(e.offsetX, e.offsetY);
this.ctx.stroke();
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
},
stopDraw() {
this.isDrawing = false;
},
clear() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
};
在这段代码中,我们创建了一个Vue实例,用于管理所有的手写签名绘制功能。我们添加了一个data对象,用于存储笔划的状态和最后一个笔画的位置。通过computed属性,我们引用了Canvas元素和它的上下文对象。在mounted()函数中,我们添加了鼠标事件监听器,这些事件会触发相应的绘图函数。在methods对象中,我们添加了四个绘图函数,分别用于开始和结束笔画,绘制线条和清空画布。
3.3.绘画效果
现在我们可以尝试在页面上手写签名,并把绘图效果呈现出来,这是一个示例:
<div id="signature">
<canvas id="canvas" ref="canvas"></canvas>
<button @click="clear">清除</button>
</div>
<script>
export default {
data() {
return {
isDrawing: false,
lastX: 0,
lastY: 0
};
},
computed: {
canvas: function() {
return this.$refs.canvas;
},
ctx: function() {
return this.canvas.getContext("2d");
}
},
mounted() {
this.canvas.addEventListener("mousedown", this.startDraw);
this.canvas.addEventListener("mousemove", this.draw);
this.canvas.addEventListener("mouseup", this.stopDraw);
this.canvas.addEventListener("mouseout", this.stopDraw);
},
methods: {
startDraw(e) {
this.isDrawing = true;
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
},
draw(e) {
if (!this.isDrawing) return;
this.ctx.beginPath();
this.ctx.moveTo(this.lastX, this.lastY);
this.ctx.lineTo(e.offsetX, e.offsetY);
this.ctx.stroke();
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
},
stopDraw() {
this.isDrawing = false;
},
clear() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
};
</script>
<style scoped>
#canvas {
border: 1px solid #000;
}
</style>
4.实现手势识别功能
4.1.设计界面
在手势识别功能的界面设计上,我们需要添加一个用于显示手势指令的按钮。我们可以在template标签中添加以下代码:
<button @click="recognize">识别手势</button>
4.2.手势识别算法
为了实现手势识别功能,我们需要实现一个算法来检测用户的手势。在这篇文章中,我们将采用一种简单的手势识别算法,它基于用户绘制的图形曲线来推断他们的意图。
我们假设用户只能画出直线和弧线,并使这些曲线成为一个连接的曲线。在这种情况下,我们可以通过一些简单的规则来判断用户所画的曲线属于哪种手势,比如一个圆形或一个提供选项卡切换的箭头。
4.3.手势检测代码
在Vue组件中,我们需要添加以下代码,以实现手势检测功能:
methods: {
calculateAngleFromPoints(p1, p2) {
return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;
},
recognize() {
const points = this.getPointsOnCanvas();
const firstSegment = points.slice(0, 2);
const lastSegment = points.slice(-2);
const angle = this.calculateAngleFromPoints(firstSegment[0], firstSegment[1]) - this.calculateAngleFromPoints(lastSegment[0], lastSegment[1]);
if (points.length < 10 || Math.abs(angle) < 15) {
return;
}
const last = points[points.length - 1];
const prev1 = points[points.length - 3];
const prev2 = points[points.length - 5];
const canBeArrow = Math.abs(angle) > 160 &&
last.x > prev1.x && prev1.x > prev2.x &&
Math.abs(last.y - prev1.y) < 20 && Math.abs(prev1.y - prev2.y) < 20;
if (canBeArrow) {
console.log('it is an arrow');
} else {
const first = points[0];
const last = points[points.length - 1];
if (Math.abs(first.x - last.x) < 20 && Math.abs(first.y - last.y) < 20) {
console.log('it is a circle');
} else {
console.log('it is unknown gesture');
}
}
},
getPointsOnCanvas() {
const rect = this.canvas.getBoundingClientRect();
return Array.from(this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height).data)
.reduce((acc, pixel, i) => {
if (i % 4 === 3 && pixel > 0) {
let pt = { x: (i / 4) % rect.width, y: Math.floor((i / 4) / rect.width) };
acc.push(pt);
}
return acc;
}, []);
}
}
在这段代码中,我们添加了一个方法calculateAngleFromPoints(),用于计算两个点之间的角度。我们还添加了一个方法recognize(),用于检测用户手势的内容。该方法将检查用户是否使用推测出的手势类型完成了路径,并在控制台上输出相应的消息。最后,我们还添加了一个方法getPointsOnCanvas(),用于获取Canvas中所有非透明的像素点,以便识别用户的手势。
5.总结
在本文中,我们介绍了如何使用Vue和Canvas实现手写签名和手势识别功能。在手写签名功能中,我们创建了一个Vue实例,并使用Canvas绘制了可以手写的画布。在手势识别功能中,我们创建了一个简单的算法来检测用户的手势,并在控制台上输出相应消息。通过阅读本文,您应该有了一些有关如何使用Vue和Canvas实现类似功能的基础知识。请自行扩展这个功能并添加更多的特性。