在前端开发的日常工作中,我们常常会遇到需要用户进行在线签名的需求,比如电子合同签署、表单确认等场景。最近,我在项目里使用了一款极为好用的 Vue2 在线签名组件,今天就来和大家分享一下使用心得。
效果图
上代码 在 views 下将一个vue文件比如。sign.vue
<template>
<div class="page">
<el-button type="primary" @click="openSign()">签 名</el-button>
<SignImgDialog v-if="signVisible" ref="SignImg" :lineWidth='3' :isDefault='0' @close="closeDialog" />
</div>
</template>
<script>
import SignImgDialog from '@/components/SignImgDialog'
export default {
components: { SignImgDialog },
props: {
user: {
type: Object,
default: () => {
return {}
}
}
},
data() {
return {
signVisible: false,
signImg: ''
}
},
methods: {
closeDialog() {
this.signVisible = false
},
openSign() {
this.signVisible = true
this.$nextTick(() => {
this.$refs.SignImg.init()
})
},
}
}
</script>
<style lang="scss" scoped>
.userInfo {
height: 100%;
overflow: hidden;
>>> .el-tabs__nav-scroll {
padding-top: 0 !important;
}
}
.sign {
padding: 20px 50px 0px 50px;
}
.add-sign {
position: relative;
height: 160px;
background-color: rgb(247, 247, 247);
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
&.active {
border: 1px solid #1890ff;
box-shadow: 0 0 6px rgba(6, 58, 108, 0.26);
color: #1890ff;
.btn,
.icon-checked {
display: block;
}
}
.add-button {
position: absolute;
display: none;
}
.add-icon {
font-size: 50px;
color: rgb(157, 158, 159);
}
.sign-img {
width: 100%;
height: 100%;
border-radius: 10px;
}
}
.add-sign:hover .add-button {
display: flex;
width: 100%;
height: 100%;
border-radius: 10px;
background-color: rgba(157, 158, 159, 0.8);
justify-content: center;
align-items: center;
}
.icon-checked1 {
display: block;
width: 20px;
height: 20px;
border: 20px solid #1890ff;
border-left: 20px solid transparent;
border-top: 20px solid transparent;
border-bottom-right-radius: 10px;
position: absolute;
transform: scale(0.8);
right: -5px;
bottom: -5px;
i {
position: absolute;
top: -4px;
left: -4px;
font-size: 24px;
color: #fff;
transform: scale(0.8);
}
}
.sign-item {
margin-bottom: 20px;
}
</style>
然后再src下创建 components/SignImgDialog.vue
<template>
<div>
<el-dialog title="请签名" class="JNPF-dialog JNPF-dialog_center sign-dialog"
:closeOnClickModal='false' :visible.sync="signVisible" append-to-body width="600px">
<div class="sign-main-box">
<vue-esign ref="esign" :height='300' :width="560" :lineWidth="lineWidth" />
<div class="tip" v-show="showTip">请在此区域使用鼠标手写签名</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleReset">清空</el-button>
<el-button type="primary" :loading="loading" @click="handleGenerate()">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { createSign } from '@/api/permission/userSetting'
import vueEsign from 'vue-esign'
export default {
name: 'SignImgDialog',
components: { vueEsign },
props: {
lineWidth: {
required: true,
type: Number
},
isDefault: {
required: true,
type: Number
},
userInfo: {
type: Object,
default() {
return {}
}
},
type: {
type: Number,
default: 0
}
},
data() {
return {
signVisible: false,
loading: false,
signImg: '',
showTip: true
}
},
methods: {
init() {
this.handleReset()
this.signVisible = true
this.showTip = true
this.$nextTick(() => {
this.$watch(
() => {
return this.$refs.esign.hasDrew
},
(val) => {
this.showTip = !val
}
)
})
},
handleReset() {
this.signImg = ''
this.$nextTick(() => {
this.$refs.esign && this.$refs.esign.reset()
})
},
handleGenerate() {
this.loading = true
this.$refs.esign.generate().then(res => {
if (res) this.signImg = res
if (this.type == 1) {
this.signVisible = false
this.loading = false
return this.$emit('close', this.signImg)
}
let query = {
signImg: this.signImg,
isDefault: this.isDefault
}
createSign(query).then(res => {
if (this.isDefault == 0) {
this.$message({
message: res.msg,
type: 'success',
duration: 1500
})
if (!this.userInfo.signImg) this.$store.commit('user/SET_USERINFO_SIGNIMG', this.signImg)
}
if (this.isDefault == 1) {
this.$store.commit('user/SET_USERINFO_SIGNIMG', this.signImg)
}
this.signVisible = false
this.loading = false
this.$emit('close', this.signImg)
this.handleReset()
}).catch(err => {
this.signVisible = false
this.loading = false
this.$emit('close')
this.handleReset()
})
}).catch(err => {
this.loading = false
this.$message.warning("请签名")
})
},
}
}
</script>
<style lang="scss" scoped>
.sign-dialog {
>>> .el-dialog__body {
overflow: hidden;
height: 320px;
overflow: auto;
overflow-x: hidden;
padding: 23px 14px 2px !important;
}
}
.sign-main-box {
border: 1px solid rgb(224, 238, 238);
width: 100%;
height: 300px;
background-color: rgb(247, 247, 247);
display: flex;
justify-content: center;
align-items: center;
margin-top: -10px;
margin-bottom: -10px;
position: relative;
.tip {
height: 300px;
line-height: 300px;
text-align: center;
position: absolute;
left: 0;
top: 0;
right: 0;
color: #9d9d9f;
font-size: 16px;
pointer-events: none;
}
}
</style>
是基于 vue-esign 实现的记得 npm install
ok 可以运行尝试了。
这款 Vue2 在线签名组件在功能、易用性和兼容性等方面都表现出色,为我们的项目开发带来了极大的便利。在未来的工作中,随着业务需求的不断拓展,我们也期待该组件能够持续更新和完善,比如增加更多的签名特效、支持多人签名等功能。同时,我也希望将这款好用的组件推荐给更多的前端开发者,让大家在遇到类似需求时能够少走弯路,共同提升前端开发的效率和质量。