zoukankan      html  css  js  c++  java
  • 移动端横屏、竖屏签名面板

    原理:signature_pad插件,canvas

    <template>
      <div id="app">
        <button @click="handleClick">点击签名</button>
        <img :src="imgUrl" v-if="showImg" style="border:1px dashed #ccc;"/>
        <div class="sign-box" v-show="showSignature">
          <div class="bgc"></div>
          <div class="main-box">
            <span @click="cancelBgc" class="cancel">取消</span>
            <p class="title">签名</p>
            <p class="sub-title">请用正楷签下您的名字</p>
            <div :style="{w,height:h}" class="canvass">
              <canvas :id="uid" class="canvas" :data-uid="uid"></canvas>
            </div>
            <div id='reset' @click="clear">
              <span>清除</span>
            </div>
            <div @click="saveSign" class="next">确认</div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
      /* eslint-disable */
      import SignaturePad from 'signature_pad';
      export default {
        data() {
          return {
            showSignature: false,
            showImg:false,
            sig: () => { },
            uid: 'canvas',
            option: {
              backgroundColor: 'rgb(255,255,255)',
              penColor: 'rgb(0, 0, 0)',
              minWidth: 0.8,
              maxWidth: 4
            },
            w: '94.6%',
            h: "240px",
          }
        },
        methods: {
          handleClick() {
            this.showSignature = true;
            this.$nextTick(() => {
              this.draw();
            })
          },
          // 签名
          draw() {
            var that = this;
            var canvas = document.getElementById(that.uid);
            that.sig = new SignaturePad(canvas, that.option);
            window.addEventListener('resize', that.resizeCanvas);
            that.resizeCanvas();
          },
          resizeCanvas() {
            var that = this
            var canvas = document.getElementById(that.uid);
            var url;
            var ratio = Math.max(window.devicePixelRatio || 1, 1);
            canvas.width = canvas.offsetWidth * ratio;
            canvas.height = canvas.offsetHeight * ratio;
            canvas.getContext('2d').scale(ratio, ratio);
            that.clear()
            !that.clearOnResize && url !== undefined && that.fromDataURL(url);
          },
          fromDataURL(url) {
            var that = this;
            that.sig.fromDataURL(url);
          },
          // 取消签名
          cancelBgc() {
            this.showSignature = false;
          },
          // 清除签名
          clear() {
            var that = this;
            that.sig.clear();
          },
          isEmpty() {
            var that = this;
            return that.sig.isEmpty();
          },
          // 保存签名
          saveSign() {
            var that = this;
            if (that.isEmpty()) {
              alert('请用正楷签下您的名字');
              return
            }
            var sign = {
              signature: that.sig.toDataURL().split(',')[1]
            }
            that.imgUrl = "data:image/png;base64," + sign.signature;
            that.showImg = true;
            that.showSignature = false;
          }
        }
      }
    /* eslint-disable */
    </script>
    
    <style>
      #app {
        font-family: Avenir, Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        color: #2c3e50;
        margin-top: 60px;
      }
    
      .canvass {
        margin: auto;
        background: #fff;
        border: 1px dashed #e5e5e5;
        border-radius: 8px;
        margin-top: 17px;
        position: relative;
      }
    
      #reset {
        text-align: center;
        font-size: 14px;
        color: #666666;
        margin-top: 26px;
        margin-bottom: 47px;
    
      }
    
      #reset img {
         13px;
        height: 13px;
      }
    
      canvas {
         100%;
        height: 100%;
      }
    
      .sign-box {
        position: fixed;
        top: 0;
        left: 0;
         100%;
        min-height: 100vh;
    
      }
    
      .bgc {
        opacity: 0.7;
        background: #000000;
         100%;
        height: 100%;
        position: absolute;
        top: 0;
        z-index: 5;
      }
    
      .main-box {
        height: 500px;
         100%;
        background-color: #fff;
        position: absolute;
        bottom: 0;
        z-index: 10;
    
      }
    
      .cancel {
        position: absolute;
        font-size: 18px;
        color: #31A4FF;
        left: 15px;
        top: 16px;
      }
    
      .title {
        text-align: center;
        font-size: 18px;
        color: #333333;
        padding-top: 16px;
        padding-bottom: 4px;
      }
    
      .sub-title {
        font-size: 12px;
        color: #999999;
        text-align: center;
      }
    
      .next {
        border: 1px solid #31A4FF;
        height: 44px;
        text-align: center;
        line-height: 44px;
        font-size: 18px;
        color: #31A4FF;
        background: #fff;
        margin: 0 15px;
      }
    
      .footer {
        position: fixed;
        left: 0;
        bottom: 0;
        display: flex;
        justify-content: space-between;
         100%;
      }
    
      .pre {
         28%;
        margin-right: 1px;
        border-top: 1px solid #d6d6d6;
        color: #454545;
        background: #fff;
      }
    
      .share {
         44%;
        border-top: 1px solid #d6d6d6;
        background: #66b9ff;
        color: #fff;
      }
    
      .nextOne {
         28%;
        color: #fff;
        background: #31A4FF;
      }
    
      .commoncss {
        height: calc(110rem / 24);
        line-height: calc(110rem / 24);
        font-size: 1.6rem;
        text-align: center;
        box-sizing: border-box;
        margin-top: 1rem;
      }
    
      .hasLinkpre {
        margin-top: 1rem;
        background: #fff;
         50%;
        height: calc(110rem / 24);
        line-height: calc(110rem / 24);
        font-size: 1.6rem;
        text-align: center;
        box-sizing: border-box;
        color: #454545;
      }
    
      .hasLinknextone {
        margin-top: 1rem;
        background: #31A4FF;
         50%;
        height: calc(110rem / 24);
        line-height: calc(110rem / 24);
        font-size: 1.6rem;
        text-align: center;
        box-sizing: border-box;
        color: #fff;
      }
    </style>

    效果图:

    横屏签名:

    <template>
      <div id="app">
        <div class="content">
          <div class="btn" @click='toSign()'>点击此处签名</div>
          <img :src="'data:image/png;base64,'+appntSign" alt="" v-show="appntSign" id="signImg">
        </div>
        <div id="signContent" class='signBox' v-show="showSign">
          <div class="canvass">
            <canvas :id="uid" class="canvas" :data-uid="uid"></canvas>
          </div>
          <div class='footer'>
            <span @click="clear()">重签</span>
            <span @click="keepSign()" :class='{active:canSaveBtn}'>保存签名</span>
          </div>
        </div>
      </div>
    </template>
    
    <script>
      /* eslint-disable */
      import SignaturePad from 'signature_pad';
      export default {
        props: {
          showSignPage: {
            type: Boolean,
            default: false
          },
          relation: {
            type: String
          },
          sigOption: {
            type: Object,
            default: () => {
              return {
                backgroundColor: 'rgb(255,255,255)',
                penColor: 'rgb(0, 0, 0)'
              }
            }
          },
          w: {
            type: String,
            default: '90%'
          },
          h: {
            type: String,
            default: '250px'
          },
          clearOnResize: {
            type: Boolean,
            default: false
          }
        },
        data() {
          return {
            sig: () => { },
            option: {
              backgroundColor: 'rgb(255,255,255)',
              penColor: 'rgb(0, 0, 0)'
            },
            uid: '',
            signPerson: '投保人',
            time: 0,
            contNo: '',
            num: '',
            getdata: "",
            buttomShow: false,
            showSign: false,
            appntSign: '',
            canSaveBtn: false,
            needRotate: ''// 0 不旋转  1旋转
          }
        },
        created() {
          var _this = this
          this.uid = 'canvas' + _this._uid
          var sigOptions = Object.keys(_this.sigOption)
          for (var item of sigOptions) {
            _this.option[item] = _this.sigOption[item]
          }
        },
        watch: {
          // 险种信息监听
          showSignPage: {
            handler: function (val, oldVal) {
              this.resizeCanvas()
            },
            // 深度观察
            deep: true
          }
        },
        methods: {
          checkbox() {
            if (!this.appntSign) {
              this.buttomShow = false;
              Dialog.alert({
                message: '请签名'
              }).then(() => {
                // on close
              });
              return
            }
            this.buttomShow = !this.buttomShow;
          },
          draw() {
            var _this = this
            var canvas = document.getElementById(_this.uid)
            _this.sig = new SignaturePad(canvas, _this.option)
            window.addEventListener('resize', _this.resizeCanvas)
            _this.resizeCanvas()
            canvas.addEventListener('touchstart', function (e) {
              e.preventDefault()
              _this.canSave()
            })
            _this.setMark('请在此处使用正楷签名')
          },
          resizeCanvas() {
            var _this = this
            var canvas = document.getElementById(_this.uid)
            var url
            var ratio = Math.max(window.devicePixelRatio || 1, 1)
            canvas.width = canvas.offsetWidth * ratio
            canvas.height = canvas.offsetHeight * ratio
            canvas.getContext('2d').scale(ratio, ratio)
            _this.clear()
            !_this.clearOnResize && url !== undefined && _this.fromDataURL(url)
          },
          clear() {
            var _this = this
            _this.sig.clear()
            this.canSaveBtn = false
          },
          canSave() {
            this.canSaveBtn = true
          },
          toSign() {
            this.appntSign = ''
            this.showSign = true
            this.buttomShow = false;
            this.$nextTick(() => {
              this.draw()
            })
          },
          keepSign() { //保存签名
            var _this = this
            if (_this.isEmpty()) {
              return
            }
            _this.appntSign = _this.sig.toDataURL().split(',')[1]
            _this.showSign = false
            clearInterval(this.time)
            let id = _this.setWatermark('请在此处使用正楷签名');
            let rotate = document.getElementById(id).style.transform
            console.log(rotate)
            document.getElementById(id).style.display = 'none'
            let img = document.getElementById('signImg')
            debugger
            if (!rotate) {
              img.style.height = '65px'
              img.style.width = ''
              img.style.marginBottom = '-20px'
              img.style.marginLeft = '15px'
              img.style.transform = ''
              _this.needRotate = '0'
            } else {
              img.style.width = '65px'
              img.style.height = ''
              img.style.marginBottom = '-50px'
              img.style.marginLeft = '35px'
              img.style.transform = 'rotate(-90deg)'
              _this.needRotate = '1'
            }
          },
          cancel() {
            this.$emit('callback')
          },
          save(format) {
            var _this = this
            var str = "";
            if (!_this.appntSign) {
              Dialog.alert({
                message: '请签名'
              }).then(() => {
                // on close
              });
              return
            }
            let params = {
              contNo: _this.contNo,
              status: "02",
              imgBase64: _this.appntSign,
              index: "0",
              faceImageFlag: sessionStorage.getItem("faceImageFlag"),
              needRotate: _this.needRotate
            }
            questionnaireSubmit(params).then(result => {
              if (result && result.errorCode === "1") {
                _this.getdata = result.responseBody;
                str = _this.getdata.appntName + "," + _this.getdata.contNo + "," + _this.getdata.mainRiskName + "," + _this.getdata.addRiskName + "," + _this.getdata.statusLabel + "," + _this.getdata.visitDate + "," + _this.getdata.visitStatus + "," + _this.num;
                sessionStorage.setItem("camera", true); //true (正在进行中)  false  (下一次重新开始)
                _this.$router.push({ path: "end", query: { postdata: str } })
              } else {
                _this.$toast(result.errorMessage)
              }
            })
              .catch(rej => {
                console.log("签名", rej)
              })
            _this.buttomShow = !_this.buttomShow
          },
          fromDataURL(url) {
            var _this = this
            _this.sig.fromDataURL(url)
          },
          isEmpty() {
            var _this = this
            return _this.sig.isEmpty()
          },
          undo() {
            var _this = this
            var data = _this.sig.toData()
            if (data) {
              data.pop()
              _this.sig.fromData(data)
            }
          },
          setWatermark(str) { // 水印背景设置
            let id = '1.23452384164.123412416';
            if (document.getElementById(id) !== null) {
              document.body.removeChild(document.getElementById(id));
            }
            //创建一个画布
            let can = document.createElement('canvas');
            //设置画布的长宽
            can.width = 500;
            can.height = 100;
    
            let cans = can.getContext('2d');
            //旋转角度
            // cans.rotate(-15 * Math.PI / 180);
            cans.font = '40px Vedana';
            //设置填充绘画的颜色、渐变或者模式
            cans.fillStyle = 'rgba(200, 200, 200, 0.40)';
            //设置文本内容的当前对齐方式
            cans.textAlign = 'left';
            //设置在绘制文本时使用的当前文本基线
            cans.textBaseline = 'Middle';
            //在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)
            cans.fillText(str, can.width / 8, can.height / 2);
    
            let div = document.createElement('div');
            div.id = id;
            div.style.pointerEvents = 'none';
            div.style.position = 'fixed';
            div.style.zIndex = '100000';
            let e = document.getElementsByClassName('canvas')[0]
            let height = e.offsetHeight
            let width = e.offsetWidth
            console.log(width)
            console.log(height)
            if (width > height) { // 横屏
              div.style.width = width + 'px';
              div.style.height = height + 'px';
              div.style.top = '20px';
              div.style.left = '15px';
            } else { // 竖屏
              div.style.width = height + 'px';
              div.style.height = width + 'px';
              div.style.top = 20 + (height - width) / 2 + 'px';
              div.style.right = 15 - (height - width) / 2 + 'px';
              div.style.transform = 'rotate(90deg)'
            }
            div.style.background = 'url(' + can.toDataURL('image/png') + ') center center no-repeat';
            document.body.appendChild(div);
            return id;
          },
          setMark(str) { // 显示水印背景
            let id = this.setWatermark(str);
            this.time = setInterval(() => {
              if (document.getElementById(id) === null) {
                id = this.setWatermark(str);
              }
            }, 500);
            window.onresize = () => {
              this.setWatermark(str);
            };
          }
        },
        mounted() {
    
        }
      }
    /* eslint-disable */
    </script>
    
    <style>
      #app {
        font-family: Avenir, Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        color: #2c3e50;
        margin-top: 60px;
      }
    
      .content {
        background: #fff;
        padding: 20px 23px 35px;
        min-height: 200px;
    
      }
    
      .content h4 {
        font-size: 16px;
        margin-bottom: 20px;
        color: #333;
      }
    
      .content p {
        color: #666;
        font-size: 14px;
      }
    
      .content div.btn {
         150px;
        height: 40px;
        line-height: 40px;
        text-align: center;
        background: #31A4FF;
        color: #fff;
        font-size: 16px;
        margin: 15px auto 40px;
      }
    
      .content span {
        color: #666;
        font-size: 14px;
      }
    
      /* 竖屏情况下 */
      @media screen and (orientation:portrait) {
        .signBox {
          position: absolute;
          top: 0;
          left: 0;
          bottom: 0;
           100%;
          background: #fff;
          z-index: 10000;
    
    
        }
    
        .canvass {
          padding: 20px 15px;
           100%;
          height: 90%;
          box-sizing: border-box;
        }
    
        canvas {
           100%;
          height: 100%;
          border: 1px dashed #333;
          border-radius: 8px;
        }
    
        .footer {
          text-align: center;
          height: 10%;
          padding: 10px 0;
          writing-mode: vertical-lr;
          box-sizing: border-box;
    
        }
    
        .footer span {
          border: 1px solid #999;
          color: #999;
          height: 30vw;
           40px;
          display: inline-block;
          line-height: 40px;
          font-size: 16px;
          text-align: center;
          background: #fff;
          margin-top: -40px;
          margin-left: 24vw;
          transform: rotate(90deg)
        }
    
        .footer span:last-child {
          background: #ccc;
          color: #fff;
          border-color: transparent;
          margin-left: 34vw;
        }
    
        .footer span.active {
          background: #31A4FF;
          color: #fff;
        }
      }
    
      /* 横屏情况下 */
      @media screen and (orientation:landscape) {
        .signBox {
          position: absolute;
          top: 0;
          left: 0;
          bottom: 0;
           100%;
          background: #fff;
          z-index: 10000;
    
        }
    
        .canvass {
          float: left;
          padding: 12px 10px;
           90%;
          height: 100%;
          box-sizing: border-box;
        }
    
        canvas {
           100%;
          height: 100%;
          border: 1px dashed #333;
          border-radius: 5px;
        }
    
        .footer {
          text-align: center;
          float: right;
           10%;
          height: 100%;
          padding: 0 5px;
          box-sizing: border-box;
          writing-mode: vertical-lr;
    
        }
    
        .footer span {
          border: 1px solid #999;
          color: #999;
           22px;
          height: 30vh;
          display: inline-block;
          line-height: 22px;
          font-size: 8px;
          text-align: center;
          background: #fff;
          margin-top: calc (13vh - 20px);
        }
    
        .footer span:last-child {
          background: #ccc;
          color: #fff;
          border-color: transparent;
          margin-top: 14vh;
        }
    
        .footer span.active {
          background: #31A4FF;
          color: #fff;
        }
      }
    
      .take-photo {
        margin: auto;
      }
    
      .take-photo #submit {
        background: #31A4FF;
        color: #fff;
        font-size: 16px;
        text-align: center;
        margin: 15px auto;
         90%;
        height: 100%;
        line-height: 1.5;
      }
    
      .take-photo #submit2 {
        background: #E0E0E0;
        color: #fff;
        font-size: 16px;
        text-align: center;
        margin: 15px auto;
         90%;
         90%;
        height: 100%;
        line-height: 1.5;
      }
    
      .mobile-ts {
        color: #4c4c4c;
        font-size: 12px;
        padding: 10px 10px 0px 25px;
        position: relative;
        text-indent: 25px;
    
      }
    
      .imgSpan {
        position: absolute;
        left: 25px;
        text-indent: 0;
      }
    
      .mobile-ts .imgSpan img {
         16px;
        height: 16px;
      }
    </style>

     

  • 相关阅读:
    职场中如何沟通 15条技巧现在学
    白领丽人:这六行盛产“钻石王老五”
    个人创业融资中的八大法律问题
    [转帖]用心领导先于理性管理
    职场中牢固人际关系的三十六计
    创业:如何制定最佳融资决策
    工作中如何演绎好你的职场情绪
    怎么成为一个成功的人
    创业不得不看:华商富豪们的成功哲学
    一流简历的10大关注项
  • 原文地址:https://www.cnblogs.com/liuxuande/p/14025571.html
Copyright © 2011-2022 走看看