最近项目组要求做一个移动端手写签名的组件,效果图如下

去查了很多资料,也借鉴了很多别人写好的例子,最终完成,记录一下

因为需要横屏签名,所以有监听手机屏幕,如果是手机屏幕锁定的情况下就通过代码旋转页面div实现横屏效果,如果手机屏幕自己旋转了,那就直接正常显示

项目签名的canvas是在sign-canvas组件的基础上修改的https://github.com/richerdyoung/vue-sign-canvas,同时横屏显示借鉴了关于移动端页面强制竖屏https://www.cnblogs.com/daniao11417/p/9524374.html 文章,旋转base64是参考canvas实现手写签名并旋转base64图片https://www.shangmayuan.com/a/5e1c769abd854f489ea8baf6.html文章,修修补补最后做出了上图效果,记录一下,格式上面小细节还不太完善,后面再修改

packages文件直接去https://github.com/richerdyoung/vue-sign-canvas链接下载后复制过来就可以了,复制之后去自己项目的main.js进行组件全局注册,注册完成在自己页面使用即可

//全局注册 main.js
import SignCanvas from 'sign-canvas';

Vue.use(SignCanvas)

这个是main.vue中我改动后的代码

const l = this.canvas.offsetLeft;

const t = this.canvas.offsetTop;加了这两个去矫正手指落点偏差

bindEvent() {
      // pc事件
      //鼠标按下 => 下笔
      this.canvas.addEventListener("mousedown", e => {
        e && e.preventDefault() && e.stopPropagation();
        this.writeBegin({
          x: e.offsetX || e.clientX,
          y: e.offsetY || e.clientY
        });
      });

      //书写过程 => 下笔书写
      this.canvas.addEventListener("mousemove", e => {
        e && e.preventDefault() && e.stopPropagation();
        this.config.isWrite && this.writing({ x: e.offsetX, y: e.offsetY });
      });

      //鼠标松开 => 提笔
      this.canvas.addEventListener("mouseup", e => {
        e && e.preventDefault() && e.stopPropagation();
        this.writeEnd({ x: e.offsetX, y: e.offsetY });
      });

      //离开书写区域 => 提笔离开
      this.canvas.addEventListener("mouseleave", e => {
        e && e.preventDefault() && e.stopPropagation();
        this.writeEnd({ x: e.offsetX, y: e.offsetY });
      });

      // app事件
      //手指按下 => 下笔
      this.canvas.addEventListener("touchstart", e => {
        e && e.preventDefault() && e.stopPropagation();
        const touch = e.targetTouches[0];
        // 这个是为了解决移动端手指落点偏移问题
        const l = this.canvas.offsetLeft;
        const t = this.canvas.offsetTop;
        // const t=0
        this.writeBegin({
          x: touch.pageX - l || touch.clientX - l,
          y: touch.pageY - t || touch.clientY - t
        });
      });

      //手指移动 => 下笔书写
      this.canvas.addEventListener("touchmove", e => {
        e && e.preventDefault() && e.stopPropagation();
        const touch = e.targetTouches[0];
        const l = this.canvas.offsetLeft;
        const t = this.canvas.offsetTop;
        // const t=0
        this.config.isWrite &&
          this.writing({ x: touch.pageX - l, y: touch.pageY - t });
      });

      //手指移动结束 => 提笔离开
      this.canvas.addEventListener("touchend", e => {
        e && e.preventDefault() && e.stopPropagation();
        const tcs = e.targetTouches;
        const ccs = e.changedTouches;
        const touch =
          (tcs && tcs.length && tcs[0]) || (ccs && ccs.length && ccs[0]);
        const l = this.canvas.offsetLeft;
        const t = this.canvas.offsetTop;
        // const t=0
        this.writeEnd({ x: touch.pageX - l, y: touch.pageY - t });
      });
    },

这个是签名的页面index.vue,用来展示签完的名字

<template>
  <div class="sign b-white">
    <van-nav-bar title="我的签名" left-arrow @click-left="onClickLeft"/>
    <div class="img">
      <img :src="src" alt class="myImg" v-if="src">
    </div>
    <div class="btn" @click="btnClick">{{src?'重签':'签名'}}</div>
  </div>
</template>
<script>
import { mobileURL } from '@/config/baseURL'
export default {
  data() {
    return {
      src: ""
    };
  },
  methods: {
    btnClick() {
      this.$router.push(`${mobileURL}/sign/mySign`);
      this.src = "";
    },
    onClickLeft() {
      // this.$router.go(-1)
    }
  },
  created() {
    // console.log(this.$route.query.img);
    if (this.$route.query.img) {
      this.src = this.$route.query.img;
    }
  }
};
</script>
<style lang="less">
.sign {
  height: 100vh;
  padding: 10px;
  .img {
    width: 100%;
    height: 175px;
    margin-top: 10px;
    border: 1px solid #eee;
    border-radius: 5px;
    background: #fff;
    .myImg {
      width: 100%;
      height: 100%;
    }
  }
  .btn {
    padding: 5px 10px;
    width: 90%;
    height: 30px;
    line-height: 30px;
    border: 2px solid #eee;
    border-radius: 10px;
    text-align: center;
    margin: 20px auto;
    cursor: pointer;
    background: #1890ff;
    color: #fff;
  }
}
</style>

这个是签名页面,使用了canvas组件,同时做了横屏处理

签完名也可以下载到本地,按钮我注释了,js代码还在,可以自己选择,样式方面也可以根据自己要求调整。

备注:强制横屏那里,原本我的思路是选择整个html,但是旋转完canvas手指落点就完全不对了,调整起来比较麻烦,所以我就canvas依然是竖的,但是我把里面的其他所有元素放在一个div里面用js代码旋转了,这样看起来就是整个屏幕旋转,凑合这用吧

Logo

前往低代码交流专区

更多推荐