<style>
#signatureArea {
height: 100%;
background-color: #FFFFFF;
margin-bottom: 10px;
position: relative;
}
.sign-btn-box {
position: absolute;
right: 0;
bottom: 0;
padding: 10px;
}
</style>
<div id="signatureArea">
<div class="sign-btn-box">
<button id="clearButton">清除</button>
<button id="saveButton">保存签名</button>
</div>
</div>
<script type="text/javascript">
$(function () {
// 获取DOM元素
var signatureArea = document.getElementById('signatureArea');
var clearButton = document.getElementById('clearButton');
var saveButton = document.getElementById('saveButton');
// 定义变量
var isDrawing = false; // 是否正在绘制
var lastX, lastY; // 上一个触摸点的坐标
// 创建两个canvas元素
var drawingCanvas = document.createElement('canvas'); // 用于绘制签名
var backgroundCanvas = document.createElement('canvas'); // 用于保存带有白色背景的签名图像
var drawingCtx = drawingCanvas.getContext('2d');
var backgroundCtx = backgroundCanvas.getContext('2d');
drawingCanvas.width = signatureArea.offsetWidth;
drawingCanvas.height = signatureArea.offsetHeight;
backgroundCanvas.width = drawingCanvas.width;
backgroundCanvas.height = drawingCanvas.height;
// 将canvas元素插入DOM树中
signatureArea.appendChild(drawingCanvas);
// 绑定触摸事件
signatureArea.addEventListener('touchstart', startDrawing);
signatureArea.addEventListener('mousedown', startDrawingPC);
signatureArea.addEventListener('touchmove', draw);
signatureArea.addEventListener('mousemove', drawPC);
signatureArea.addEventListener('touchend', stopDrawing);
signatureArea.addEventListener('mouseup', stopDrawing);
clearButton.addEventListener('click', clearSignature);
saveButton.addEventListener('click', saveSignature);
// 开始绘制
function startDrawing(e) {
e.preventDefault();
let touch = e.touches[0];
let rect = signatureArea.getBoundingClientRect();
lastX = touch.clientX - rect.left;
lastY = touch.clientY - rect.top;
isDrawing = true;
}
function startDrawingPC(e) {
e.preventDefault();
let rect = signatureArea.getBoundingClientRect();
lastX = e.x - rect.left;
lastY = e.y - rect.top;
isDrawing = true;
}
// 绘制中
function draw(e) {
if (!isDrawing) return;
let touch = e.touches[0];
let rect = signatureArea.getBoundingClientRect();
let x = touch.clientX - rect.left;
let y = touch.clientY - rect.top;
drawLine(lastX, lastY, x, y);
lastX = x;
lastY = y;
}
function drawPC(e) {
if (!isDrawing) return;
let rect = signatureArea.getBoundingClientRect();
let x = e.x - rect.left;
let y = e.y - rect.top;
drawLine(lastX, lastY, x, y);
lastX = x;
lastY = y;
}
// 停止绘制
function stopDrawing() {
isDrawing = false;
}
// 绘制实线
function drawLine(x1, y1, x2, y2) {
drawingCtx.beginPath();
drawingCtx.moveTo(x1, y1);
drawingCtx.lineTo(x2, y2);
drawingCtx.lineWidth = 1;
drawingCtx.strokeStyle = '#000';
drawingCtx.stroke();
}
// 清除签名
function clearSignature() {
drawingCtx.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height);
backgroundCtx.clearRect(0, 0, backgroundCanvas.width, backgroundCanvas.height);
}
// 方式一:保存签名并下载图片
function saveSignature() {
// 绘制白色背景
backgroundCtx.fillStyle = 'white';
backgroundCtx.fillRect(0, 0, backgroundCanvas.width, backgroundCanvas.height);
// 复制绘制的签名到带有白色背景的画布
backgroundCtx.drawImage(drawingCanvas, 0, 0);
// 将带有白色背景的画布内容转为PNG格式的DataURL
var dataURL = backgroundCanvas.toDataURL("image/png");
// 创建一个链接元素并设置下载属性
var link = document.createElement('a');
link.href = dataURL;
link.download = '签名.png'; // 设置下载文件的名称
// 检查是否支持保存到相册
if ("download" in link) {
link.style.display = "none";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} else {
// 如果不支持保存到相册,你可以提供其他方式或提示用户手动保存
alert("无法直接保存到相册,请手动保存签名图片。");
}
}
// 方式二:保存签名并用ajax上传(BLOB模式)
function saveSignature() {
// 绘制白色背景
backgroundCtx.fillStyle = 'white';
backgroundCtx.fillRect(0, 0, backgroundCanvas.width, backgroundCanvas.height);
// 复制绘制的签名到带有白色背景的画布
backgroundCtx.drawImage(drawingCanvas, 0, 0);
// 将带有白色背景的画布内容转为BLOB
backgroundCanvas.toBlob((blob) => {
/*
* 注意第一个File的构造方法第一个参数必须要用[]包起来,表明这是一个数组
* 第二个参数是这个文件名
* 第三个参数是选项,其中通过type指定这个文件的mime值
*/
let file2 = new File([blob], 'sign.png', {type: 'image/png'})
// ajax上传文件不能像上传普通对象那样,得用上FormData
let formData = new FormData()
formData.append('file', file2)
$.ajax({
url: '/',
type: 'POST',
processData: false, // processData和contentType必须指定为false
contentType: false,
cache: false,
data: formData,
success(res) {
console.log("上传完成!")
}
})
});
}
// 方式三:保存签名并用ajax上传(Base64模式)
function saveSignature() {
// 绘制白色背景
backgroundCtx.fillStyle = 'white';
backgroundCtx.fillRect(0, 0, backgroundCanvas.width, backgroundCanvas.height);
// 复制绘制的签名到带有白色背景的画布
backgroundCtx.drawImage(drawingCanvas, 0, 0);
// 将带有白色背景的画布内容转为PNG格式的DataURL
let base64 = backgroundCanvas.toDataURL("image/png"); // 同样通过canvas的toDataURL方法将canvas图片Base64编码
let bstr = atob(base64.split(',')[1]); // atob是将base64编码解码,去掉data:image/png;base64,部分
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
let file2 = new File([u8arr], 'sign.png', {type: 'image/png'})
// ajax上传文件不能像上传普通对象那样,得用上FormData
let formData = new FormData()
formData.append('file', file2)
$.ajax({
url: '/',
type: 'POST',
processData: false, // processData和contentType必须指定为false
contentType: false,
cache: false,
data: formData,
success(res) {
console.log("上传完成!")
}
})
}
})
</script>
手写电子签名,生成图片,下载图片或用blob和base64转文件并通过ajax上传到服务器
最新推荐文章于 2024-08-20 19:48:29 发布