移动端手写签名

可以用组件的方式实现! 

  <van-popup v-model="showss" get-container="body" position="bottom" :style="{ height: '60%' }"  @open="openeName('showss',showss)" @close="closePop('showss')">
            <signCanvas@setshow="setshow"@signImg="signImg"></signCanvas>
   </van-popup>

 

  setshow() {
      this.showss = false;
    },
    //签字保存之后的返回图片
    signImg(res) {
      console.log(res,"保存传回的参数")
      this.showss = false;
    },

 单个引用到页面也是可以实现

<template>
  <div class="signature" @touchmove.prevent>
    <div class="boardBox" ref="boardBox">
      <div style=" width: 100%; height: 3%;position: fixed;font-size: 14px; color: #7f7f7f; border: 1px solid #7f7f7f;" >如本月考勤无异议请进行签字确认</div>
      <canvas ref="board" id="canvas" @touchstart="mStart" @touchmove="mMove" @touchend="mEnd"></canvas>
    </div>
    <div class="bar" ref="barrie">
      <div class="item" @click="goback">
        <div class="ico">
        </div>
        <!-- <div class="text">取消</div> -->
        <van-button style="width: 80px;" type="default" >取消</van-button>
      </div>
      <div class="item" @click="clearcanvas">
        <div class="ico">
        </div>
        <van-button style="width: 80px;"  type="warning">重绘</van-button>
        <!-- <div class="text">重绘</div> -->
      </div>
      <div class="item" @click="getcanvas">
        <div class="ico">
        </div>
        <van-button style="width: 80px;"  type="info">保存</van-button>
        <!-- <div class="text">保存</div> -->
      </div>
    </div>
  </div>
</template>
<script>
import { Dialog, Toast, Popu,Button  } from "vant";
import { deviceModel } from "@/api";
import personal from "../PersonManagement/managementCheck/personalServiceList/js/personal";
import { log } from 'util';
export default {
  data() {
    return {
      familysignatureurl:"",
      basedata: "",
      ctx: null,
      point: {
        x: 0,
        y: 0,
      },
      moving: false, // 是否正在绘制中且移动
      mubHeight: 0 //弹出层的蒙版高度
    };
  },
  mounted() {
    let board = this.$refs.board; // 获取DOM
    board.width = this.$refs.boardBox.offsetWidth; // 设置画布宽
    board.height = this.$refs.boardBox.offsetHeight; // 设置画布高
    // console.log(this.$refs.boardBox.offsetHeight,"45!!!!!");
    // console.log(this.$refs.boardBox.offsetWidth,"46!!!!!");
    this.ctx = board.getContext("2d"); // 二维绘图
    this.ctx.strokeStyle = "#000"; // 颜色
    this.ctx.lineWidth = 3; // 线条宽度
    this.mubHeight = document.body.clientHeight-(this.$refs.boardBox.offsetHeight+this.$refs.barrie.offsetHeight)
  },
  methods: {
    // 触摸(开始)
    mStart(e) {
      let x = e.touches[0].clientX - e.target.offsetLeft,
          y = e.touches[0].clientY - this.mubHeight // 获取触摸点在画板(canvas)的坐标
      // console.log(x,555);
      // console.log(y,555);
      this.point.x = x;
      this.point.y = y;
      this.ctx.beginPath();
      this.moving = true;
    },
    // 滑动中...
    mMove(e) {
      if (this.moving) {
        this.mubHeight
        let x = e.touches[0].clientX - e.target.offsetLeft,
          y = e.touches[0].clientY - this.mubHeight; // 获取触摸点在画板(canvas)的坐标
        this.ctx.moveTo(this.point.x, this.point.y); // 把路径移动到画布中的指定点,不创建线条(起始点)
        this.ctx.lineTo(x, y); // 添加一个新点,然后创建从该点到画布中最后指定点的线条,不创建线条
        this.ctx.stroke(); // 绘制
        (this.point.x = x), (this.point.y = y); // 重置点坐标为上一个坐标
      }
    },
    // 滑动结束
    mEnd() {
      if (this.moving) {
        this.ctx.closePath(); // 停止绘制
        this.moving = false; // 关闭绘制开关
      }
    },
    getcanvas() {
      //绘画转图片
      document.getElementById("canvas").toDataURL("image/png");
      document.getElementById("canvas").toBlob(async (blobObj) => {
        var file1 = new File([blobObj], "pic.png", {
          type: blobObj.type,
          lastModified: Date.now(),
        });
        this.convertImg(file1);
      });
    },
        //旋转图片
    convertImg(file) {
      let _this = this;
      var canvas1 = document.createElement("canvas");
      var context1 = canvas1.getContext("2d");
      var oReader = new FileReader();
      oReader.readAsDataURL(file);
      oReader.onload = function (e) {
        var img = new Image();
        img.src = e.target.result;
        img.onload = function () {
          // 图片原始尺寸
          var originWidth = this.width;
          var originHeight = this.height;
          // 最大尺寸限制
          var maxWidth = 1080,
            maxHeight = 1080;
          // 目标尺寸
          var targetWidth = originWidth,
            targetHeight = originHeight;
          // 图片尺寸超过300x300的限制
          if (originWidth > maxWidth || originHeight > maxHeight) {
            if (originWidth / originHeight > maxWidth / maxHeight) {
              targetWidth = maxWidth;
              targetHeight = Math.round(
                maxWidth * (originHeight / originWidth)
              );
            } else {
              targetHeight = maxHeight;
              targetWidth = Math.round(
                maxHeight * (originWidth / originHeight)
              );
            }
          }
          var type = "image/jpeg";
          // canvas对图片进行缩放
          canvas1.width = targetHeight;
          canvas1.height = targetWidth;
          // 旋转90度
          context1.translate(0, 0);
          context1.rotate(Math.PI / 2);
          // (0,-imgHeight) 从旋转原理图那里获得的起始点
          // context.clearRect(0,  -targetHeight, targetWidth, targetHeight);
          context1.drawImage(img, 0, -targetHeight, targetWidth, targetHeight);
          // 将canvas的透明背景设置成白色
          var imageData = context1.getImageData(
            0,
            0,
            canvas1.width,
            canvas1.height
          );
          for (var i = 0; i < imageData.data.length; i += 4) {
            // 当该像素是透明的,则设置成白色
            if (imageData.data[i + 3] == 0) {
              imageData.data[i] = 255;
              imageData.data[i + 1] = 255;
              imageData.data[i + 2] = 255;
              imageData.data[i + 3] = 255;
            }
          }
          context1.putImageData(imageData, 0, 0);
          var dataurl = canvas1.toDataURL(type);
          _this.basedata = dataurl;
          console.log(dataurl);
          _this.updatavue();
        };
      };
    },
    //base64转Blob
    base64ToBlob(base64Data) {
      let arr = base64Data.split(","),
        fileType = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        l = bstr.length,
        u8Arr = new Uint8Array(l);

      while (l--) {
        u8Arr[l] = bstr.charCodeAt(l);
      }
      return new Blob([u8Arr], {
        type: fileType,
      });
    },
    dataURLtoFile(dataurl, filename) {
      //将base64转换为文件
      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,
      });
    },
    getFileName(o) {
      var pos = o.lastIndexOf("\\");
      return o.substring(pos + 1);
    },
       //上传图片
    async updatavue() {
      //转成file文件
      let me = this;
    //   let blobObj = this.base64ToBlob(this.basedata);
      let name = personal.nameImg();
      let fileGroupId = personal.QRCodeguid();
      let fileName = this.getFileName(name); //将文件名进行截取;
      let photoFile = this.dataURLtoFile(this.basedata, fileName); //dataURL ----base64文件;
    //   let fileName = personal.QRCodeguid()
    //   var file = new File([blobObj], fileName + ".png", {
    //     type: blobObj.type,
    //     lastModified: Date.now(),
    //   });
      console.log(photoFile)
      //此处为发送请求给后台获取图片路径
      deviceModel._fileUpload(
          photoFile,
          fileGroupId + '.png',
          function cb(result) {
              console.log(result,"result")
              me.$emit("signImg",result)
          }
        );
    //   let res = await upload(file);
    //   this.familysignatureurl=res.details.data.filePath
    //   console.log(this.familysignatureurl);//此处打印的为绘画的图片url
    },

    //清除画布
    clearcanvas() {
      console.log(11111);
      var c = document.getElementById("canvas");
      var cxt = c.getContext("2d");
      c.height = c.height;
      this.ctx.lineWidth = 3;
    },
        //返回上一级
    goback() {
      this.$emit("setshow");
    // this.$router.go(-1)
    },
  },
}
</script>
<style lang="scss" scoped>
.loadingtext {
  transform: rotate(-90deg);
  color: red;
}
// .item {
//   -webkit-transform: rotate(-90deg);
// }

.text {
  text-align: center;
}

.boardBox {
  width: 100vw;
  height: 50vh;
  background: #f9f9f9;
}

.bar {
  box-sizing: border-box;
  padding: 0rem 1rem;
  display: flex;
  width: 100vw;
  height: 10vh;
  background-color: #ffffff;
  justify-content: space-around;
  align-items: center;
}
.shade {
  width: 100vw;
  height: 50vh;
  position: fixed;
  top: 0;
  background-color: #333333;
  z-index: 66666;
  opacity: 0.9;
  .minishade {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>

 

 最终的图片会base64转Blob

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值