效果如下,竖屏和横屏
- 第一步安装插件,使用到了SignaturePad
npm install --save signature_pad
- 新建一个vue页面
<template>
<div class="recruit-canvas">
<div class="text-box">请在横屏方向进行签名</div>
<div class="canvas-box" ref="canvasRef">
<canvas ref="canvasMapRef" id="canvas-map" width="100" height="100" />
</div>
<slot name="default" :signatrue="canvasNode">
<div class="btn-box flex-row">
<el-button @click="clearHandle" type="info">清除画布</el-button>
<el-button @click="confirmHandle" type="warning">提交到系统</el-button>
</div>
</slot>
</div>
</template>
<script>
import SignaturePad from "signature_pad";
import { rotateBase64Img } from "@/utils/sign";//这是使用的方法,当手机屏幕是竖屏的时候要旋转图片
export default {
data() {
return {
canvasNode: "",
};
},
created() {
this.$nextTick(() => {
this.initalHandle();
window.addEventListener("resize", this.initalHandle, false);
});
},
methods: {
initalHandle() {
const _canvasBox = this.$refs.canvasRef;
const _canvas = this.$refs.canvasMapRef;
if (!_canvasBox || !_canvas) {
console.warn("DOM节点初始化失败");
return false;
}
_canvas.width = _canvasBox.clientWidth;
_canvas.height = _canvasBox.clientHeight;
const computedOpt = Object.assign(
{},
{
dotSize: 5,
minWidth: 5,//因为有笔锋的效果的,鼠标压力不同显示粗细不同
maxWidth: 7,
penColor: "rgb(0, 0, 0)",
},
);
this.clearHandle();
this.canvasNode = new SignaturePad(_canvas, computedOpt);//这里设置笔的宽度和颜色的样式
},
clearHandle() {
const hasNode = this.canvasNode;
if (hasNode) {
hasNode.clear();
this.$emit("cancelEvent", hasNode);
}
},
async confirmHandle() {
// 重新初始化画布
const canvasNode = this.canvasNode;
if (!canvasNode) {
this.initalHandle();
}
// 是否签字
if (canvasNode.isEmpty()) {
console.warn("您还没有签名");
this.$emit("confirmEvent", canvasNode);
return false;
}
// 图像旋转二次处理
const _boxWidth = window.innerWidth;
const _boxHeight = window.innerHeight;
// let _signImg = null;
const _signImg = canvasNode.toDataURL("image/png", 0.6) || null;//不旋转就是手机横屏
if (_boxWidth < _boxHeight) {
await rotateBase64Img(_signImg, -90, (imgUrlRes) => {
this.$emit("confirmEvent", imgUrlRes); //在这里修改逻辑,返回的是旋转后的database
});
}
},
},
beforeUnmount() {
window.removeEventListener("resize", this.initalHandle, false);
},
};
</script>
<style scoped lang="scss">
.recruit-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
.canvas-box,
.btn-box,
.text-box {
position: absolute;
top: 50%;
z-index: 100;
}
.canvas-box {
left: 20%;
width: 67vw;
height: 80vh;
overflow: hidden;
transform: translateY(-50%);
background-color: #fff;
border: 1px dashed #d4d4d4;
#canvas-map {
width: 100%;
height: 100%;
}
}
.text-box {
background-color: #ffbc0124;
color: #e6a23c;
right: -105% !important;
height: 30px;
line-height: 30px;
}
.btn-box,
.text-box {
left: -15%;
z-index: 1000;
text-align: center;
transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
.del-btn,
.sure-btn {
display: inline-block;
width: 100px;
height: 24px;
margin: 0 10px;
line-height: 24px;
border-radius: 6px;
background-color: #fff;
}
.del-btn {
color: #ff5e00;
}
.sure-btn {
color: #fff;
background: linear-gradient(100deg, #ff4e01 0%, #ffbc01 100%);
}
}
}
@media screen and (orientation: portrait) {
/*竖屏 css*/
}
@media screen and (orientation: landscape) {
/*横屏 css*/
.recruit-canvas {
.canvas-box {
top: 12%;
left: 10%;
width: 80vw;
height: 70vh;
transform: translateY(0);
}
.btn-box {
width: 60%;
top: 86%;
left: 20%;
transform: rotate(0);
}
.text-box {
width: 130%;
top: 1%;
transform: rotate(0);
}
}
}
</style>
3.旋转图片的方法
export const rotateBase64Img = (src, edg, callback) => {
try {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
let imgW = 0; // 图片宽度
let imgH = 0; // 图片高度
let size = 0; // canvas初始大小
if (edg % 90 !== 0) {
throw new Error("旋转角度必须是90的倍数!");
}
edg < 0 && (edg = (edg % 360) + 360);
const quadrant = (edg / 90) % 4; // 旋转象限
const cutCoor = { sx: 0, sy: 0, ex: 0, ey: 0 }; // 裁剪坐标
const image = new Image();
image.src = src;
image.crossOrigin = "anonymous";
image.onload = function () {
imgW = image.width;
imgH = image.height;
size = imgW > imgH ? imgW : imgH;
canvas.width = size * 2;
canvas.height = size * 2;
switch (quadrant) {
case 0:
cutCoor.sx = size;
cutCoor.sy = size;
cutCoor.ex = size + imgW;
cutCoor.ey = size + imgH;
break;
case 1:
cutCoor.sx = size - imgH;
cutCoor.sy = size;
cutCoor.ex = size;
cutCoor.ey = size + imgW;
break;
case 2:
cutCoor.sx = size - imgW;
cutCoor.sy = size - imgH;
cutCoor.ex = size;
cutCoor.ey = size;
break;
case 3:
cutCoor.sx = size;
cutCoor.sy = size - imgW;
cutCoor.ex = size + imgH;
cutCoor.ey = size + imgW;
break;
}
ctx.translate(size, size);
ctx.rotate((edg * Math.PI) / 180);
ctx.drawImage(image, 0, 0);
const imgData = ctx.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey);
if (quadrant % 2 === 0) {
canvas.width = imgW;
canvas.height = imgH;
} else {
canvas.width = imgH;
canvas.height = imgW;
}
ctx.putImageData(imgData, 0, 0);
if (typeof callback === "function") {
callback(canvas.toDataURL("image/png", 0.7));
}
return new Promise((resolve) => {
// 异步操作...
resolve(canvas.toDataURL("image/png", 0.7));
});
};
} catch (e) {
console.log(e);
}
};
以上直接取来用应该是没问题的
参考文章: