美文网首页
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