手写签名
一、安装 二、引入 三、使用 vue-signature-pad 完成签批功能 四、解构出data为base64编码的图片 一、图片实现横屏
使用案例图
一、安装
npm i vue- signature- pad@2 .0 .5
二、引入
* mian. js*
import VueSignaturePad from 'vue-signature-pad'
Vue . use ( VueSignaturePad )
三、使用 vue-signature-pad 完成签批功能
< template>
< div id= "app" >
< div style= "background: #fff" >
< vue- signature- pad
id= "signature"
width= "95%"
height= "400px"
ref= "signaturePad"
: options= "options"
/ >
< / div>
< button @click = "save" > 保存< / button>
< button @click = "resume" > 重置< / button>
< / div>
< / template>
< script>
export default {
name: 'App' ,
data ( ) {
return {
options: {
penColor: '#000' ,
} ,
}
} ,
methods: {
save ( ) {
const { isEmpty, data } = this . $refs. signaturePad. saveSignature ( )
console. log ( isEmpty)
console. log ( data)
} ,
resume ( ) {
this . $refs. signaturePad. clearSignature ( )
} ,
} ,
}
< / script>
< style lang= "scss" >
html,
body {
padding: 0 ;
margin: 0 ;
}
#app {
width: 100 vw;
height: 100 vh;
background: #ececec;
}
< / style>
四、解构出data为base64编码的图片
< template>
< div id= "app" >
< div style= "background: #fff" >
< vue- signature- pad
id= "signature"
width= "95%"
height= "300px"
ref= "signaturePad"
: options= "options"
/ >
< / div>
< div v- for = "(item, index) in imgList" : key= "index" >
< img : src= "item.src" alt= "" width= "100" / >
< / div>
< button @click = "save" class = "btn" > 保存< / button>
< button @click = "resume" class = "btn" > 重置< / button>
< / div>
< / template>
< script>
export default {
name: 'App' ,
data ( ) {
return {
options: {
penColor: '#000' ,
} ,
imgList: [ ] ,
}
} ,
methods: {
save ( ) {
const { isEmpty, data } = this . $refs. signaturePad. saveSignature ( )
this . imgList. push ( {
src: data,
} )
let res = this . dataURLtoFile ( data, 'demo' )
console. log ( res)
} ,
resume ( ) {
this . $refs. signaturePad. clearSignature ( )
} ,
dataURLtoFile ( dataurl, filename) {
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 } )
} ,
} ,
}
< / script>
< style lang= "scss" >
html,
body {
padding: 0 ;
margin: 0 ;
}
#app {
width: 100 vw;
height: 100 vh;
background: #ececec;
}
. btn {
width: 35 % ;
color: #fff;
background: #5 daaf3;
border: none;
height: 40 px;
border- radius: 20 px;
margin- top: 20 px;
margin- left: 40 px;
}
< / style>
一、图片实现横屏
< template>
< div id= "app" >
< div style= "background: #fff" >
< vue- signature- pad
id= "signature"
width= "95%"
height= "300px"
ref= "signaturePad"
: options= "options"
/ >
< / div>
< div v- for = "(item, index) in imgList" : key= "index" >
< img : src= "item.src" alt= "" width= "100" / >
< / div>
< div class = "buttons" >
< button @click = "save" class = "btn" > 保存< / button>
< button @click = "resume" class = "btn" > 重置< / button>
< / div>
< / div>
< / template>
< script>
export default {
name: 'App' ,
data ( ) {
return {
options: {
penColor: '#000' ,
} ,
imgList: [ ] ,
fileList: [ ] ,
}
} ,
methods: {
save ( ) {
const { isEmpty, data } = this . $refs. signaturePad. saveSignature ( )
this . rotateBase64Img ( data, 90 , ( res) = > {
console. log ( res)
this . fileList. push ( {
file: this . dataURLtoFile ( res, 'sign' ) ,
name: 'sign' ,
} )
this . imgList. push ( {
src: res,
} )
} )
} ,
resume ( ) {
this . $refs. signaturePad. clearSignature ( )
} ,
dataURLtoFile ( dataurl, filename) {
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 } )
} ,
rotateBase64Img ( src, edg, callback) {
var canvas = document. createElement ( 'canvas' )
var ctx = canvas. getContext ( '2d' )
var imgW
var imgH
var size
if ( edg % 90 != 0 ) {
console. error ( '旋转角度必须是90的倍数!' )
throw '旋转角度必须是90的倍数!'
}
edg < 0 && ( edg = ( edg % 360 ) + 360 )
const quadrant = ( edg / 90 ) % 4
const cutCoor = { sx: 0 , sy: 0 , ex: 0 , ey: 0 }
var image = new Image ( )
image. crossOrigin = 'anonymous'
image. src = src
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 )
var 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 )
callback ( canvas. toDataURL ( ) )
}
} ,
} ,
}
< / script>
< style lang= "scss" >
html,
body {
padding: 0 ;
margin: 0 ;
}
#app {
width: 100 vw;
height: 100 vh;
background: #ececec;
}
. btn {
width: 35 % ;
color: #fff;
background: #5 daaf3;
border: none;
height: 40 px;
border- radius: 20 px;
margin- top: 20 px;
margin- left: 40 px;
}
< / style>