手写电子签名,生成图片,下载图片或用blob和base64转文件并通过ajax上传到服务器

<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>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值