html移动端实现手写签名,signature手写签名实现,微信公众号浏览器html手写签名实现

前言

html移动端手写自动横竖签名实现,并base64图片格式获取;
横竖根据屏幕宽高自动平铺。

效果图

图一

在这里插入图片描述

图二

在这里插入图片描述

实现

如下代码直接复制成.html文件打开即可预览效果

<!DOCTYPE html>
<html>
    <head>
        <title>手写签名</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
        <style>
            html,body {
                padding:0;
                margin:0;
                width: 100%;
                height: 100%;
            }
            .text-center {
			    text-align: center;
			}
			#signature-button {
			    display: block;
			    margin: 0 auto;
			    border: 1px solid #6680ff;
			    background: #6680ff;
			    color: #fff;
			    border-radius: 4px;
			    padding: 8px 10px;
			    font-size: 16px;
			    cursor: pointer;
			}
			#signature-button:hover {
				opacity: 0.8;
			}
			#signature-img {
			    width: 100%;
			    margin: 10px auto;
			    display: none;
			}
			#signature-pop {
			    position: fixed;
			    background-color: #fff;
			    top:0;
			    left:0;
			    bottom:0;
			    right:0;
			    width: 100%;
			    height: 100%;
			    display: none;
			}
			#signature-container {
			    width: 100%;
			    height: 100%;
			}
			.demo-top-info {
			    position: absolute;
			    top: 0;
			    left: 0;
			    width: 100%;
			    height: 40px;
			    background: #7b8bff;
			    box-sizing: border-box;
			    text-align: center;
			    color: #fff;
			}
			.demo-top-info .return {
			    padding-left: 5px;
			    height: 40px;
			    line-height: 40px;
			    position: absolute;
			    left: 10px;
			    display: inline-block;
			    cursor: pointer;
			}
			.signature-title {
			    height: 40px;
			    line-height: 40px;
			    display: inline-block;
			}
			.canvas-container {
			    width: 100%;
			    height: 100%;
			    background-color: #ffffff;
			    box-sizing: border-box;
			    padding: 40px 0 50px 0;
			}
			.canvas-parent {
			    width: 100%;
			    height: 100%;
			}
			.demo-bottom-info {
			    position: absolute;
			    bottom: 0;
			    left: 0;
			    width: 100%;
			    height: 50px;
			    background: #ffffff;
			    padding: 0 2%;
			    box-sizing: border-box;
			    overflow: hidden;
			    /* box-shadow: #efefef 0 -2px 5px 0; */
			    border-top: 1px solid #efefef;
			}
			#clean_canvas {
			    float: left;
			    font-size: 16px;
			    margin-top: 5px;
			    /* background: #f8f8f8; */
			    border: 1px solid #ddd;
			    padding: 8px 10px;
			    border-radius: 4px;
			    color: #323232;
			    cursor: pointer;
			}
			#sure_canvas {
			    float: right;
			    padding: 3px 0;
			    background: #7b8bff;
			    padding: 8px 10px;
			    border: 1px solid #7b8bff;
			    border-radius: 4px;
			    color: #fff;
			    margin-top: 5px;
			    cursor: pointer;
			}
			#clean_canvas:hover,
			#sure_canvas:hover{
				opacity: 0.8;
			} 
			#canvas2 {
			    position: absolute;
			    top: 0;
			    left:0;
			    z-index: 999;
			    margin-left: 40px;
			}
        </style>
    </head>
    <body>
    	
        <div class="app-container" style="padding-top: 100px;">
            <button id="signature-button">开始手写签名</button>
            <div class="signature-result__img">
                <img src="" id="signature-img" alt="手写签名图片预览"/>
            </div>
        </div>
        
        <!-- 注意核心块 -->
        <div id="signature-pop">
            <div id="signature-container">
                <div class="demo-top-info" id="rotate-container">
                    <div class="return" id="return">返回</div>
                    <div class="signature-title text-center">手写签名</div>
                </div>
                <div class="canvas-container">
                    <div class="canvas-parent">
                        <canvas id="canvas"></canvas>
                    </div>
                </div>
                <div class="demo-bottom-info">
                    <div id="clean_canvas">清空</div>
                    <div id="sure_canvas">确认</div>
                </div>
            </div>
            <canvas id="canvas2"></canvas>
        </div>
        
    </body>
    <script type="text/javascript">
        
        // 手绘签名类
		var SignatureClass = (function(){
		    //获取当前位置(返回px)
		    function getStyle(obj, attr) {
		        if (obj.currentStyle) {
		            return obj.currentStyle[attr];
		        } else {
		            return getComputedStyle(obj, false)[attr];
		        }
		    }
		    
		    function Signatrue(options) {
		        this.cavnas = null;
		        this.ctx = null;
		        this.maxparams = {};
		        this.minparams = {};
		        this.entershuping = true; //是否是竖屏 true=是
		        this.firstTouch = true; // 第一次点击或touch
		        this.allowSubmit = false; // 是否手写了内容 是=才能提交 否=不能提交
		        if(options === void 0) {
		            options = {};
		        }
		        this.options = options;
		    }
		    
		    // 初始化
		    Signatrue.prototype.init = function() {
		        var self = this;
		        console.log(getStyle(document.getElementById("rotate-container"), "height")); // 不知道为什么加,否则有些Apple出问题
		        this.hengshuping();
		        this.clear();
		        this.submit();
		        
		        window.addEventListener('resize',function() {
		            self.hengshuping();
		        },false);
		    }
		    
		    // 判断横竖屏
		    Signatrue.prototype.hengshuping = function() {
		        if (window.orientation == 90 || window.orientation == -90) {
		            this.entershuping = false; // 横屏
		            document.getElementById("canvas2").style.display = "none";
		            document.getElementById("canvas").style.display = "block";
		            this.canvas = document.getElementById("canvas");
		            this.ctx = this.canvas.getContext("2d");
		            this.ctx.lineWidth = 2; // 画线的大小
		            this.ctx.strokeStyle = "#000000";
		            this.drawEvent();
		            document.querySelector("#signature-container").style.width = window.innerWidth + "px";
		            document.querySelector("#signature-container").style.height = window.innerHeight + "px";
		            this.canvas.height = parseInt(getStyle(document.getElementById("canvas").parentNode, 'height'));
		            this.canvas.width = parseInt(getStyle(document.getElementById("canvas").parentNode, 'width'));
		            document.querySelector("#signature-container").style.transform = "rotate(0deg)";
		            document.querySelector("#signature-container").style.transformOrigin = "0 0";
		            document.querySelector("#signature-container").style.marginLeft = "0px";
		        } else { // 竖屏
		            this.entershuping = true;
		            document.getElementById("canvas").style.display = "none";
		            document.getElementById("canvas2").style.display = "block";
		            this.canvas = document.getElementById("canvas2");
		            this.ctx = this.canvas.getContext("2d");
		            this.canvas.height = window.innerHeight;
		            this.canvas.width = window.innerWidth - 40 - 40;
		            this.ctx.lineWidth = 2;// 画线的大小
		            this.ctx.strokeStyle = "#000000";
		            this.drawEvent();
		            document.querySelector("#signature-container").style.width = window.innerHeight + "px";
		            document.querySelector("#signature-container").style.height = window.innerWidth + "px";
		            document.querySelector("#signature-container").style.transform = "rotate(90deg)";
		            document.querySelector("#signature-container").style.transformOrigin = "0 0";
		            document.querySelector("#signature-container").style.marginLeft = window.innerWidth + "px";
		        }
		    }
		    
		    // 绘画事件
		    Signatrue.prototype.drawEvent = function() {
		        var self = this;
		        this.canvas.addEventListener("touchstart", function(evt) {
		            var oEvent = evt || event;
		            oEvent.preventDefault();
		            var position = self.pos(oEvent);
		            self.ctx.beginPath();
		            self.ctx.moveTo(position.x, position.y);
		            if (self.firstTouch) {
		                self.minparams = {
		                    x: position.x,
		                    y: position.y
		                };
		                self.maxparams = {
		                    x: position.x,
		                    y: position.y
		                };
		                self.firstTouch = false;
		            } else {
		                self.judgeSize(position);
		            }
		            self.canvas.addEventListener("touchmove", touchmove, false)
		        
		            function touchmove(evt) {
		                var oEvent = evt || event;
		                oEvent.preventDefault();
		                var position = self.pos(oEvent);
		                self.ctx.lineTo(position.x, position.y);
		                self.judgeSize(position);
		                self.ctx.stroke();
		            }
		            document.addEventListener("touchend", touchend, false)
		        
		            function touchend(evt) {
		                var oEvent = evt || event;
		                oEvent.preventDefault();
		                self.allowSubmit = true;
		                self.canvas.removeEventListener("touchmove", touchmove);
		                document.removeEventListener("touchend", touchend);
		            }
		        })
		    }
		    
		    // 清空画笔
		    Signatrue.prototype.clear = function() {
		        var self = this;
		        document.getElementById("clean_canvas").addEventListener("click", function() {
		            self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height);
		            self.allowSubmit = false;
		        })
		    }
		    
		    // 提交画笔内容
		    Signatrue.prototype.submit = function() {
		        var self = this;
		        document.getElementById("sure_canvas").addEventListener("click", function() {
		            if (self.allowSubmit) {
		                var imgSRC = self.canvas.toDataURL('image/png', 1);
		                var img = new Image();
		                img.src = imgSRC;
		                self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height);
		                img.onload = function() {
		                    var width = self.maxparams.x - self.minparams.x;
		                    var height = self.maxparams.y - self.minparams.y;
		                    var targetWidth = 200;
		                    var targetHeight = 100;
		                    var clipCanvas = document.createElement("canvas");
		                    clipCanvas.width = targetWidth;
		                    clipCanvas.height = targetHeight;
		                    var ctx2 = clipCanvas.getContext("2d");
		                    if (self.entershuping) {
		                        ctx2.translate(0, targetHeight);
		                        ctx2.rotate(-90 * Math.PI / 180);
		                        ctx2.drawImage(img, self.minparams.x, self.minparams.y, width, height, 0, 0, targetHeight, targetWidth);
		                    } else {
		                        ctx2.drawImage(img, self.minparams.x, self.minparams.y, width, height, 0, 0, targetWidth, targetHeight);
		                    }
		                    var imgSRC2 = clipCanvas.toDataURL('image/png', 1);
		                    if(self.options && self.options.callback && typeof self.options.callback == 'function') {
		                        self.options.callback(imgSRC2);
		                        // imgSRC2 这就是base64返回值了
		                    }
		                    self.canvas = null;
		                    self.ctx = null;
		                    ctx2 = null;
		                    clipCanvas = null;
		                    
		                }
		            } else {
		                alert("没有手写签名,不能提交!")
		            }
		        })
		    }
		    
		    
		    // 获取当前位置
		    Signatrue.prototype.pos = function(event) {
		        var x = event.touches[0].pageX - event.target.offsetLeft;
		        var y = event.touches[0].pageY - event.target.offsetTop;
		        return {
		            x: x,
		            y: y
		        };
		    }
		    
		    // 优化画笔界限,去掉空白区域
		    Signatrue.prototype.judgeSize = function(value) {
		        if (this.minparams.x > value.x) {
		            this.minparams.x = value.x;
		        }
		        if (this.maxparams.x < value.x) {
		            this.maxparams.x = value.x;
		        }
		        if (this.minparams.y > value.y) {
		            this.minparams.y = value.y;
		        }
		        if (this.maxparams.y < value.y) {
		            this.maxparams.y = value.y;
		        }
		    }
		    
		    return Signatrue;
		})();
        
        // 【使用方式-参数接收】
        // 点击去手写签名-展示手写签名弹框
        document.getElementById('signature-button').addEventListener('click',function(){
            document.getElementById('signature-pop').style.display = 'block';
            var signatrueDraw = new SignatureClass({
                callback: function(base64) {
                	// base64就是这个图片的值了【注意:这里得到值】
                    document.getElementById('signature-img').src = base64;
                    document.getElementById('signature-pop').style.display = 'none';
                    document.getElementById('signature-img').style.display = 'block';
                }
            });
            signatrueDraw.init();

        },false);
        
        // 点击弹框返回
        document.getElementById('return').addEventListener('click',function(){
            document.getElementById('signature-pop').style.display = 'none';
        },false);
        
        
    </script>
</html>
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要在Vue移动端实现横屏手写签名功能,可以使用HTML5的canvas元素和JavaScript来实现。首先,你需要创建一个canvas元素,并设置其宽高比,以便在横屏模式下正确显示。然后,你需要监听设备方向变化事件,根据设备方向动态调整canvas元素的宽高比,以便在横屏模式下正确显示。最后,你需要监听用户手写事件,并在canvas元素上绘制用户手写签名。 以下是示例代码,可以在移动设备上测试: ```html <template> <div class="canvas-container"> <canvas ref="canvas"></canvas> </div> </template> <script> export default { mounted() { // 监听设备方向变化事件 window.addEventListener("orientationchange", this.onOrientationChange); // 初始化canvas this.initCanvas(); }, methods: { initCanvas() { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 设置canvas宽高比为3:2 canvas.width = 300; canvas.height = 200; // 监听用户手写事件 canvas.addEventListener("touchstart", this.onTouchStart); canvas.addEventListener("touchmove", this.onTouchMove); canvas.addEventListener("touchend", this.onTouchEnd); }, onOrientationChange() { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 根据设备方向动态调整canvas宽高比 if (window.orientation === 90 || window.orientation === -90) { canvas.width = 200; canvas.height = 300; } else { canvas.width = 300; canvas.height = 200; } // 清空canvas ctx.clearRect(0, 0, canvas.width, canvas.height); }, onTouchStart(event) { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 开始绘制路径 ctx.beginPath(); // 获取触点位置 const touch = event.touches[0]; const x = touch.pageX - canvas.offsetLeft; const y = touch.pageY - canvas.offsetTop; // 移动到触点位置 ctx.moveTo(x, y); }, onTouchMove(event) { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 获取触点位置 const touch = event.touches[0]; const x = touch.pageX - canvas.offsetLeft; const y = touch.pageY - canvas.offsetTop; // 绘制直线到触点位置 ctx.lineTo(x, y); ctx.stroke(); }, onTouchEnd() { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 结束路径绘制 ctx.closePath(); } }, beforeDestroy() { // 移除事件监听 window.removeEventListener("orientationchange", this.onOrientationChange); const canvas = this.$refs.canvas; canvas.removeEventListener("touchstart", this.onTouchStart); canvas.removeEventListener("touchmove", this.onTouchMove); canvas.removeEventListener("touchend", this.onTouchEnd); } }; </script> <style scoped> .canvas-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; } canvas { border: 1px solid #ccc; } </style> ``` 在上面的示例中,我们创建了一个canvas元素,并设置了其宽高比为3:2,以便在竖屏模式下正确显示。我们还监听了设备方向变化事件,根据设备方向动态调整canvas元素的宽高比。我们还监听了用户手写事件,并在canvas元素上绘制用户手写签名。当用户完成签名后,可以将canvas元素上的图像数据保存到服务器或本地存储中。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值