前端代码
javascript
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手写电子签名</title>
<style>
canvas {
border: 1px solid #000 ;
}
button {
margin-top: 10px;
}
</style>
</head>
<body>
<canvas id="signatureCanvas" width="400" height="200"></canvas>
<button onclick="clearCanvas()">重新输入签名</button>
<button onclick="saveSignature()">保存签名</button>
<script>
// 获取页面上的canvas元素,这个元素用于绘制签名
const canvas = document.getElementById('signatureCanvas');
// 获取canvas的2D绘图上下文,用于在canvas上进行绘图操作
const ctx = canvas.getContext('2d');
// 定义一个变量来跟踪当前是否正在绘图
let isDrawing = false;
// 定义变量来存储上一个点的坐标,用于绘制线条
let lastX = 0;
let lastY = 0;
// 当鼠标按下时触发的事件监听器
canvas.addEventListener('mousedown', (e) => {
// 设置isDrawing为true,表示开始绘图
isDrawing = true;
// 使用解构赋值更新lastX和lastY为鼠标当前的位置
[lastX, lastY] = [e.offsetX, e.offsetY];
});
// 当鼠标移动时触发的事件监听器
canvas.addEventListener('mousemove', (e) => {
// 如果正在绘图,则执行以下操作
if (isDrawing) {
// 开始一个新的路径
ctx.beginPath();
// 将路径的起点移动到上一个点的坐标
ctx.moveTo(lastX, lastY);
// 将路径的终点设置为当前鼠标的位置
ctx.lineTo(e.offsetX, e.offsetY);
// 描边路径,使线条可见
ctx.stroke();
// 更新lastX和lastY为当前鼠标的位置,为下一次绘制准备
[lastX, lastY] = [e.offsetX, e.offsetY];
}
});
// 当鼠标松开时触发的事件监听器
canvas.addEventListener('mouseup', () => {
// 设置isDrawing为false,表示停止绘图
isDrawing = false;
});
// 定义一个函数用于清空canvas上的内容
function clearCanvas() {
// 使用clearRect方法清空canvas上的所有内容
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// 定义一个函数用于保存签名到服务器
function saveSignature() {
// 将canvas的内容转换为DataURL格式的字符串,这个字符串包含了图像的base64编码
const imageDataUrl = canvas.toDataURL();
// 从imageDataUrl中提取出base64编码的图像数据
const imageData = imageDataUrl.substring("data:image/png;base64,".length);
// 调用sendDataToServer函数将图像数据发送到服务器
sendDataToServer(imageData);
}
// 定义一个函数用于通过XMLHttpRequest将数据发送到服务器
function sendDataToServer(imageDataUrl) {
// 创建一个新的XMLHttpRequest对象
const xhr = new XMLHttpRequest();
// 配置xhr对象,设置请求方法为POST,请求URL为'/one/saveSignature',并设置为异步请求
xhr.open('POST', '/one/saveSignature', true);
// 设置请求头Content-Type为application/json,表示发送的数据是JSON格式
xhr.setRequestHeader('Content-Type', 'application/json');
// 设置xhr的onload事件处理函数,用于处理响应
xhr.onload = function () {
// 如果响应状态码为200,表示请求成功,打印响应文本
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
// 如果响应状态码不是200,打印错误信息
console.error('Error:', xhr.statusText);
}
};
// 发送请求,请求体是一个JSON对象,包含一个名为imageData的属性,其值为base64编码的图像数据
xhr.send(JSON.stringify({imageData: imageDataUrl}));
}
</script>
</body>
</html>
后端代码
java
@ApiOperation(value = "电子签名图片", notes = "电子签名图片")//接口释义
@RequestMapping(value = "/saveSignature", method = RequestMethod.POST)
@ApiImplicitParams({
@ApiImplicitParam(name = "imageData", value = "base64", required = true)
})
public String saveSignature(@RequestBody String imageData,HttpServletRequest request) {
// 创建日期格式器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd/");
// 格式化日期
String formattedDate = LocalDate.now().format(formatter);
// 压缩临时目录
String tmpdir = request.getSession().getServletContext().getRealPath("/") + "files/sign/" + formattedDate;
if (!FileUtil.exist(new File(tmpdir))) {
FileUtil.mkdir(tmpdir);
}
try {
// 尝试解码Base64字符串
byte[] imageBytes = Base64.getDecoder().decode(JSONObject.parseObject(imageData).getString("imageData"));
// 保存图片到指定路径
File imageFile = new File(tmpdir + UUID.randomUUID() + ".png");
FileOutputStream outputStream = new FileOutputStream(imageFile);
outputStream.write(imageBytes);
outputStream.close();
// 返回保存成功的信息
return "保存成功" + imageFile.getPath();
} catch (Exception e) {
e.printStackTrace();
return "保存失败";
}
}
结果展示