vue移动端横屏手写签名

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

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

因为需要横屏签名,所以有监听手机屏幕,如果是手机屏幕锁定的情况下就通过代码旋转页面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代码旋转了,这样看起来就是整个屏幕旋转,凑合这用吧

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在Vue移动端实现横屏手写签名功能,可以使用HTML5的canvas元素和JavaScript来实现。首先,你需要创建一个canvas元素,并设置其宽高比,以便在横屏模式下正确显示。然后,你需要监听设备方向变化事件,根据设备方向动态调整canvas元素的宽高比,以便在横屏模式下正确显示。最后,你需要监听用户手写事件,并在canvas元素上绘制用户手写签名。 以下是示例代码,可以在移动设备上测试: ```html <template> <div class="canvas-container"> <canvas ref="canvas"></canvas> </div> </template> <script> export default { mounted() { // 监听设备方向变化事件 window.addEventListener("orientationchange", this.onOrientationChange); // 初始化canvas this.initCanvas(); }, methods: { initCanvas() { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 设置canvas宽高比为3:2 canvas.width = 300; canvas.height = 200; // 监听用户手写事件 canvas.addEventListener("touchstart", this.onTouchStart); canvas.addEventListener("touchmove", this.onTouchMove); canvas.addEventListener("touchend", this.onTouchEnd); }, onOrientationChange() { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 根据设备方向动态调整canvas宽高比 if (window.orientation === 90 || window.orientation === -90) { canvas.width = 200; canvas.height = 300; } else { canvas.width = 300; canvas.height = 200; } // 清空canvas ctx.clearRect(0, 0, canvas.width, canvas.height); }, onTouchStart(event) { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 开始绘制路径 ctx.beginPath(); // 获取触点位置 const touch = event.touches[0]; const x = touch.pageX - canvas.offsetLeft; const y = touch.pageY - canvas.offsetTop; // 移动到触点位置 ctx.moveTo(x, y); }, onTouchMove(event) { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 获取触点位置 const touch = event.touches[0]; const x = touch.pageX - canvas.offsetLeft; const y = touch.pageY - canvas.offsetTop; // 绘制直线到触点位置 ctx.lineTo(x, y); ctx.stroke(); }, onTouchEnd() { const canvas = this.$refs.canvas; const ctx = canvas.getContext("2d"); // 结束路径绘制 ctx.closePath(); } }, beforeDestroy() { // 移除事件监听 window.removeEventListener("orientationchange", this.onOrientationChange); const canvas = this.$refs.canvas; canvas.removeEventListener("touchstart", this.onTouchStart); canvas.removeEventListener("touchmove", this.onTouchMove); canvas.removeEventListener("touchend", this.onTouchEnd); } }; </script> <style scoped> .canvas-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; } canvas { border: 1px solid #ccc; } </style> ``` 在上面的示例中,我们创建了一个canvas元素,并设置了其宽高比为3:2,以便在竖屏模式下正确显示。我们还监听了设备方向变化事件,根据设备方向动态调整canvas元素的宽高比。我们还监听了用户手写事件,并在canvas元素上绘制用户手写签名。当用户完成签名后,可以将canvas元素上的图像数据保存到服务器或本地存储中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值