使用vue-esign实现手机签名

·  阅读 109

使用vue-esign实现手机签名

ps:vue-esign只适用vue2,vue3可以使用vue-signature-pad

这里先附上文档地址

www.npmjs.com/package/vue…

1.下载

$ npm install vue-esign
复制代码

2.引入

2.1 全局引入
//main.js文件
//引入
import vueEsign from "vue-esign";
Vue.use(vueEsign)
复制代码
2.2 组件内引入
<script>
//引入
import vueEsign from "vue-esign";
//注册组件
export default {
    ...
    components: {vueEsign}
}
</script>
<template>
/*使用*/
<vue-esign></vue-esign>
</template>
复制代码

3.使用案例

签名板在手机打开,默认是竖屏,如果旋转屏幕(前提是未锁定屏幕方向),签名板会也会变成横向。

3.1效果和源码

image.png

image.png

<template>
  <div id="sign" v-loading="loading">
    <vue-esign
      class="esign"
      ref="esign"
      v-if="showPad"
      :width="padWidth"
      :height="padHeight"
      :isCrop="isCrop"
      :lineWidth="lineWidth"
      :lineColor="lineColor"
      :bgColor="bgColor"
    ></vue-esign>
    <div class="text-green tip">*请在签名板上进行签名,并保持字迹清晰</div>
    <div class="btn-group btns">
      <pas-btn
        @click="handleReset"
        width="100px"
        height="30px"
        fontSize="16px"
        color="grey"
        radius="0.4rem"
        >清空</pas-btn
      >
      <pas-btn
        color="green"
        width="100px"
        height="30px"
        fontSize="16px"
        @click="handleGenerate"
        radius="0.4rem"
        >确定</pas-btn
      >
    </div>
    <div class="toast" v-show="showToast">
      {{ msg }}
    </div>
  </div>
</template>

<script>
import vueEsign from "vue-esign";
export default {
  name: "Sign",
  components: {
    vueEsign,
  },
  data() {
    return {
      lineWidth: 3, //笔画的粗细
      lineColor: "#000000", //画笔颜色
      bgColor: "", //背景颜色
      resultImg: "",
      isCrop: true,  //是否将白色多余部分裁掉
      showPad: false,
      padWidth: document.body.clientWidth - 0.8 * this.$rem,
      padHeight: 240,
      staffCode: sessionStorage.getItem("staffCode"),
      msg: "请先签字再提交",
      showToast: false,
      originProtrait: window.matchMedia("(orientation: portrait)").matches,
      loading: false,
    };
  },
  methods: {
    handleReset() {
      this.$refs["esign"].reset(); //清空画布
    },
    handleGenerate() {
      this.loading = true;
      // 获取base64
      this.$refs.esign
        .generate()
        .then((res) => {
          // 转成文件
          const file = this.dataURLtoFile(res, "签名照.png");
          /*
           ...上传文件操作
          */
        })
        .catch(() => {
          this.showToast = true;
          this.loading = false;
          setTimeout(() => {
            this.showToast = false;
            this.msg = "请先签字再提交";
          }, 1000);
          // 画布没有签字时会执行这里,报'Not Signned'
        });
    },
    dataURLtoFile: function (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 });
    }
  },
  mounted() {
    this.loading = false;
    this.staffCode = this.$route.query.staffCode;
    this.padHeight = window.matchMedia("(orientation: portrait)").matches
      ? 240
      : document.body.clientHeight - 85;
    this.showPad = true;
    window.onorientationchange = () => {
      this.loading = true;
      document.location.reload();
    };
  },
};
</script>
<style lang="scss">
#sign {
  position: relative;
  padding: 0.5rem 0.4rem;
  canvas {
    box-shadow: 0px 0px 21px 0px rgba(92, 124, 187, 0.27);
  }
  .toast {
    display: inline-block;
    padding: 0.15rem;
    position: absolute;
    color: #fff;
    background-color: rgba(0, 0, 0, 0.7);
    border-radius: 10px;
    top: calc(50% - 1rem);
    left: calc(50% - 0.8rem);
    transition: 0.3s;
  }
  .tip {
    margin-top: 0.2rem;
  }
  .btns {
    margin-top: 0.27rem;
  }
}
@media screen and (orientation: landscape) {
  #sign {
    padding: 0.1rem 1rem;
  }
}
</style>
复制代码
3.2几个关键点:
3.2.1 签名板的宽高设置

因为签名板是mounted阶段就已经生成了,这时候没有办法通过width和height参数来修改宽高了。所以需要修改宽高,可以使用v-if使签名板先不渲染,设置了宽高之后,再进行渲染。这里我用了showPad来控制。然后旋转屏幕时,重新加载页面,达到签名板随着屏幕旋转的效果。window.matchMedia("(orientation: portrait)").matches用来判断页面是否是竖屏,竖屏则会返回true。

this.padHeight = window.matchMedia("(orientation: portrait)").matches
      ? 240
      : document.body.clientHeight - 85;
    this.showPad = true;
    window.onorientationchange = () => {
      this.loading = true; //显示loading
      document.location.reload();
    };
复制代码
3.2.2 isCrop属性

isCrop设置为true,可以使生成图片去掉留白部分。想象一下有些人可能会将字签到角落里,如果没有设置isCrop属性,生成的图片就会不太美观。

3.2.3 生成图片

文档已经写了,生成的图片是base64格式,但是一般传给后端都会使用File格式的文件,所以需要先将base64转为File,用了dataURLtoFile方法

dataURLtoFile: function (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 });
    },
复制代码
3.2.4 横竖屏样式

使用媒体查询可以根据手机屏幕当前的横竖屏状态设置不同样式

@media screen and (orientation: landscape) {
    /* ... 横屏*/
}

@media screen and (orientation: portrait) {
    /* ... 竖屏 */
}
复制代码
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改