美文网首页
vue 电子签名

vue 电子签名

作者: 张晓畅 | 来源:发表于2020-01-11 10:34 被阅读0次

    上来就干货!

    autograph.vue
    <template>
      <page-box>
        <v-header slot="header" title="确认签名"/>
        <p :class="['autograph-tip', {'horizontal': isHorizontalScreen}]">确认无误,请在签名区签名</p>
        <div
          :class="['canvas-box',{'active': isWarning}, {'horizontal': isHorizontalScreen}]"
          ref="canvasBox"
          id="canvasBox"
        >
          <!-- <p class="tip" v-if="!isWarning">签名区</p> -->
        </div>
        <div slot="footer" :class="['footer', {'horizontal': isHorizontalScreen}]">
          <p :class="['warning', {active: isWarning}]">
            <span :class="['agree', {active: isAgree}]" @click="isAgree = !isAgree"></span>本人申明:本人已认真核对并确认以上内容真实无误。
          </p>
          <p class="btn-box">
            <a href="javascript:;" class="short-btn reset" @click="resetCanvas">重置</a>
            <a
              href="javascript:;"
              :class="['short-btn', 'submit', {active: isAgree}]"
              @click="submit"
            >提交</a>
          </p>
        </div>
      </page-box>
    </template>
    <script>
    import { mapGetters } from "vuex";
    export default {
      data() {
        return {
          isWarning: false,
          isAgree: false,
          headerHeight: "46",
          canvas: null,
          canvasTop: "", //画布上距离
          canvasLeft: "", //画布左距离
          isHorizontalScreen: false, //是否横屏
          ctx: null //画布内容
        };
      },
      mounted() {
        this.verticalScreen();
        if (/iP(hone|od|ad)/.test(window.navigator.userAgent)) {
          //键盘收齐页面空白问题
          const scrollHeight =
            document.documentElement.scrollTop || document.body.scrollTop || 0;
          window.scrollTo(0, Math.max(scrollHeight - 1, 0));
        }
        window.onresize = () => {
          this.verticalScreen();
          this.$nextTick(() => {
            let canvasBox = this.$refs.canvasBox;
            this.canvas.width = canvasBox.offsetWidth;
            this.canvas.height = canvasBox.offsetHeight;
            let canvasInfo = canvasBox.getBoundingClientRect();
            this.canvasTop = Math.round(canvasInfo.top);
            this.canvasLeft = Math.round(canvasInfo.left);
            this.resetCanvas();
          });
        };
        this.$nextTick(() => {
          document.body.addEventListener("touchmove", this.preventDefault, {
            passive: false
          }); //passive防止阻止默认事件不生效
          this.createdCanvas();
        });
      },
      created() {},
      computed: {
        ...mapGetters(["getUserInfo"])
      },
      methods: {
        // 判断手机是横屏还是竖屏
        verticalScreen() {
          if (window.orientation == 180 || window.orientation == 0) {
            // console.log("竖屏状态!");
            this.isHorizontalScreen = false;
          }
          if (window.orientation == 90 || window.orientation == -90) {
            // console.log("横屏状态!");
            this.isHorizontalScreen = true;
          }
        },
        // 阻止默认事件
        preventDefault(event) {
          event.preventDefault();
        },
        //   创建画布
        createdCanvas() {
          let canvasBox = this.$refs.canvasBox;
          // console.log(canvasBox.offsetTop, canvasBox.offsetLeft)
          let canvasInfo = canvasBox.getBoundingClientRect();
          this.canvasTop = Math.round(canvasBox.offsetTop*1 + this.headerHeight*1); //首次进入canvasInfo.top不准
          // console.log(this.canvasTop)
          this.canvasLeft = Math.round(canvasInfo.left);
          this.canvas = document.createElement("canvas");
          this.canvas.setAttribute("id", "autograph");
          canvasBox.appendChild(this.canvas);
          this.canvas.width = canvasBox.offsetWidth - 4;
          this.canvas.height = canvasBox.offsetHeight - 4;
    
          this.ctx = this.canvas.getContext("2d");
          this.ctx.fillStyle = "transparent"; //画布背景色
          this.ctx.strokeStyle = "#333";
          this.ctx.lineCap = "round";
          this.ctx.lineJoin = "round";
          this.ctx.lineWidth = 2;
          this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
          this.canvas.addEventListener("touchstart", this.writeDown, { passive: false });
          this.canvas.addEventListener("touchmove", this.write, { passive: false });
          this.canvas.addEventListener("touchend", this.writeUp, { passive: false });
        },
        // 下笔
        writeDown(e) {
          e.preventDefault();
          let touch = e.touches[0];
          let pageX = touch.pageX - this.canvasLeft;
          let pageY = touch.pageY - this.canvasTop;
          this.ctx.beginPath();
          this.ctx.moveTo(pageX, pageY);
        },
        //写字
        write(e) {
          e.preventDefault();
          let touch = e.touches[0];
          this.ctx.fillStyle = "#fff"; //画布背景色
          let pageX = touch.pageX - this.canvasLeft;
          let pageY = touch.pageY - this.canvasTop;
          this.ctx.lineTo(pageX, pageY);
          this.ctx.stroke();
          this.isWarning = true;
        },
        // 写完
        writeUp(e) {
          e.preventDefault();
          this.ctx.closePath();
        },
        // 重置
        resetCanvas() {
          this.isWarning = false;
          this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
          this.ctx.fillStyle = "transparent"; //画布背景色
        },
        // 确认提交
        submit() {
          if (!this.isWarning) return this.$vux.toast.text("请在签名区签名");
          if (!this.isAgree) return this.$vux.toast.text("请确认本人申明");
          let that = this;
          this.$vux.confirm.show({
            content: "信息采集完成,提交后将无法再次修改,是否确认提交?",
            confirmText: "确认提交",
            cancelText: "我再看看",
            onConfirm() {
              that.autogranph();
            }
          });
        },
        autogranph() {
          let imgBase64 = this.canvas.toDataURL();
          this.$api
            .saveHospitalInfo({signUrl: imgBase64 })
            .then(res => {
              this.$router.push(`/hosSuccess`);
            })
            .catch(err => {
              console.log(err);
            });
        }
      },
      beforeRouteLeave(to, from, next) {
        window.onresize = "";
        document.body.removeEventListener("touchmove", this.preventDefault);
        next();
      }
    };
    </script>
    <style lang="less" scoped>
    .main {
      position: relative;
    }
    .autograph-tip {
      padding: 4% 15px 4% 60px;
      background: url("~@/assets/images/ximg09.png") no-repeat 15px;
      background-size: 20px;
      color: @theme-color;
      font-weight: 700;
      &.horizontal {
        padding: 1% 15px 0 50px;
        background-size: 18px;
      }
    }
    .canvas-box {
      width: 90%;
      height: 85%;
      position: absolute;
      left: 50%;
      top: 12%;
      transform: translate(-50%, 0);
      border: 2px dashed @theme-color;
      background: url("~@/assets/images/ximg10.png") no-repeat center;
      background-size: 65%;
      &.horizontal {
        top: 16%;
        height: 80%;
        background-size: 50%;
      }
      &.active {
        background: none;
      }
      .tip {
        position: absolute;
        top: 50%;
        left: 0;
        width: 100%;
        text-align: center;
        transform: translate(0, -50%);
        font-size: 72px;
        font-weight: 700;
        color: rgba(72, 196, 160, 0.4);
        z-index: 1;
      }
    }
    .warning {
      color: #f00000;
      margin: 0 15px 10px;
      line-height: 1.2;
      padding-left: 20px;
      position: relative;
      opacity: 0;
      visibility: hidden;
      .agree {
        position: absolute;
        top: 1px;
        left: 0;
        width: 12px;
        height: 12px;
        background-color: #fff;
        border: 1px solid @border-color;
        border-radius: 2px;
        &.active {
          background: @theme-color url("~@/assets/images/ximg01.png") no-repeat
            center;
          background-size: 100%;
          border-color: @theme-color;
        }
      }
      &.active {
        opacity: 1;
        visibility: visible;
      }
    }
    .btn-box {
      display: flex;
      justify-content: space-between;
      padding: 0 15px 25px;
      box-sizing: border-box;
      .short-btn {
        width: 2.8rem;
        &.active {
          background-color: @theme-color;
        }
        &.reset {
          background-color: #fff;
          border: 1px solid @theme-color;
          color: @theme-color;
        }
      }
    }
    .footer.horizontal {
      display: flex;
      align-items: center;
      .warning {
        flex: 1;
      }
      .btn-box {
        padding-bottom: 10px;
        padding-left: 0;
        width: 4.5rem;
      }
      .short-btn {
        line-height: 0.6rem;
        width: 1.8rem;
        margin: 0;
      }
    }
    </style>
    <style lang="less">
    .main {
      position: relative;
    }
    </style>
    
    
    

    有空再整理成组件,拜拜!

    相关文章

      网友评论

          本文标题:vue 电子签名

          本文链接:https://www.haomeiwen.com/subject/gcuvactx.html