实现电子签名(vue)
代码如下:
<template>
<div class="canvas-content">
<div :class="{'canvas-container': type == 90 || type == -90, 'canvas-container-vertical': type == 0 || type == 180}">
<canvas id="signCanvas"></canvas>
</div>
<div class="vertical-text" v-if="type == 0 || type == 180">
<p>横屏体验更佳哦!</p>
</div>
<div class="canvas-operation">
<button @click="handelClearEl">清除</button>
<button @click="saveImage">保存</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
imgsrc: '',
type: 0,
}
},
mounted() {
let vm = this;
this.$nextTick(() => {
setTimeout(() => {
vm.greenType()
}, 100)
})
},
methods: {
// 横屏和竖屏下的展示不一样的样式
greenType() {
let that = this;
// 竖屏时
if (window.orientation == 0 || window.orientation == 180) {
// 竖屏时通过type来设置不同样式
this.type = window.orientation;
// 初始化画布
this.initCanvas(window.orientation);
// 横屏时
} else if (window.orientation == 90 || window.orientation == -90) {
// 横屏时通过type来设置不同样式
this.type = window.orientation;
// 初始化画布
this.initCanvas(window.orientation);
}
window.addEventListener("orientationchange", function() {
if (window.orientation == 0 || window.orientation == 180) {
// 在横竖更换后要清除之前的画布
let oCanvas = document.getElementById("signCanvas");
let cxt = oCanvas.getContext("2d");
// 在一个画布的一个矩形区域中清除掉像素,这时的矩形框也清除了
cxt.clearRect(0, 0, oCanvas.width, oCanvas.height);
that.type = window.orientation;
// 加入计时器防止画布还没有渲染就被初始化了,导致找不到canvas
setTimeout(() => {
that.initCanvas(window.orientation);
}, 100)
} else if (window.orientation == 90 || window.orientation == -90){
// 在横竖更换后要清除之前的画布
let oCanvas = document.getElementById("signCanvas");
let cxt = oCanvas.getContext("2d");
// 在一个画布的一个矩形区域中清除掉像素,这时的矩形宽也清除了
cxt.clearRect(0, 0, oCanvas.width, oCanvas.height);
that.type = window.orientation;
setTimeout(() => {
that.initCanvas(window.orientation);
}, 100)
}
}, false);
},
// 初始化画布
initCanvas(type) {
let oCanvas = document.getElementById('signCanvas');
if (type == 0 || type == 180) {
oCanvas.width = oCanvas.offsetWidth;
oCanvas.height = 300;
} else if (type == 90 || type == -90) {
oCanvas.width = oCanvas.offsetWidth;
oCanvas.height = oCanvas.offsetHeight;
}
// 获取画布绘图环境
let cxt = oCanvas.getContext('2d');
// 设置画布绘图背景色
cxt.fillStyle = "#fff";
// 使用fillStyle属性所指的颜色.渐变或模式来填充指定的矩形
cxt.fillRect(0, 0, oCanvas.width, oCanvas.height);
// 指定用于画笔(绘制)路径的颜色
cxt.strokeStyle = "#101010";
// 画笔的大小设置
cxt.lineWidth = 2 * (oCanvas.width/oCanvas.height);
let posX = 0;
let posY = 0;
// 获取canvas的DOMrect对象
let parentPosintin = oCanvas.getBoundingClientRect();
oCanvas.ontouchstart = function(event) {
// 获取手指开始触摸的位移
posX = event.changedTouches[0].clientX ;
// y轴要减去没有画布的部分,并留出.5的距离;
// posY = event.changedTouches[0].clientY - parentPosintin.top + 0.5;
posY = event.changedTouches[0].clientY ;
// 开始画布中的一条新路径(或者子路径的集合)
cxt.beginPath();
// 设置当前位置并开始一条新的子路径。
cxt.moveTo(posX, posY);
}
// // 手指滑动画线
oCanvas.ontouchmove = function (event) {
optimizedMove(event);
}
// 执行一个动画,在下一次重绘之前调用指定回调函数
let requestAnimationFrame = window.requestAnimationFrame;
let optimizedMove = requestAnimationFrame ? function(e) {
requestAnimationFrame(function() {
// 再下一个动画前执行的回调
move(e);
});
} : move;
function move(event) {
// 手指移动后重新获取坐标
posX = event.changedTouches[0].clientX;
posY = event.changedTouches[0].clientY;
// posY = event.changedTouches[0].clientY - parentPosintin.top + 0.5;
// 为当前的子路径添加一条直线,参数为终点坐标
cxt.lineTo(posX, posY);
// 绘制当前路径
cxt.stroke();
}
},
// 清除画布
handelClearEl() {
let oCanvas = document.getElementById("signCanvas");
let cxt = oCanvas.getContext("2d");
// 在一个画布的一个矩形区域中清除掉像素,这时的矩形宽也清除了
cxt.clearRect(0, 0, oCanvas.width, oCanvas.height);
// 所以要重新创建矩形画布
this.initCanvas();
},
// 保存图片
saveImage() {
let oCanvas = document.getElementById("signCanvas");
let cxt = oCanvas.getContext("2d");
// HTMLCanvasElement.toDataURL() 方法返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为96dpi。
let imgBase64 = oCanvas.toDataURL();
this.imgsrc = imgBase64;
// 向父组件传值
this.$emit('returnImageUrl', this.imgsrc);
// 最后清空矩形画布
cxt.clearRect(0, 0, oCanvas.width, oCanvas.height)
},
}
}
</script>
<style lang="less" scoped>
.canvas-content {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1111111;
background: #bbb;
.vertical-text {
p {
color: #ddd;
font-size: 20px;
margin: 40px 0;
text-align: center;
}
}
.canvas-operation {
width: 100%;
height: 40px;
position: fixed;
bottom: 0;
left: 0;
z-index: 111111111;
background: #ccc;
button {
width: 70px;
height: 40px;
background: #aaa;
margin: 0 10px;
outline: none;
&:active {
background: #888;
}
}
}
.canvas-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 40px;
background: green;
#signCanvas {
width: 100%;
height: calc(100% - 40px);
background: #fff;
border: none;
box-sizing: border-box;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
z-index: 1111111112;
}
}
.canvas-container-vertical {
width: 100%;
height: 300px;
position: relative;
top: 0;
left: 0;
background: green;
#signCanvas {
width: 100%;
height: 100%;
background: #fff;
border: none;
box-sizing: border-box;
overflow: hidden;
position: relative;
top: 0;
left: 0;
bottom: 40px;
z-index: 1111111112;
}
}
}
</style>
效果如下:
竖屏
横屏