适用于移动端,项目做了移动端的自适配
html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,maximum-scale=1,initial-scale=1,user-scalable=no">
<title>sing2</title>
<!-- <link rel="stylesheet" href="addicon/iconfont.css" /> -->
<link rel="stylesheet" href="signature.css" />
<script type="text/javascript" src="signature.js"></script>
</head>
<body>
</body>
</html>
css文件
body,p,dl,dd,ul,ol,li,div,h1,h2,h3,h4,h5,h6,form,input,table,tr,td{
margin:0;
padding:0;
}
html{
font-size: 26.67vw;
}
html,body,.cancas-cont{
height: 100%;
height: 100%;
font-size: 1rem;
}
ul,ol{
list-style:none;
}
img{
border: 0;
display: block;
}
a{
text-decoration: none;
display: block;
}
span{
display: block;
}
.cancas-cont{
display: flex;
flex-direction: column;
}
.sign-footer{
width: 100%;
height: 2rem;
position: fixed;
top: 0;
}
.sign-footer{
display: flex;
}
.sign-footer,.sign-header{
background-color: #fff;
}
.cell-top,.cell-bottom{
display: flex;
flex-direction: row-reverse;
width: 50%;
height: 2rem;
text-align: center;
border-bottom: 1px solid #d0cccc;
position: relative;
}
.cell-bottom{
border-left: 1px solid #d0cccc;
}
.cell-bottom span{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
width: 1rem;
color: #72f572;
}
.cell-top span{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
width: 1rem;
color: #cc1313;
}
/* 画布 */
.sign-context{
width: 100%;
height: 100%;
overflow: hidden;
}
/* canvas{
width: 100%;
height: 100%;
} */
.sign-header{
position: fixed;
bottom: 0;
height: 2rem;
display: flex;
justify-content: space-between;
border-top: 1px solid #d0cccc;
width: 100%;
}
.title{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
width: 1rem;
}
.close-con{
margin-right: .4rem;
display: flex;
justify-content: center;
align-items: center;
}
javascript文件
function Signature (param) {
this.param = param;
this.init();
this.paintInit({});
this.addListener();
};
/**
* 对象初始化
*/
Signature.prototype.init = function () {
var clientWidth = document.body.clientWidth || document.documentElement.clientWidth;
var clientHeight = document.body.clientHeight || document.documentElement.clientHeight;
var con = document.createElement('div');
con.id = 'sign-con';
con.className = 'sign-con';
con.style.height = clientHeight + 'px';
document.body.appendChild(con);
var arcHtml =
`<div class="cancas-cont">
<div class="sign-footer">
<div class="cell-top"><span id="rewrite">重写</span></div>
<div class="cell-bottom"><span id="signcommit">提交</span></div>
</div>
<div class="sign-context" id="sign-context"><canvas id="sign-canvas"></canvas></div>
<div class="sign-header">
<div></div>
<span class="title" id="sign-title">电子签名</span>
<div class="close-con" id="sign-close"><i class="addiconfont icon-123"></i></div>
</div>
</div>`
con.innerHTML = arcHtml;
this.con = con;
this.canvas = document.getElementById('sign-canvas');
this.ctx = this.canvas.getContext('2d');
var clientWidth = document.documentElement.clientWidth;
var clientHeight = document.documentElement.clientHeight;
var canvasWidth = Math.floor(clientWidth);
var canvasHeight = Math.floor(clientHeight);
this.canvas.setAttribute('width', canvasWidth + 'px');
this.canvas.setAttribute('height', canvasHeight + 'px');
};
//设置监听事件
Signature.prototype.addListener = function () {
var _this = this;
var point = {
boxTop: 0,
boxLeft: 0,
startX: 0,
startY: 0,
};
var eventObj = {
touchStart: function (ev) {
ev.preventDefault();
var box = _this.canvas.getBoundingClientRect();
var targetTouch = ev.targetTouches[0];
point.boxTop = box.top;
point.boxLeft = box.left;
point.startX = targetTouch.clientX;
point.startY = targetTouch.clientY;
_this.ctx.beginPath();
_this.ctx.moveTo(point.startX - point.boxLeft, point.startY - point.boxTop);
_this.ctx.lineTo(targetTouch.clientX - point.boxLeft, targetTouch.clientY - point.boxTop);
_this.ctx.stroke();
},
touchMove: function (ev) {
ev.preventDefault();
var targetTouch = ev.targetTouches[0];
_this.ctx.beginPath();
_this.ctx.moveTo(point.startX - point.boxLeft, point.startY - point.boxTop);
_this.ctx.lineTo(targetTouch.clientX - point.boxLeft, targetTouch.clientY - point.boxTop);
_this.ctx.stroke();
point.startX = targetTouch.clientX;
point.startY = targetTouch.clientY;
},
//提交/重写
controlEvent: function (ev) {
var targetId = ev.target.id;
if (targetId == 'sign-close') {
alert("路由跳转")
} else if (targetId == 'rewrite') {
_this.ctx.clearRect(0, 0, _this.canvas.width, _this.canvas.height);
} else if (targetId == 'signcommit') {
if (maxX - minX <= 100 || maxY - minY <= 300) {
alert("亲,签名太小啦,请重新输入嘛!!!")
_this.ctx.clearRect(0, 0, _this.canvas.width, _this.canvas.height);
return
}
var signData = _this.canvas.toDataURL();
_this.param.cb.call(null, signData);
};
}
};
this.eventObj = eventObj;
this.canvas.addEventListener('touchstart', eventObj.touchStart, false);
this.canvas.addEventListener('touchmove', eventObj.touchMove, false);
this.con.addEventListener('click', eventObj.controlEvent, false);
};
/**
* 画笔初始化
* @param {Object} opt
*/
Signature.prototype.paintInit = function (opt) {
var paintOpt = opt || {};
this.ctx.lineJoin = 'round';
this.ctx.lineCap = 'round';
this.ctx.strokeStyle = opt.strokeStyle || '#000';
this.ctx.lineWidth = opt.lineWidth || 3;
};
//移除监听
Signature.prototype.removeListener = function () {
this.canvas.removeEventListener('touchstart', this.eventObj.touchStart);
this.canvas.removeEventListener('touchmove', this.eventObj.touchMove);
this.con.removeEventListener('click', this.eventObj.controlEvent);
};
//关闭签名器
Signature.prototype.close = function () {
this.removeListener();
document.body.removeChild(this.con);
};
let arrX = []
let arrY = []
let maxX
let minX
let maxY
let minY
window.onload = function () {
var sign = new Signature({
cb: function (signData) {
let baseAcreage =
(maxX - minX) *
(maxY - minY);
let canvasAcreage = document.getElementById('sign-canvas').width * document.getElementById('sign-canvas').height;
if (canvasAcreage / baseAcreage >= 4) {
alert("亲,签名太小啦,请重新签名嘛!!!");
document.getElementById('rewrite').addEventListener('click', sign.eventObj.controlEvent, false);
} else {
dealImage(signData, 200, (callback) => {
console.log(callback)
})
}
function dealImage (base64, w, callback) {
var newImage = new Image();
var quality = 0.6; //压缩系数0-1之间
newImage.src = base64;
newImage.setAttribute("crossOrigin", 'Anonymous'); //url为外域时需要
var imgWidth, imgHeight;
newImage.onload = function () {
imgWidth = this.width;
imgHeight = this.height;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
if (Math.max(imgWidth, imgHeight) > w) {
if (imgWidth > imgHeight) {
canvas.width = w;
canvas.height = w * imgHeight / imgWidth;
} else {
canvas.height = w;
canvas.width = w * imgWidth / imgHeight;
}
} else {
canvas.width = imgWidth;
canvas.height = imgHeight;
quality = 0.6;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
var base64 = canvas.toDataURL("image/png", quality); //压缩语句
callback(base64)
}
}
sign.removeListener();
},
})
var pad = document.getElementById('sign-context');
pad.addEventListener('touchmove', function (e) {
var ev = e || window.event;
var touch = ev.targetTouches[0];
arrX.push(touch.clientX)
arrY.push(touch.clientY)
maxX = Math.max.apply(null, arrX);
minX = Math.min.apply(null, arrX);
maxY = Math.max.apply(null, arrY);
minY = Math.min.apply(null, arrY);
});
}