合同签名
1.首先先画签名的cavans

<template>
<div class="signature">
<!--touchstart,touchmove,touchend,touchcancel 这-->
<div class="signature__header">
<van-nav-bar
title="电子签名"
@click-left="onClickLeft"
>
<div slot="left">
<van-icon name="arrow-left" size="25px" color="#b6b6b6" />
</div>
</van-nav-bar>
</div>
<div class="signature__zang"></div>
<div>
<div>
<canvas id="canvas" :height="tabListHeight">Canvas画板</canvas>
</div>
<div class="signature__button">
<van-button type="primary"
size="small"
v-on:click="save">保存, 下一步</van-button>
<van-button type="default"
size="small"
v-on:click="clear">清除</van-button>
</div>
</div>
</div>
</template>
<script>
var draw
var preHandler = function (e) {
e.preventDefault()
}
class Draw {
constructor (el) {
this.el = el
this.canvas = document.getElementById(this.el)
this.canvas.width = document.documentElement.clientWidth
this.cxt = this.canvas.getContext('2d')
this.stage_info = this.canvas.getBoundingClientRect()
this.path = {
beginX: 0,
beginY: 0,
endX: 0,
endY: 0
}
}
init (btn) {
var that = this
this.canvas.addEventListener('touchstart', function (event) {
document.addEventListener('touchstart', preHandler, { passive: false })
that.drawBegin(event)
})
this.canvas.addEventListener('touchend', function (event) {
document.addEventListener('touchend', preHandler, { passive: false })
that.drawEnd()
})
this.clear(btn)
}
drawBegin (e) {
var that = this
window.getSelection()
? window.getSelection().removeAllRanges()
: document.selection.empty()
this.cxt.strokeStyle = '#000'
this.cxt.beginPath()
this.cxt.moveTo(
e.changedTouches[0].clientX - this.stage_info.left,
e.changedTouches[0].clientY - this.stage_info.top
)
this.path.beginX = e.changedTouches[0].clientX - this.stage_info.left
this.path.beginY = e.changedTouches[0].clientY - this.stage_info.top
this.canvas.addEventListener('touchmove', function () {
that.drawing(event)
})
}
drawing (e) {
this.cxt.lineTo(
e.changedTouches[0].clientX - this.stage_info.left,
e.changedTouches[0].clientY - this.stage_info.top
)
this.path.endX = e.changedTouches[0].clientX - this.stage_info.left
this.path.endY = e.changedTouches[0].clientY - this.stage_info.top
this.cxt.stroke()
}
drawEnd () {
document.removeEventListener('touchstart', preHandler, { passive: false })
document.removeEventListener('touchend', preHandler, { passive: false })
document.removeEventListener('touchmove', preHandler, { passive: false })
// canvas.ontouchmove = canvas.ontouchend = null
}
clear (btn) {
this.cxt.clearRect(0, 0, this.canvas.width, 600)
}
save () {
return this.canvas.toDataURL('image/png')
}
}
export default {
data () {
return {
msg: 'Welcome to Your Vue.js App',
val: true,
screenWidth: 0,
screenHeight: 0
}
},
mounted () {
draw = new Draw('canvas')
draw.init()
this.screenWidth = document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth
this.screenHeight = document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight
},
computed: {
tabListHeight () {
return this.screenHeight - 100
}
},
methods: {
onClickLeft () {
this.$router.go(-1)
},
clear: function () {
draw.clear()
},
save: function () {
var data = draw.save()
this.$router.push({ name: 'newidentity' })
sessionStorage.setItem('imgs', data)
console.log(111)
console.log(data)
},
mutate (word) {
this.$emit('input', word)
}
}
// data () {
// return {
// msg: 'Just use canvas to draw',
// degree: 0, // 屏幕整体旋转的角度, 可取 -90,90,180等值
// scope: [
// {
// value: 0,
// title: '正常',
// },
// {
// value: 90,
// title: '顺时针旋转90°',
// },
// {
// value: 180,
// title: '顺时针旋转180°',
// },
// {
// value: -90,
// title: '逆时针旋转90°',
// },
// ],
// };
// },
// components: {
// Draw,
// },
// mounted () {
// this.canvasBox = document.getElementById('canvasBox');
// this.initCanvas();
// },
// computed: {
// getHorizontalStyle () {
// console.log(232323)
// const d = document;
// const w = window.innerWidth || d.documentElement.clientWidth || d.body.clientWidth;
// const h = window.innerHeight || d.documentElement.clientHeight || d.body.clientHeight;
// let length = (h - w) / 2;
// let width = w;
// let height = h;
// switch (this.degree) {
// case -90:
// length = -length;
// case 90:
// width = h;
// height = w;
// break;
// default:
// length = 0;
// }
// if (this.canvasBox) {
// this.canvasBox.removeChild(document.querySelector('canvas'));
// this.canvasBox.appendChild(document.createElement('canvas'));
// setTimeout(() => {
// this.initCanvas();
// }, 200);
// }
// return {
// transform: `rotate(${this.degree}deg) translate(${length}px,${length}px)`,
// width: `${width}px`,
// height: `${height}px`,
// transformOrigin: 'center center',
// };
// },
// },
// methods: {
// initCanvas () {
// const canvas = document.querySelector('canvas');
// this.draw = new Draw(canvas, -this.degree);
// },
// clear () {
// this.draw.clear();
// },
// download () {
// this.draw.downloadPNGImage(this.draw.getPNGImage());
// },
// upload () {
// const image = this.draw.getPNGImage();
// const blob = this.draw.dataURLtoBlob(image);
// const url = '';
// const successCallback = (response) => {
// console.log(response);
// };
// const failureCallback = (error) => {
// return this.$toast(res.data.statusText);
// };
// this.draw.upload(blob, url, successCallback, failureCallback);
// },
// },
}
</script>
<style lang="less" scoped>
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
#canvasBox {
display: flex;
flex-direction: column;
height: 100%;
}
canvas {
flex: 1;
cursor: crosshair;
background-color: #f2f2f2;
}
.signature {
height: 100%;
width: 100%;
background-color: #ffffff;
position: relative;
.signature__header {
width: 100%;
height: 46px;
position: fixed;
top: 0;
left: 0;
}
.signature__zang {
width: 100%;
height: 46px;
}
.signature__button {
height: 50px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
}
#keyword-box {
margin: 10px 0;
}
</style>
2.合成
<template>
<div id="identity" class="identity">
<div class="identity__header">
<van-nav-bar
title="签订合同"
@click-left="onClickLeft"
>
<div slot="left">
<van-icon name="arrow-left" size="25px" color="#b6b6b6" />
</div>
</van-nav-bar>
</div>
<div class="identity__zang"></div>
<div class="identity__content" :style="{ height: tabListHeight }">
<div class="identity__content-item">
<div class="identity-bnt van-hairline--top">
<!-- <div class="upphoto"> 上传交款凭证</div> -->
<!-- 上传图片 -->
<!-- <div class="pushphoto">
<img class="pushphoto-add"
v-for="(item,index) of photo"
:key="index"
:src="item"
@click="showimg(item)">
<van-uploader class="pushphoto-add"
:after-read="onRead"
v-if="falses">
<img class="pushphoto-add"
src="../../assets/img/addphoto.png">
</van-uploader>
</div> -->
<!-- <div class="upphoto"> 上传身份证</div>
<div class="pushphoto">
<img class="pushphoto-add"
v-for="(item,index) of photo1"
:key="index"
:src="item"
@click="showimg1(item)">
<van-uploader class="pushphoto-add"
:after-read="onRead1"
v-if="falses1">
<img class="pushphoto-add"
src="../../assets/img/addphoto.png">
</van-uploader>
</div> -->
<div class="info-conter"
ref="infoconter">
//这里是你的合同
<img src="../../assets/img/hetong.png"
id="imgCover"
ref="imgCover">
//这里是你的签名
<img v-show="zou"
:src="ba64"
id="imgUploadX">
<canvas v-show="yincang"
id="can"></canvas>
</div>
<!-- <van-button type="primary" @click="pull">签订合同</van-button> -->
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted () {
this.$nextTick(() => {
this.ba64 = sessionStorage.getItem('imgs');
//this.pull();
this.$toast.loading({
mask: true,
message: '合同签名中,请等待...'
});
//渲染需要一个过程,需要用到定时器,不然手机合成的签名合同是一片黑
setTimeout(()=>{
// console.log(Timer);
this.pull();
},4000);
this.screenWidth = document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth
this.screenHeight = document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight
})
},
computed: {
tabListHeight () {
return this.screenHeight / (this.screenWidth / 10) - 2 - 1.226667 + 'rem'
}
},
data () {
return {
ba64: '',
zou: false,
yincang: false,
enen: false,
frist: '',
second: '',
files: '',
three: '',
dataurls: '',
threeimg: '',
secondimg: '',
fristimg: '',
text1: true,
text2: true,
text3: true,
imgs1: false,
imgs2: false,
imgs3: false,
screenWidth: 0,
screenHeight: 0,
falses: true,
falses1:true,
photo: [],
photo1: [],
photolist: [],
photolist1: [],
}
},
methods: {
// onRead (i) {
// this.photo.push(i.content);
// //console.log(this.photo);
// this.photolist.push(i.file)
// if (this.photo.length >= 3) {
// this.falses = false
// }
// console.log(this.photo)
// },
// onRead1 (i) {
// this.photo1.push(i.content)
// this.photolist1.push(i.file)
// if (this.photo1.length >= 3) {
// this.falses1 = false
// }
// console.log(this.photo1)
// },
// showimg (item) {
// this.show = true
// this.file = item
// },
// showimg1 (item) {
// this.show = true
// this.file1 = item
// },
// 合成图片
pull () {
console.log(this.photolist);
//console.log(this.photolist1);
this.compound();
// setTimeout(()=>{
this.$router.push({ path: '/newesignature' })
// },5000);
},
//这里是签名与合同的渲染合成
compound () {
this.yincang = true
let eleImgUploadX = document.getElementById('imgUploadX')
let eleImgCover = document.getElementById('imgCover')
let can = document.getElementById('can')
let context = can.getContext('2d')
let width = this.$refs.infoconter.offsetWidth
let heigth = this.$refs.infoconter.offsetHeight
let heigths = this.$refs.imgCover.offsetHeight
let hei = this.$refs.imgCover.offsetHeight
can.width = width
can.height = heigths
var devicePixelRatio = window.devicePixelRatio || 1,
backingStoreRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1,
ratio = devicePixelRatio / backingStoreRatio
var oldWidth = can.width;
var oldHeight = can.height;
can.width = oldWidth * ratio
can.height = oldHeight * ratio
can.style.width = oldWidth + 'px'
can.style.height = oldHeight + 'px'
context.scale(ratio, ratio)
console.log(width)
context.drawImage(eleImgCover, 0, 0, width, heigth)
context.drawImage(eleImgUploadX, width * 0.65, hei * 0.8, 95, 80)
console.log(can.toDataURL('image/png'))
let dataurls = can.toDataURL('image/jpeg')
this.dataurls = can.toDataURL('image/jpeg')
this.enen = true
// 转文件flie
let filename = 'canvas.jpg'
let feli = dataURLtoFile(dataurls, filename)
function dataURLtoFile (dataurl, filename) {//将base64转换为文件
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime })
}
this.files = feli
console.log(this.files)
sessionStorage.setItem('files', this.dataurls)
},
onClickLeft () {
this.$router.push({ name: 'openvip' })
}
}
}
</script>
<style lang="less" scoped>
.identity {
width: 100%;
// height: 100%;
overflow: hidden;
position: relative;
img {
width: 100%;
height: 100%;
}
.identity__header {
width: 100%;
height: 46px;
position: fixed;
top: 0;
left: 0;
z-index: 999;
}
.identity__zang {
width: 100%;
height: 46px;
}
.info-conter {
width: 100%;
// height: 100%;
// background-color: white;
// overflow: hidden;
overflow-x: auto;
overflow-y: auto;
position: absolute;
right: 0;
// bottom: -100%;
}
#imgCover {
opacity: 0;
}
.info-conter img {
width: 100%;
}
.identity__content{
width: 100%;
background-color: #ffffff;
overflow: scroll;
-webkit-overflow-scrolling: touch;
.identity__content-item {
// height: 100%;
width: 100%;
.identity-frist {
width: 100%;
height: 180px;
background-color: #f2f2f2;
margin-top: 10px;
margin-bottom: 10px;
text-align: center;
line-height: 180px;
font-size: 18px;
.van-uploader {
width: 100%;
height: 100%;
}
}
}
}
.pushphoto {
width: 100%;
height: 100px;
padding-left: 16px;
padding-bottom: 16px;
// margin-bottom: 20px;
box-sizing: border-box;
display: flex;
.pushphoto-add {
width: 25%;
height: 100%;
margin-right: 10px;
img {
width: 100%;
}
}
}
.identity-bottom {
width: 100%;
height: 118px;
}
.identity-bnt {
width: 100%;
// position: fixed;
// bottom: 0px;
// z-index: 99999;
padding: 20px 20px;
background-color: #ffffff;
box-sizing: border-box;
// height: 118px;
.identity-reset {
margin-bottom: 10px;
}
.van-button {
width: 100%;
}
}
}
</style>
效果:

越努力越幸运

浙公网安备 33010602011771号