效果图
<template>
<div class="signature">
<header>签名</header>
<div class="rect_position" v-if="isShow">
<div class="div_canvas_container">
<canvas id="signCanvas"></canvas>
</div>
</div>
<span class="clear_btn" @click="handelClearEl">清除签名</span>
<button class="confirm_btn" @click="saveImage">确定</button>
</div>
</template>
<script>
export default {
name: 'sign',
data () {
return {
imgsrc: '',
isShow: true
}
},
mounted () {
const _this = this
this.$nextTick(() => {
setTimeout(() => {
_this.initCanvas()
}, 100)
})
},
methods: {
initCanvas() {
let rate = 2
let oCanvas = document.getElementById("signCanvas")
oCanvas.width = oCanvas.offsetWidth * rate
oCanvas.height = oCanvas.offsetHeight * rate
let cxt = oCanvas.getContext("2d")
cxt.fillStyle = "#fff" // 签名版背景颜色
cxt.fillRect(0, 0, oCanvas.width, oCanvas.height)
cxt.lineWidth = 6 * rate // 签名线条粗细
cxt.strokeStyle = "#101010" // 签名线条颜色
let posX = 0 //x坐标
let posY = 0 //y坐标
let position = null
let parentPosintin = oCanvas.getBoundingClientRect()
// 解决canvas有间距 手指落点和实际绘画点有偏移的问题
const offsetT = oCanvas.offsetTop
const offsetL = oCanvas.offsetLeft
// console.log(offsetT, offsetL);
//手指触摸屏幕可记录此时的位置作为起点
oCanvas.addEventListener("touchstart", function(event) {
posX = event.changedTouches[0].clientX
// console.log(posX);
posY = event.changedTouches[0].clientY - parentPosintin.top + 0.5
cxt.beginPath()
cxt.moveTo((posX - offsetL) * rate, (posY - offsetT + 20) * rate)
});
//手指屏滑动画线
oCanvas.addEventListener("touchmove", 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 + 0.5
posY = event.changedTouches[0].clientY - parentPosintin.top + 0.5
cxt.lineTo((posX - offsetL) * rate, (posY - offsetT + 20) * rate)
cxt.stroke()
}
},
// 清除画板
handelClearEl() {
let oCanvas = document.getElementById("signCanvas")
let cxt = oCanvas.getContext("2d")
cxt.clearRect(0, 0, oCanvas.width, oCanvas.height)
setTimeout(() => {
// 清除画板后重新绘制画布
this.initCanvas()
}, 200);
},
//保存为图片
saveImage() {
let oCanvas = document.getElementById("signCanvas")
let imgBase64 = oCanvas.toDataURL("image/png")
oCanvas.toBlob(async (blobObj) => {
var file = new File([blobObj], "pic.png", {
type: blobObj.type,
lastModified: Date.now()
})
this.convertImg(file)
})
},
//旋转图片
convertImg(file) {
// 旋转图片操作不可见
this.isShow = false
let _this = this;
let canvas1 = document.getElementById("signCanvas")
let context1 = canvas1.getContext('2d')
var oReader = new FileReader()
oReader.readAsDataURL(file)
oReader.onload = function (e) {
var img = new Image()
img.src = e.target.result
img.onload = function () {
// 图片原始尺寸
const originWidth = this.width
const originHeight = this.height
// 最大尺寸限制
const maxWidth = 1080,
maxHeight = 1080
// 目标尺寸
let targetWidth = originWidth,
targetHeight = originHeight
// 图片尺寸超过300x300的限制
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
targetWidth = maxWidth
targetHeight = Math.round(
maxWidth * (originHeight / originWidth)
)
} else {
targetHeight = maxHeight
targetWidth = Math.round(
maxHeight * (originWidth / originHeight)
)
}
}
var type = "image/png"
// canvas对图片进行缩放
canvas1.width = targetHeight
canvas1.height = targetWidth
context1.save()
// 旋转90度
// 设置画布旋转的中心点
context1.translate(canvas1.width / 2, canvas1.height / 2)
context1.rotate(-90 * Math.PI / 180)
context1.translate(-canvas1.width / 2, -canvas1.height / 2)
// 吧图片绘制在旋转的中心点
context1.drawImage(img, canvas1.width / 2 - img.width / 2, canvas1.height / 2 - img.height / 2)
// context1.drawImage(img, 0, 0, canvas1.width, canvas1.height)
context1.translate(canvas1.width / 2, canvas1.height / 2)
context1.rotate(90 * Math.PI / 180)
context1.translate(canvas1.width / 2, canvas1.height / 2)
context1.restore()
// 将canvas的透明背景设置成白色
var imageData = context1.getImageData(0,0,canvas1.width,canvas1.height
)
for (var i = 0; i < imageData.data.length; i += 4) {
// 当该像素是透明的,则设置成白色
if (imageData.data[i + 3] == 0) {
imageData.data[i] = 255
imageData.data[i + 1] = 255
imageData.data[i + 2] = 255
imageData.data[i + 3] = 255
}
}
context1.putImageData(imageData, 0, 0)
var dataurl = canvas1.toDataURL(type)
_this.basedata = dataurl
_this.getPolictReceiptImg()
}
}
},
//
getPolictReceiptImg () {
if (window.sessionStorage.getItem('sign')) {
window.sessionStorage.removeItem('sign')
window.sessionStorage.setItem('sign', this.basedata)
} else {
window.sessionStorage.setItem('sign', this.basedata)
}
this.$emit('returnImg')
}
}
}
</script>
<style lang="less" scoped>
.signature {
width: 100vw;
height: 100vh;
box-sizing: border-box;
// padding: 10px 10px 10px 30px;
padding: 10px 10px 10px 20px;
.rect_position {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 16px;
background: linear-gradient(to left, black, black) left top no-repeat,
linear-gradient(to bottom, black, black) left top no-repeat,
linear-gradient(to left, black, black) right top no-repeat,
linear-gradient(to bottom, black, black) right top no-repeat,
linear-gradient(to left, black, black) left bottom no-repeat,
linear-gradient(to bottom, black, black) left bottom no-repeat,
linear-gradient(to left, black, black) right bottom no-repeat,
linear-gradient(to left, black, black) right bottom no-repeat;
background-size: 16px 40px, 40px 16px, 16px 40px, 40px 16px;
/*左边两条线的宽高 上边两条线的宽高 右边两条线的宽高 下边两条线的宽高*/
.div_canvas_container {
width: 100%;
height: 100%;
#signCanvas {
width: 100%;
height: 100%;
background: #FFF;
border: none;
box-sizing: border-box;
// overflow: hidden;
}
}
}
header {
position: absolute;
width: 100px;
height: 30px;
line-height: 30px;
background-color: #ccc;
color: #FFF;
font-size: 14px;
text-align: center;
top: 50%;
right: -16px;
transform: rotate(90deg) translateX(-50%);
}
.clear_btn {
position: absolute;
// top: 27px;
// left: -20px;
top: 70px;
left: -20px;
padding: 7px 10px;
transform: rotate(90deg);
background-color: #FF5D3C;
color: #FFF;
font-size: 14px;
}
.confirm_btn {
position: absolute;
// left: -8px;
// bottom: 20px;
left: -6px;
bottom: 58px;
padding: 7px 10px;
text-align: center;
transform: rotate(90deg);
border: 0;
outline: 0;
font-size: 14px;
}
}
</style>