1. 简介
在很多应用中,由于用户可能需要通过手写来填写信息,因此手写签名的功能就成为了一种很常见的需求。在 Vue 中实现手写签名,需要用到以下技术:HTML5 的 Canvas、JavaScript 绘图 API 和 Vue 的生命周期函数。
2. HTML5 的 Canvas
Canvas 是HTML5 的一种新增元素,它可以用于通过 JavaScript 来绘制图像、动画或者其他图形。我们可以利用 Canvas 实现绘制、保存、撤销等功能。
2.1. Canvas 的基本用法
要在 HTML 页面中创建一个 Canvas 元素,需要使用以下代码:
<canvas id="myCanvas"></canvas>
然后在 JavaScript 中获取这个 Canvas 元素对象,即可开始绘制。下面的代码演示了如何在 Canvas 上绘制一条红线:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.moveTo(0, 0);
ctx.lineTo(200, 100);
ctx.stroke();
上面的代码中,首先获取了 ID 为 "myCanvas" 的 Canvas 元素对象,然后通过 getContext() 方法获得画布上绘图的上下文,接着设置线条的宽度和颜色,并用 moveTo() 和 lineTo() 方法绘制了一条斜线,最后用 stroke() 方法将线条渲染到画布上。
2.2. 实现手写签名
要实现手写签名的功能,需要先创建一个 Canvas 元素,然后在该元素上绘制用户的手写轨迹。我们可以监听鼠标/触摸事件,获取用户的手写坐标,并用之前介绍过的绘图 API 在 Canvas 上绘制路径。
假设我们已经创建了一个 Canvas 元素,且其 ID 为 "myCanvas",我们可以使用下面的代码来实现手写签名:
new Vue({
el: '#app',
data: {
isDrawing: false,
lastX: 0,
lastY: 0
},
mounted: function() {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
// 设置 Canvas 大小
canvas.width = 500;
canvas.height = 300;
// 绑定事件
canvas.addEventListener('mousedown', this.onStartDrawing);
canvas.addEventListener('mousemove', this.onDrawing);
canvas.addEventListener('mouseup', this.onStopDrawing);
canvas.addEventListener('mouseout', this.onStopDrawing);
},
methods: {
onStartDrawing: function(e) {
this.isDrawing = true;
var pos = this.getPosition(e);
this.lastX = pos.x;
this.lastY = pos.y;
},
onDrawing: function(e) {
if (!this.isDrawing) return;
var pos = this.getPosition(e);
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 2;
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.moveTo(this.lastX, this.lastY);
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
this.lastX = pos.x;
this.lastY = pos.y;
},
onStopDrawing: function(e) {
this.isDrawing = false;
},
getPosition: function(e) {
var canvas = document.getElementById('myCanvas');
var rect = canvas.getBoundingClientRect();
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
}
}
});
上述代码中,我们在 Vue 的 mounted() 生命周期函数中绑定了鼠标/触摸事件,并绘制了手写轨迹。isDrawing、lastX、lastY 是我们需要在 data 中定义的属性,用于追踪鼠标/触摸事件和手写轨迹。
需要注意的是,我们在获取鼠标/触摸事件的坐标时,需要减去 Canvas 元素在页面中的位置,这可以通过 Canvas 元素的 getBoundingClientRect() 方法得到。
3. 其他功能
除了手写签名,我们很可能还需要添加一些其他功能,例如保存、清除、撤销等。下面的代码演示了如何实现这些功能:
new Vue({
el: '#app',
data: {
isDrawing: false,
lastX: 0,
lastY: 0,
undoList: []
},
mounted: function() {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
// 设置 Canvas 大小
canvas.width = 500;
canvas.height = 300;
// 绑定事件
canvas.addEventListener('mousedown', this.onStartDrawing);
canvas.addEventListener('mousemove', this.onDrawing);
canvas.addEventListener('mouseup', this.onStopDrawing);
canvas.addEventListener('mouseout', this.onStopDrawing);
// 添加 Clear 按钮
var buttonClear = document.createElement('button');
buttonClear.textContent = '清除';
buttonClear.addEventListener('click', this.onClear);
document.body.appendChild(buttonClear);
// 添加 Save 按钮
var buttonSave = document.createElement('button');
buttonSave.textContent = '保存';
buttonSave.addEventListener('click', this.onSave);
document.body.appendChild(buttonSave);
// 添加 Undo 按钮
var buttonUndo = document.createElement('button');
buttonUndo.textContent = '撤销';
buttonUndo.addEventListener('click', this.onUndo);
document.body.appendChild(buttonUndo);
},
methods: {
onStartDrawing: function(e) {
this.isDrawing = true;
var pos = this.getPosition(e);
this.lastX = pos.x;
this.lastY = pos.y;
},
onDrawing: function(e) {
if (!this.isDrawing) return;
var pos = this.getPosition(e);
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 2;
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.moveTo(this.lastX, this.lastY);
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
this.lastX = pos.x;
this.lastY = pos.y;
},
onStopDrawing: function(e) {
this.isDrawing = false;
},
onClear: function(e) {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
},
onSave: function(e) {
var canvas = document.getElementById('myCanvas');
var dataURL = canvas.toDataURL();
window.open(dataURL, '_blank');
},
onUndo: function(e) {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
var lastUndo = this.undoList.pop();
if (lastUndo) {
img.src = lastUndo;
}
},
getPosition: function(e) {
var canvas = document.getElementById('myCanvas');
var rect = canvas.getBoundingClientRect();
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
}
}
});
上述代码中,我们在 mounted() 生命周期函数中添加了三个按钮:Clear、Save 和 Undo。Clear 按钮用于清除 Canvas 上的手写轨迹,Save 按钮用于将 Canvas 转化为数据 URL 并在新窗口中打开,以便用户下载/保存,Undo 按钮则用于撤销上一步绘画操作,将 Canvas 恢复到上一步绘图的状态。我们用一个 undoList 数组来储存每一步绘图的状态(也可以使用撤销栈)。
4. 总结
在 Vue 中实现手写签名的功能需要用到 HTML5 的 Canvas、JavaScript 绘图 API 和 Vue 的生命周期函数。通过监听鼠标/触摸事件,获取用户的手写坐标,我们可以通过绘图 API 在 Canvas 上绘制手写轨迹。除了手写签名,我们还可以添加 Clear、Save 和 Undo 等功能,使得用户能够清除手写轨迹、将手写签名转化为数据 URL 并保存,以及撤销上一步绘制操作等。