手写电子签名 横屏和竖屏

<template>
  <div>
     <div  class="fixed_header">
      <div>采集电子签名</div>
      <div class="header_icon"  @click="goBack">
         <img :src="require('@/images/back.png')" alt=""> 
      </div>
      
     </div>
    <div id="signature-pop">
      <div id="signature-container">
        <div class="demo-top-info" id="rotate-container">
          <div class="return" id="return">返回</div>
          <div class="signature-title text-center">手写签名</div>
        </div>
        <div class="canvas-container">
          <div class="canvas-parent">
            <canvas id="canvas"></canvas>
          </div>
        </div>
        <div class="demo-bottom-info"   :class="{'demo-bottom-key':!entershuping}" id="demo-bottom-info">
          <div class="empey"  :class="{'entershuping':!entershuping}">请收款人在上方空白处手写您的签名</div>
          <div id="clean_canvas"  :class="{'entershuping':!entershuping}">清除重写</div>
          <div id="sure_canvas"  :class="{'disabled':disabledBtn,'entershuping':!entershuping}">确认签名</div>
        </div>
      </div>
      <canvas id="canvas2"></canvas>
    </div>
  
  </div>
</template>
<script>
import { uploadImg } from "@/api/driverCertification.js";
import { imgUpload } from "@/utils/enumeration.js";
export default {
  data() {
    return {
        disabledBtn:false,
        entershuping:true,
    };
  },
  mounted() {
    // 手绘签名类
    let _this = this
    var SignatureClass = (function () {
      //获取当前位置(返回px)
      function getStyle(obj, attr) {
        if (obj.currentStyle) {
          return obj.currentStyle[attr];
        } else {
          return getComputedStyle(obj, false)[attr];
        }
      }

      function Signatrue(options) {
        this.cavnas = null;
        this.ctx = null;
        this.maxparams = {};
        this.minparams = {};
        this.entershuping = true; //是否是竖屏 true=是
        this.firstTouch = true; // 第一次点击或touch
        this.allowSubmit = false; // 是否手写了内容 是=才能提交 否=不能提交
        if (options === void 0) {
          options = {};
        }
        this.options = options;
      }

      // 初始化
      Signatrue.prototype.init = function () {
        var self = this;
        console.log(
          getStyle(document.getElementById("rotate-container"), "height")
        ); // 不知道为什么加,否则有些Apple出问题
        this.hengshuping();
        this.clear();
        this.submit();

        window.addEventListener(
          "resize",
          function () {
            self.hengshuping();
          },
          false
        );
      };

      // 判断横竖屏
      Signatrue.prototype.hengshuping = function () {
        if (window.orientation == 90 || window.orientation == -90) {
          this.entershuping = false; // 横屏
          _this.entershuping = false
          document.getElementById("canvas2").style.display = "none";
          document.getElementById("canvas").style.display = "block";
          this.canvas = document.getElementById("canvas");
          this.ctx = this.canvas.getContext("2d");
          this.ctx.lineWidth = 2;
          this.ctx.strokeStyle = "#000000";
          this.drawEvent();
          document.querySelector("#signature-container").style.width =
            window.innerWidth + "px";
          document.querySelector("#signature-container").style.height =
            window.innerHeight + "px";
          this.canvas.height = parseInt(
            getStyle(document.getElementById("canvas").parentNode, "height")
          );
          this.canvas.width = parseInt(
            getStyle(document.getElementById("canvas").parentNode, "width")
          );
          document.querySelector("#signature-container").style.transform =
            "rotate(0deg)";
          document.querySelector("#signature-container").style.transformOrigin =
            "0 0";
          document.querySelector("#signature-container").style.marginLeft =
            "0px";
        } else {
          // 竖屏
          this.entershuping = true;
          _this.entershuping = true
          document.getElementById("canvas").style.display = "none";
          document.getElementById("canvas2").style.display = "block";
          this.canvas = document.getElementById("canvas2");
          this.ctx = this.canvas.getContext("2d");
          this.canvas.height = window.innerHeight;
          let signatureContainerDom =  document.querySelector("#signature-container")
          let demoBottomInfoDom =  document.getElementById("demo-bottom-info")
          this.canvas.width =
            window.innerWidth -
            demoBottomInfoDom.offsetHeight;
          this.ctx.lineWidth = 2;
          this.ctx.strokeStyle = "#000000";
          this.drawEvent();
          signatureContainerDom .style.width =
            window.innerHeight + "px";
          signatureContainerDom .style.height =
            window.innerWidth + "px";
         signatureContainerDom .style.transform =
            "rotate(90deg)";
          signatureContainerDom .style.transformOrigin =
            "0 0";
          signatureContainerDom .style.marginLeft =
            window.innerWidth + "px";
        }
      };

      // 绘画事件
      Signatrue.prototype.drawEvent = function () {
        var self = this;
        this.canvas.addEventListener("touchstart", function (evt) {
          var oEvent = evt || event;
          oEvent.preventDefault();
          var position = self.pos(oEvent);
          self.ctx.beginPath();
          self.ctx.moveTo(position.x, position.y);
          if (self.firstTouch) {
            self.minparams = {
              x: position.x,
              y: position.y,
            };
            self.maxparams = {
              x: position.x,
              y: position.y,
            };
            self.firstTouch = false;
          } else {
            self.judgeSize(position);
          }
          self.canvas.addEventListener("touchmove", touchmove, false);

          function touchmove(evt) {
            var oEvent = evt || event;
            oEvent.preventDefault();
            var position = self.pos(oEvent);
            self.ctx.lineTo(position.x, position.y);
            self.judgeSize(position);
            self.ctx.stroke();
          }
          document.addEventListener("touchend", touchend, false);

          function touchend(evt) {
            var oEvent = evt || event;
            oEvent.preventDefault();
            self.allowSubmit = true;
            self.canvas.removeEventListener("touchmove", touchmove);
            document.removeEventListener("touchend", touchend);
          }
        });
      };

      // 清空画笔
      Signatrue.prototype.clear = function () {
        var self = this;
        document
          .getElementById("clean_canvas")
          .addEventListener("click", function () {
            self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height);
            self.allowSubmit = false;
          });
      };

      // 提交画笔内容
      Signatrue.prototype.submit = function () {
        var self = this;
        document
          .getElementById("sure_canvas")
          .addEventListener("click", function () {
            if (self.allowSubmit) {
              var imgSRC = self.canvas.toDataURL("image/png", 1);
              var img = new Image();
              img.src = imgSRC;
              // self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height);
              img.onload = function () {
                var width = self.maxparams.x - self.minparams.x;
                var height = self.maxparams.y - self.minparams.y;
                var targetWidth = 200;
                var targetHeight = 100;
                var clipCanvas = document.createElement("canvas");
                clipCanvas.width = targetWidth;
                clipCanvas.height = targetHeight;
                var ctx2 = clipCanvas.getContext("2d");
                if (self.entershuping) {
                  ctx2.translate(0, targetHeight);
                  ctx2.rotate((-90 * Math.PI) / 180);
                  ctx2.drawImage(
                    img,
                    self.minparams.x,
                    self.minparams.y,
                    width,
                    height,
                    0,
                    0,
                    targetHeight,
                    targetWidth
                  );
                } else {
                  ctx2.drawImage(
                    img,
                    self.minparams.x,
                    self.minparams.y,
                    width,
                    height,
                    0,
                    0,
                    targetWidth,
                    targetHeight
                  );
                }
                var imgSRC2 = clipCanvas.toDataURL("image/png", 1);
                console.log("imgSRC2==", imgSRC2);
                if(self.options && self.options.callback && typeof self.options.callback == 'function') {
                    self.options.callback(imgSRC2);
                }
                // self.canvas = null;
                // self.ctx = null;
                // ctx2 = null;
                // clipCanvas = null;
              };
            } else {
            //   alert("没有手写签名,不能提交!");
            }
          });
      };

      // 获取当前位置
      Signatrue.prototype.pos = function (event) {
        var x = event.touches[0].pageX - event.target.offsetLeft;
        var y = event.touches[0].pageY - event.target.offsetTop;
        return {
          x: x,
          y: y,
        };
      };

      // 优化画笔界限,去掉空白区域
      Signatrue.prototype.judgeSize = function (value) {
        if (this.minparams.x > value.x) {
          this.minparams.x = value.x;
        }
        if (this.maxparams.x < value.x) {
          this.maxparams.x = value.x;
        }
        if (this.minparams.y > value.y) {
          this.minparams.y = value.y;
        }
        if (this.maxparams.y < value.y) {
          this.maxparams.y = value.y;
        }
      };

      return Signatrue;
    })();

    var signatrueDraw = new SignatureClass({
      callback: function (base64) {
          console.log(base64)
          if(_this.disabledBtn){
               return
          }
         _this.disabledBtn = true
        _this.handleCompessUpload(
            base64,
            imgUpload,
            (res) => {
                  _this.disabledBtn = false
                  console.log("{res.imgUrl==",res.imgUrl)
                  _this.$router.replace({
                    path: `/drive/saveSign?signUrl=${res.imgUrl}`,
                  });
                },
                "",
            (res) => {}
          );

      },
    });
    signatrueDraw.init();
  },
  methods: {
    goBack(){
       this.$router.go(-1)
    },
    dataURLtoBlob(dataurl) {
      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 Blob([u8arr], { type: mime });
    },
    //上传前压缩
    handleCompessUpload(
      file,
      uploadUrl,
      uploadCallBack,
      ocrLoadUrl,
      ocrLoadCallback
    ) {
      let self = this;
      let Orientation;
      let ndata;
      let _fileBlob = this.dataURLtoBlob(file);
      let fileOfBlob = new File([_fileBlob], new Date() + ".jpg");
      self.postImg(
        2,
        fileOfBlob,
        uploadUrl,
        (res) => {
          uploadCallBack && uploadCallBack(res);
        },
        ocrLoadUrl,
        (res) => {
          ocrLoadCallback && ocrLoadCallback(res);
        }
      );
    },
    async postImg(
      type,
      blob,
      uploadUrl,
      uploadCallBack,
      ocrLoadUrl,
      ocrLoadCallback
    ) {
      let fd;
      if (type == 1) {
        let filename = `${new Date().getTime()}.jpg`;
        let file = new File([blob], filename, { type: "image/jpg" });
        fd = new FormData();
        fd.append("file", file);
      } else {
        fd = new FormData();
        fd.append("file", blob);
      }
      uploadImg(uploadUrl, fd).then((res) => {
        console.log(res, "res===");
        if (res.data) {
          uploadCallBack && uploadCallBack(res.data);
        }
      });
      if (ocrLoadUrl) {
        uploadImg(ocrLoadUrl, fd).then((res) => {
          if (res.data) {
            ocrLoadCallback && ocrLoadCallback(res.data);
          }
        });
      }
    },

    compress(img, Orientation) {
      let canvas = document.createElement("canvas");
      let ctx = canvas.getContext("2d");
      //瓦片canvas
      let tCanvas = document.createElement("canvas");
      let tctx = tCanvas.getContext("2d");
      let initSize = img.src.length;
      let width = img.width;
      let height = img.height;
      //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
      let ratio;
      if ((ratio = (width * height) / 4000000) > 1) {
        console.log("大于400万像素");
        ratio = Math.sqrt(ratio);
        width /= ratio;
        height /= ratio;
      } else {
        ratio = 1;
      }
      canvas.width = width;
      canvas.height = height;
      // 		铺底色
      ctx.fillStyle = "#fff";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      //如果图片像素大于100万则使用瓦片绘制
      let count;
      if ((count = (width * height) / 1000000) > 1) {
        console.log("超过100W像素");
        count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
        //            计算每块瓦片的宽和高
        let nw = ~~(width / count);
        let nh = ~~(height / count);
        tCanvas.width = nw;
        tCanvas.height = nh;
        for (let i = 0; i < count; i++) {
          for (let j = 0; j < count; j++) {
            tctx.drawImage(
              img,
              i * nw * ratio,
              j * nh * ratio,
              nw * ratio,
              nh * ratio,
              0,
              0,
              nw,
              nh
            );
            ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
          }
        }
      } else {
        ctx.drawImage(img, 0, 0, width, height);
      }
      //修复ios上传图片的时候 被旋转的问题
      // if (Orientation != "" && Orientation != 1) {
      //   switch (Orientation) {
      //     case 6: //需要顺时针(向左)90度旋转
      //       this.rotateImg(img, "left", canvas);
      //       break;
      //     case 8: //需要逆时针(向右)90度旋转
      //       this.rotateImg(img, "right", canvas);
      //       break;
      //     case 3: //需要180度旋转
      //       this.rotateImg(img, "right", canvas); //转两次
      //       this.rotateImg(img, "right", canvas);
      //       break;
      //   }
      // }
      //进行最小压缩
      let ndata = canvas.toDataURL("image/jpeg", 0.1);
      tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
      return ndata;
    },
  },
};
</script>

<style lang="scss" scoped>
 .fixed_header{
   position:fixed;
   left: 0px;
   top:0px;
   line-height: 0.88rem;
   width: 100%;
   z-index: 100;
   background: #fff;
   display: flex;
   align-items: center;
   justify-content: center;
   border-bottom: 1px  solid #F2F3F7;
   .header_icon{
        position:absolute;
        height: 0.88rem;
        left: 0px;
        top:0px;
        width: 1rem;
        display: flex;
        justify-content: center;
        align-items: center;
         img{
          // position:absolute;
          // left: 0.3rem;
          // top: 50%;
          width:0.2rem ;
          height: 0.36rem;
          // transform: translateY(-50%);
        }
   }
  
 }

 
.text-center {
  text-align: center;
}

#signature-button {
  display: block;
  margin: 0 auto;
}

#signature-img {
  width: 200px;
  height: 100px;
  margin: 10px auto;
  display: none;
}

#signature-pop {
  position: fixed;
  background-color: #fff;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  height: 100%;
  /* display: none; */
}

#signature-container {
  /* width: 100%;
                height: 100%; */
  width: 812px;
  height: 375px;
  transform: rotate(90deg);
  transform-origin: 0px 0px;
  margin-left: 375px;
}

.demo-top-info {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 40px;
  background: #cccccc;
  box-sizing: border-box;
  text-align: center;

  display: none;
}

.demo-top-info .return {
  padding-left: 5px;
  height: 40px;
  line-height: 40px;
  position: absolute;
  left: 10px;
  display: inline-block;
}

.signature-title {
  height: 40px;
  line-height: 40px;
  display: inline-block;
}

.canvas-container {
  width: 100%;
  height: 100%;
  background-color: #ffffff;
  box-sizing: border-box;
}

.canvas-parent {
  width: 100%;
  height: 100%;
}

.demo-bottom-info {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background: #fff;
  box-sizing: border-box;
  overflow: hidden;
  display: flex;
  justify-content: space-around;
  align-items: center;
  border-top: 1px solid #f5f6fa;
  padding-left: 0.88rem;
  &.demo-bottom-key{
      padding-left: 0rem;
  }
}

.empey {
//   width: 4.8rem;

  height: 1.5rem;
  font-size: 0.28rem;
  font-weight: 500;
  display: flex;
  justify-content: center;
  align-items: center;
  &.entershuping{
 font-size: 0.24rem;
  }
}

#clean_canvas {
  font-size: 0.3rem;
  font-weight: 500;
  background: #fff;
  border: 1px solid #989db2;
  padding: 10px 15px;
  border-radius: 4px;
  color: #ff0000;
  &.entershuping{
 font-size: 0.24rem;
  }
}

#sure_canvas {
  background: #0f7dfc;
  padding: 10px 15px;
  border: 1px solid #0f7dfc;
  border-radius: 4px;
  color: #fff;
  font-size: 0.3rem;
  font-weight: 500;
  &.entershuping{
   font-size: 0.24rem;
  }
}

#canvas2 {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 999;
  margin-left: 1.5rem;
}
</style>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在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元素上的图像数据保存到服务器或本地存储中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值