vue-signature-pad实现电子签名:包含车型、清屏、保存、笔刷粗细调节、回显图片

参考博客:https://www.cnblogs.com/smile-fanyin/p/16544271.html,里面还包含了橡皮擦功能,因为签名对橡皮擦功能需求不大,所以没有使用。

在做中石油后台管理项目时,遇到了交接班表格要求实现签字效果,在参考上述博客后,在vue3项目中实现了此功能,上源码:

<template>
  <a-modal
    v-model:visible="panelVisible"
    class="signNameModel"
    title="签字"
    width="600"
    height="400"
    size="large"
    :destroy-on-close="true"
    @cancel="cancel"
  >
    <template #default>
      <div class="signWrap">
        <VueSignaturePad
          ref="signaturePadRef"
          width="100%"
          height="100%"
          :options="options"
        />
      </div>
    </template>
    <template #footer>
      <div class="footer flex justify-between">
        <div class="otherSet flex">
          <div class="penTxt">笔刷大小:</div>
          <div
            class="circleWrap"
            :class="{ active: isActive1 }"
            @click="selSize(1)"
          >
            <div class="b1">·</div>
          </div>
          <div
            class="circleWrap"
            :class="{ active: isActive2 }"
            @click="selSize(2)"
          >
            <div class="b2">·</div>
          </div>
          <div
            class="circleWrap"
            :class="{ active: isActive3 }"
            @click="selSize(3)"
          >
            <div class="b3">·</div>
          </div>
        </div>
        <div class="gtnGroup">
          <a-button type="primary" size="small" @click="undo">撤销</a-button>
          <a-button
            type="primary"
            size="small"
            style="margin-left: 20px"
            @click="clear"
            >清屏</a-button
          >
          <a-button
            type="primary"
            size="small"
            style="margin-left: 20px"
            @click="cancel"
            >取消</a-button
          >
          <a-button
            type="primary"
            size="small"
            style="margin-left: 20px"
            @click="save"
            >保存</a-button
          >
        </div>
      </div>
    </template>
  </a-modal>
</template>

<script lang="ts" setup>
import { message } from 'ant-design-vue';
const panelVisible = ref<boolean>(false);
const signaturePadRef = ref();
const options = ref({
  penColor: '#000',
  minWidth: 1, // 控制画笔最小宽度
  maxWidth: 1, // 控制画笔最大宽度
});
const isActive1 = ref<boolean>(true);
const isActive2 = ref<boolean>(false);
const isActive3 = ref<boolean>(false);
const props = defineProps<{
  signVisible: boolean;
}>();
const { signVisible } = toRefs(props);
const emit = defineEmits(['signed']);
// 手写签名按钮的点击
const handleClick = () => {
  panelVisible.value = true;
  isActive1.value = true;
  isActive2.value = false;
  isActive3.value = false;
  options.value = {
    penColor: '#000',
    minWidth: 1,
    maxWidth: 1,
  };
};
// 撤销
const undo = () => {
  signaturePadRef.value.undoSignature();
};
// 清除
const clear = () => {
  signaturePadRef.value.clearSignature();
};
// 取消
const cancel = () => {
  panelVisible.value = false;
  emit('signed');
};
// 保存
const save = () => {
  const { isEmpty, data } = signaturePadRef.value.saveSignature();
  if (!data) return message.error('请先进行签名');
  panelVisible.value = false;
  emit('signed', data);
};
// 调节画笔粗细大小
const selSize = (val:any) => {
  options.value = {
    penColor: '#000',
    minWidth: val,
    maxWidth: val,
  };
  if (val === 1) {
    isActive1.value = true;
    isActive2.value = false;
    isActive3.value = false;
  } else if (val === 2) {
    isActive1.value = false;
    isActive2.value = true;
    isActive3.value = false;
  } else if (val === 3) {
    isActive1.value = false;
    isActive2.value = false;
    isActive3.value = true;
  }
};

watchEffect(() => {
  if (signVisible.value) {
    handleClick();
  }
});
</script>
<style scoped lang="less">
.img-wrap {
  width: 100%;
  height: 164px;
  margin-top: 2px;
  border: 1px solid #ccc;
  img {
    width: 70%;
    height: 100%;
  }
}
.signWrap {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  .signName {
    flex: 1;
    border-top: 1px solid #ccc;
  }
}
.footer {
  height: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  .gtnGroup {
    width: 50%;
    margin-left: 20px;
  }
  .otherSet {
    width: 50%;
    display: flex;
    align-items: center;
    .penTxt {
      width: 70px;
    }
    .selSize {
      width: 70px;
    }
    .el-select__caret {
      position: absolute;
      right: -3px;
    }
    .b1,
    .b2,
    .b3 {
      background: #000;
      border-radius: 50%;
    }
    .circleWrap {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 58px;
      height: 58px;
      cursor: pointer;
      margin-right: 20px;
    }
    .active {
      border: 1px dashed #0074d9;
    }
    .b1 {
      width: 4px;
      height: 4px;
    }
    .b2 {
      width: 6px;
      height: 6px;
    }
    .b3 {
      width: 8px;
      height: 8px;
    }
  }
}
.signNameModel {
  .vxe-modal--content {
    padding: 0 !important;
  }
}
</style>

使用并回显:

<template>
    <div v-if="onShiftPersonUrl" class="img">
            <img class="w-full h-full" :src="onShiftPersonUrl" />
    </div>
    <SignaturePad :sign-visible="signVisible" @signed="signed" />
</template>

<script lang="ts" setup>
import SignaturePad from '@/views/components/Signature.vue';

const onShiftPersonUrl = ref();
const signed = (imgSrc?: any) => {
  signVisible.value = false;
  if (!imgSrc) return;
  onShiftPersonUrl.value = imgSrc;
};
<script/>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值