手机签名(横竖屏自带图片旋转)

效果如下,竖屏和横屏

  1. 第一步安装插件,使用到了SignaturePad
    npm install --save signature_pad
  2. 新建一个vue页面
<template>
  <div class="recruit-canvas">
    <div class="text-box">请在横屏方向进行签名</div>
    <div class="canvas-box" ref="canvasRef">
      <canvas ref="canvasMapRef" id="canvas-map" width="100" height="100" />
    </div>

    <slot name="default" :signatrue="canvasNode">
      <div class="btn-box flex-row">
        <el-button @click="clearHandle" type="info">清除画布</el-button>
        <el-button @click="confirmHandle" type="warning">提交到系统</el-button>
      </div>
    </slot>
  </div>
</template>
<script>
import SignaturePad from "signature_pad";
import { rotateBase64Img } from "@/utils/sign";//这是使用的方法,当手机屏幕是竖屏的时候要旋转图片

export default {
  data() {
    return {
      canvasNode: "",
    };
  },
  created() {
    this.$nextTick(() => {
      this.initalHandle();
      window.addEventListener("resize", this.initalHandle, false);
    });
  },
  methods: {
    initalHandle() {
      const _canvasBox = this.$refs.canvasRef;
      const _canvas = this.$refs.canvasMapRef;
      if (!_canvasBox || !_canvas) {
        console.warn("DOM节点初始化失败");
        return false;
      }

      _canvas.width = _canvasBox.clientWidth;
      _canvas.height = _canvasBox.clientHeight;
      const computedOpt = Object.assign(
        {},
        {
          dotSize: 5,
          minWidth: 5,//因为有笔锋的效果的,鼠标压力不同显示粗细不同
          maxWidth: 7,
          penColor: "rgb(0, 0, 0)",
        },
      );

      this.clearHandle();
      this.canvasNode = new SignaturePad(_canvas, computedOpt);//这里设置笔的宽度和颜色的样式
    },

    clearHandle() {
      const hasNode = this.canvasNode;
      if (hasNode) {
        hasNode.clear();
        this.$emit("cancelEvent", hasNode);
      }
    },

    async confirmHandle() {
      // 重新初始化画布
      const canvasNode = this.canvasNode;
      if (!canvasNode) {
        this.initalHandle();
      }

      // 是否签字
      if (canvasNode.isEmpty()) {
        console.warn("您还没有签名");
        this.$emit("confirmEvent", canvasNode);
        return false;
      }

      // 图像旋转二次处理
      const _boxWidth = window.innerWidth;
      const _boxHeight = window.innerHeight;
      // let _signImg = null;
      const _signImg = canvasNode.toDataURL("image/png", 0.6) || null;//不旋转就是手机横屏
      if (_boxWidth < _boxHeight) {
        await rotateBase64Img(_signImg, -90, (imgUrlRes) => {
        this.$emit("confirmEvent", imgUrlRes); //在这里修改逻辑,返回的是旋转后的database

        });
      }

    },
  },
  beforeUnmount() {
    window.removeEventListener("resize", this.initalHandle, false);
  },
};
</script>
<style scoped lang="scss">
.recruit-canvas {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;

  .canvas-box,
  .btn-box,
  .text-box {
    position: absolute;
    top: 50%;
    z-index: 100;
  }

  .canvas-box {
    left: 20%;
    width: 67vw;
    height: 80vh;
    overflow: hidden;
    transform: translateY(-50%);
    background-color: #fff;
    border: 1px dashed #d4d4d4;

    #canvas-map {
      width: 100%;
      height: 100%;
    }
  }
  .text-box {
    background-color: #ffbc0124;
    color: #e6a23c;
    right: -105% !important;
    height: 30px;
    line-height: 30px;
  }
  .btn-box,
  .text-box {
    left: -15%;
    z-index: 1000;
    text-align: center;
    transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -webkit-transform: rotate(90deg);

    .del-btn,
    .sure-btn {
      display: inline-block;
      width: 100px;
      height: 24px;
      margin: 0 10px;
      line-height: 24px;
      border-radius: 6px;
      background-color: #fff;
    }

    .del-btn {
      color: #ff5e00;
    }

    .sure-btn {
      color: #fff;
      background: linear-gradient(100deg, #ff4e01 0%, #ffbc01 100%);
    }
  }
}

@media screen and (orientation: portrait) {
  /*竖屏 css*/
}

@media screen and (orientation: landscape) {
  /*横屏 css*/
  .recruit-canvas {
    .canvas-box {
      top: 12%;
      left: 10%;
      width: 80vw;
      height: 70vh;
      transform: translateY(0);
    }

    .btn-box {
      width: 60%;
      top: 86%;
      left: 20%;
      transform: rotate(0);
    }
    .text-box {
      width: 130%;
      top: 1%;
      transform: rotate(0);
    }
  }
}
</style>

3.旋转图片的方法


export const rotateBase64Img = (src, edg, callback) => {
  try {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");

    let imgW = 0; // 图片宽度
    let imgH = 0; // 图片高度
    let size = 0; // canvas初始大小

    if (edg % 90 !== 0) {
      throw new Error("旋转角度必须是90的倍数!");
    }

    edg < 0 && (edg = (edg % 360) + 360);
    const quadrant = (edg / 90) % 4; // 旋转象限
    const cutCoor = { sx: 0, sy: 0, ex: 0, ey: 0 }; // 裁剪坐标

    const image = new Image();
    image.src = src;
    image.crossOrigin = "anonymous";

    image.onload = function () {
      imgW = image.width;
      imgH = image.height;
      size = imgW > imgH ? imgW : imgH;

      canvas.width = size * 2;
      canvas.height = size * 2;
      switch (quadrant) {
        case 0:
          cutCoor.sx = size;
          cutCoor.sy = size;
          cutCoor.ex = size + imgW;
          cutCoor.ey = size + imgH;
          break;
        case 1:
          cutCoor.sx = size - imgH;
          cutCoor.sy = size;
          cutCoor.ex = size;
          cutCoor.ey = size + imgW;
          break;
        case 2:
          cutCoor.sx = size - imgW;
          cutCoor.sy = size - imgH;
          cutCoor.ex = size;
          cutCoor.ey = size;
          break;
        case 3:
          cutCoor.sx = size;
          cutCoor.sy = size - imgW;
          cutCoor.ex = size + imgH;
          cutCoor.ey = size + imgW;
          break;
      }

      ctx.translate(size, size);
      ctx.rotate((edg * Math.PI) / 180);
      ctx.drawImage(image, 0, 0);

      const imgData = ctx.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey);
      if (quadrant % 2 === 0) {
        canvas.width = imgW;
        canvas.height = imgH;
      } else {
        canvas.width = imgH;
        canvas.height = imgW;
      }
      ctx.putImageData(imgData, 0, 0);

      if (typeof callback === "function") {
        callback(canvas.toDataURL("image/png", 0.7));
      }

      return new Promise((resolve) => {
        // 异步操作...
        resolve(canvas.toDataURL("image/png", 0.7));
      });
    };
  } catch (e) {
    console.log(e);
  }
};

以上直接取来用应该是没问题的

参考文章:

H5前端实现移动端手写Canvas签名(支持横竖屏,自定义图片旋转角度)_h5手写签名-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值