canvas图片旋转扩展出原生JS实现移动端横竖屏手写签名示例
前提知识
canvas是提供了各种各样的接口去控制画布,比如旋转rotate方法。
这里的旋转并不是真的把这个画布旋转了,例如ctx.rotate(90 * Math.PI / 180)顺时针旋转90°了,并不是说我们在页面上就会看到canvas旋转了90°。我们可以理解为其实canvas是有两个部分组成的,一个是肉眼看得到的画布,一个是用于操作的虚拟画布,我们所有在虚拟画布上的动作都会映射到真实画布中去。
旋转画布的原点默认画布的左上角(0,0)点,如图:

总结下,常用画布相关的知识点:
- 1.旋转画布的原点默认画布的左上角(0,0)点,可以使用ctx.translate(x, y)方法移动画布原点;
- 2.ctx.rotate(90 * Math.PI / 180)顺时针旋转90°,ctx.rotate(-90 * Math.PI / 180)逆时针旋转90°;
- 3.context.drawImage方法的使用,如下:
语法一-在画布上定位图像:
context.drawImage(img,x,y);
语法二-在画布上定位图像,并规定图像的宽度和高度:
context.drawImage(img,x,y,width,height);
语法三-剪切图像,并在画布上定位被剪切的部分:
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
参数值:
| 参数 | 描述 |
|---|---|
| img | 规定要使用的图像、画布或视频。 |
| sx | 可选。开始剪切的 x 坐标位置。 |
| sy | 可选。开始剪切的 y 坐标位置。 |
| swidth | 可选。被剪切图像的宽度。 |
| sheight | 可选。被剪切图像的高度。 |
| x | 在画布上放置图像的 x 坐标位置。 |
| y | 在画布上放置图像的 y 坐标位置。 |
| width | 可选。要使用的图像的宽度。(伸展或缩小图像) |
| height | 可选。要使用的图像的高度。(伸展或缩小图像) |
参考地址:《HTML5 canvas drawImage() 方法》。
- 4.会使用canvas的save和restore方法。
save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。 restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。
示例:
ar canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
context.lineWidth = "10";
context.strokeStyle = "#fe9901";
context.translate(canvas.width / 2, canvas.height / 2);
context.rotate( 30 / 180 * Math.PI);
context.beginPath();
context.moveTo(0, -180);
context.lineTo(0, -200);
context.stroke();
context.rotate( 30 / 180 * Math.PI);
context.beginPath();
context.moveTo(0, -140);
context.lineTo(0, -160);
context.stroke();
没有使用save,restore,第一次绘制时画布旋转30度,然后按照坐标绘制直线,第二次绘制在第一次基础上继续绘制,旋转30度,实际上相对于起点,旋转了60. 所以画出来两条直线不在一条指线上。
context.save();
context.rotate( 30 / 180 * Math.PI);
context.beginPath();
context.moveTo(0, -180);
context.lineTo(0, -200);
context.stroke();
context.restore(); context.rotate( 30 / 180 * Math.PI);
context.beginPath();
context.moveTo(0, -140);
context.lineTo(0, -160);
context.stroke();
第二次绘制加入save和restore, 再第一次绘制后,resore到起始状态,也就是现在画布又回到了0度位置,而不是30度,所以第二次绘制是从0度开始绘制,绘制出来应该和第一次的直线在一条指线上。
canvas移动与旋转示例
首先我们用如下图片绘制到canvas画布中,然后我们要保存旋转后的图片,如图所示。
画布图片:

旋转后保存的图片:

demo代码:
<!DOCTYPE html>
<html>
<head>
<title>canvas移动与旋转</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%;
}
.canvasparent {
width: 100px;
height: 200px;
margin: 100px auto 20px;
border: 1px solid #cccccc;
box-sizing: content-box;
position: relative;
}
#canvas {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 200px;
border-top-left-radius: 30px;
} </style>
</head>
<body>
<div class="canvasparent" id="canvasparent">
<canvas id="canvas"></canvas>
</div>
<img src="" id="img" style="border: 1px solid #ccc"/>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 100;
canvas.height = 200;
var img = new Image();
img.src = './images/1.jpg';
img.onload = function() {
ctx.drawImage(img,0,0,100,200);
var imgSRC = canvas.toDataURL('image/png', 1);
var img2 = new Image();
img2.src = imgSRC;
img2.onload = function() {
var clipCanvas = document.createElement("canvas");
var ctx2 = clipCanvas.getContext('2d');
clipCanvas.width = 200;
clipCanvas.height = 100;
ctx2.translate(0,100);
ctx2.rotate(-90 * Math.PI / 180);
ctx2.drawImage(img2,0,0,100,200);
var imgSRC2 = clipCanvas.toDataURL('image/png', 1);
document.getElementById('img').src = imgSRC2;
}
}
</script>
</html>
当然上面使用了translate和rotate,我们只有rotate和drawImage也是可以的,修改的JS代码如下:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 100;
canvas.height = 200;
var img = new Image();
img.src = './images/1.jpg';
img.onload = function() {
ctx.drawImage(img,0,0,100,200);
var imgSRC = canvas.toDataURL('image/png', 1);
var img2 = new Image();
img2.src = imgSRC;
img2.onload = function() {
var clipCanvas = document.createElement("canvas");
var ctx2 = clipCanvas.getContext('2d');
clipCanvas.width = 200;
clipCanvas.height = 100;
ctx2.rotate(-90 * Math.PI / 180);
ctx2.drawImage(img2,-100,0,100,200);
var imgSRC2 = clipCanvas.toDataURL('image/png', 1);
document.getElementById('img').src = imgSRC2;
}
}
手写签名demo
html代码:
<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>
CSS代码:
html,body {
padding:0;
margin:0;
width: 100%;
height: 100%;
}
.text-center {
text-align: center;
}
#signature-button {
display: block;
margin: 0 auto;
}
#signature-img {
width: 200px;
height: 100px;
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: #cccccc;
box-sizing: border-box;
text-align: center;
}
.demo-top-info .return {
padding-left: 5px;
height: 40px;
line-height: 40px;
position: absolute;
left: 10px;
display: inline-block;
}
.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 40px 0;
}
.canvas-parent {
width: 100%;
height: 100%;
}
.demo-bottom-info {
position: absolute;
bottom:0;
left:0;
width: 100%;
height: 40px;
background: #cccccc;
padding: 0 2%;
box-sizing: border-box;
overflow: hidden;
}
#clean_canvas {
float: left;
font-size: 18px;
margin-top: 2px;
background: #f8f8f8;
border: 1px solid #ddd;
padding: 5px 10px;
border-radius: 4px;
}
#sure_canvas {
float: right;
padding: 3px 0;
background: #00005F;
padding: 5px 10px;
border: 1px solid #00005F;
border-radius: 4px;
color: #fff;
margin-top: 3px;
}
#canvas2 {
position: absolute;
top: 0;
left:0;
z-index: 999;
margin-left: 40px;
}
JS代码:
// 手绘签名类
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 = 1;
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 = 1;
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);
}
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) {
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);
完整的demo代码:
<!DOCTYPE html>
<html>
<head>
<title>手写签名demo</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;
}
#signature-img {
width: 200px;
height: 100px;
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: #cccccc;
box-sizing: border-box;
text-align: center;
}
.demo-top-info .return {
padding-left: 5px;
height: 40px;
line-height: 40px;
position: absolute;
left: 10px;
display: inline-block;
}
.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 40px 0;
}
.canvas-parent {
width: 100%;
height: 100%;
}
.demo-bottom-info {
position: absolute;
bottom:0;
left:0;
width: 100%;
height: 40px;
background: #cccccc;
padding: 0 2%;
box-sizing: border-box;
overflow: hidden;
}
#clean_canvas {
float: left;
font-size: 18px;
margin-top: 2px;
background: #f8f8f8;
border: 1px solid #ddd;
padding: 5px 10px;
border-radius: 4px;
}
#sure_canvas {
float: right;
padding: 3px 0;
background: #00005F;
padding: 5px 10px;
border: 1px solid #00005F;
border-radius: 4px;
color: #fff;
margin-top: 3px;
}
#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 = 1;
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 = 1;
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);
}
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) {
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>
canvas图片旋转扩展出原生JS实现移动端横竖屏手写签名示例的更多相关文章
- 【原】js检测移动端横竖屏
摘要:上周做了一个小项目,但是要放到我们的app上,然而需要横竖屏使用不同的样式.横屏一套,竖屏一套.调用了手机APP那里的api,可是他们那里ios和安卓返回的不一样. 各种头疼.于是用了css3的 ...
- JS检测移动端横竖屏
(function () { var supportOrientation = (typeof window.orientation == ...
- HTML 5 +CSS3 + 原生js 做(雪花全屏飘落 + 3d旋转图)
原文:HTML 5 +CSS3 + 原生js 做(雪花全屏飘落 + 3d旋转图) 3d旋转图:主要用css3中transform属性中的rotate,translate;以及用来做舞台效果的 pers ...
- 用js实现web端录屏
用js实现web端录屏 原创2021-11-14 09:30·无意义的路过 随着互联网技术飞速发展,网页录屏技术已趋于成熟.例如可将录屏技术运用到在线考试中,实现远程监考.屏幕共享以及录屏等:而在我们 ...
- canvas画布实现手写签名效果
最近项目中涉及到移动端手写签名的功能需求,将实现代码记录于此,供小伙伴们参考指摘哦~ HTML代码: <!--手写区--> <div class="mSign_signMa ...
- js判断手机的横竖屏调整样式
在移动端,我们经常遇到横竖屏的问题,所以我们改如何判断或针对横竖屏来写代码呢.首先需要在head中加入如下代码: <meta name="viewport" content= ...
- Blazor组件自做二 : 使用JS隔离制作手写签名组件
Blazor组件自做二 : 使用JS隔离制作手写签名组件 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazor组件自做一 : 使用JS隔离 ...
- uni-app通过canvas实现手写签名
分享一个uni-app实现手写签名的方法 具体代码如下: <template> <view > <view class="title">请在下面 ...
- js移动端横竖屏检测
方法一:用resize事件来判断,利用屏幕的宽高比,来判断横竖屏 (兼容性较好) (function () { var updateOrientation = function () { var or ...
- 原生 JS 实现移动端 Touch 滑动反弹
什么是 Touch滑动?就是类似于 PC端的滚动事件,但是在移动端是没有滚动事件的,所以就要用到 Touch事件结合 js去实现,效果如下: 1. 准备工作 什么是移动端的 Touch事件?在移动端 ...
随机推荐
- 洛谷P1365
WJMZBMR打osu! / Easy 题目背景 原 维护队列 参见 P1903 题目描述 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:( 我们来简化一下这个游戏的规则 有 ...
- 基于Java“萌宠之家”宠物综合服务平台设计实现(源码+lw+部署文档+讲解等)
\n文末获取源码联系 感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询 系统介绍: 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面 ...
- oeasy教您玩转vim - 40 - # 复制粘贴
复制粘贴 回忆上节课内容 我们上次的内容是粘贴 小写p意味着在光标下面或者后面粘贴 大写P意味着在光标上面或者前面粘贴 p的意思是放上去,就是put 把什么放上去呢? 把 reg 中 " ...
- java面试一日一题:rabbitMQ如何保证消息不丢失
问题:请讲下rabbitMQ如何保证消息不丢失 分析:该问题属于概念题,同时也是一个设计方面的题,牵扯到部分设计层面的东西: 回答要点: 主要从以下几点去考虑, 1.rabbitMQ在保证消息不丢失方 ...
- 怎么使用github action定时运行js脚本?
github action是使用yaml文件来做到CI/CD的,文件位置存放在 .github/workflows,yaml文件内容如下: name: ncatest.cx.js on: push: ...
- hive测试数据洗刷
hive测试--HIVE数据分析 测试使用虚拟机中的hive 环境:虚拟机+jdk+hadoop+hive+mysql 题目: 1.数据导入: 要求将样表文件中的(sales_sample_20 ...
- RPA+ddddocr识别图片验证码
上篇我们已经使用python识别了验证码,接下来用RPA接收python识别验证码结果进行登录 1.RPA首先安装python包 ddddocr 2.RPA新建一个python模块 编写代码 impo ...
- 【RabbitMQ】12 日志监控 & 消息追踪
一.日志和监控 RabbitMQ日志存放目录 [root@localhost ~]# ll /var/log/rabbitmq/ 总用量 176 -rw-r-----. 1 rabbitmq rabb ...
- 【Binary】XShell6 无法使用的解决办法
感谢博主的解决方案: https://www.cnblogs.com/pinkpolk/articles/13554445.html 首先需要安装VsCode,并且安装一个[Hex Editor]的插 ...
- 【Hibernate】Re04 JPA规范使用
都忘了前面一些小前提,就是数据库需要是存在的,不过写链接参数都会写上的 JPA实现就是和Hibernate类似,也需要对应的配置文件等等... 1.配置文件必须命名[persistence.xml]且 ...