vue图形验证码滑动组件

<template>
  <div class="captcha_drop" >
    <div class="modal_popup" >
      <div class="captcha-box">
        <div class="captcha_header">
          安全验证
        </div>
        <div class="captcha-inner">
          <img :src="shadeImage"  class="captcha-img" ref="captchaImg">
          <img :src="verImg"  class="block verify_img" :style="{left:posx+'px',top:posY+'px'}" alt="">
        </div>
        <div  class="sliderContainer" :class="validateStatus" ref="sliderContainter">
          <div class="sliderbg"></div>
          <div class="sliderMask" :style="{width: posx+'px'}">
            <div class="slider"  ref="right_btn"  :style="{left:posx+'px'}"
                 @touchstart.stop.prevent="touchstart"
                 @touchmove.stop.prevent="touchmove"
                 @touchend.stop.prevent="touchend">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 20">
                <path fill="#B3B5B7" d="M21.7 10.2l-11.6 9c-.2.2-.5.1-.7-.1-.1-.1-.1-.2-.1-.3v-4.5c0-.3-.2-.5-.5-.5H.7c-.3 0-.5-.2-.5-.5V6.4c0-.3.2-.5.5-.5h8.1c.3 0 .5-.2.5-.5V.8c0-.3.2-.5.5-.5.1 0 .2 0 .3.1l11.6 9c.2.2.2.5 0 .8.1-.1 0 0 0 0z"></path>
              </svg>
            </div>
          </div>
          <span class="sliderText">{{text}}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "verSlider",
  data() {
    return {
      posx:0,
      imgBgVisible: false,
      refreshVisible: false,
      canDrag:false,
      startTime:'',
      endTime:'',
      position:{
        left:0,
      },
      text:'按住左边按钮拖动完成上方拼图',//再试一次
      move:{
        posx:0//差值
      },
      maxWidth:0,//最大宽度
      sliderW:0,
      validateStatus:'',
      verImgH:0,//校验图片高
      imgRatio:1,
    }
  },
  computed: {},
  props:{
    verImg:{
      type:String,
      default:''
    },
    posY:{
      default:0
    },
    shadeImage:{
      type:String,
      default:''
    },
    isSuccess:{
      type:String,
      default:''//'false','true'
    },
    refresh:{
      type:String,
      default:new Date().getTime().toString()
    },
  },
  created() {

  },
  mounted() {
    this.maxWidth=this.$refs.sliderContainter&&this.$refs.sliderContainter.offsetWidth;
    this.sliderW=this.$refs.right_btn&&this.$refs.right_btn.offsetWidth
  },
  methods: {
    touchstart(e){
      if(!this.canDrag){
        this.startTime=e.timeStamp;
        this.positionOld=this.getPosition(this.$refs.right_btn);
        this.position={...this.positionOld};
        this.inset={
          left:e.targetTouches[0].clientX - this.positionOld.left,
        }
        this.canDrag=true;
        this.validateStatus='sliderContainer_active'
      }
    },
    touchmove(e){
      if(this.canDrag){
        let left=e.targetTouches[0].clientX-this.inset.left ;
        if(left<0){
          left=0
        }else if(left>this.maxWidth - this.sliderW){
          left=this.maxWidth- this.sliderW;
        }
        this.posx=left;
        this.move.posx=left-this.positionOld.left;
        this.position = {left};
      }

    },
    touchend(e){
      if(this.canDrag){
        this.endTime=e.timeStamp;
       if(this.endTime-this.startTime>500|| Math.abs(this.move.posx) > 2 ){
         this.$emit('validate',{x:parseInt(this.posx)})
         //debugger
       }else{
         this.posx=-1;
         this.validateStatus='';
         this.canDrag=false
       }
      }
    },
    /*重置*/
   resetStatus(){
     this.inset={};
     this.move={};
     this.position={};
     this.posx=0;
     this.canDrag=false;
     this.validateStatus='';
     this.text='再试一次'
    },
    getPosition(source){
      let left=source.offsetLeft;
      let current=source.offsetParent;
      while (current=null){
        left+=current.offsetLeft;
      }
      return{
        left,
      }

    }
  },
  watch:{
    refresh(newValue,oldValue){
      if(this.isSuccess==='false'){
        this.validateStatus='sliderContainer_fail';
        setTimeout(()=>{
          this.resetStatus();
        },1000)
      }else  if(this.isSuccess==='true'){
        this.validateStatus='sliderContainer_success';
      }
    },


  }

}
</script>

<style scoped lang="scss">
div,img,span{
  margin:0px;
  padding:0px;
}
$h:35Px;
.block {
  position: absolute;
  left: 0;
  top: 0;
}

.sliderContainer {
  position: relative;
  text-align: center;
  line-height:$h;
  height:$h;
  background: #f7f9fa;
  color: #45494c;
  border-radius: 2px;
  margin:20px auto;
}

.sliderbg {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  background-color: #f7f9fa;
  height: $h;
  border-radius: 2px;
  border: 1Px solid #e6e8eb;
}

.sliderContainer_active{
  .slider {
    top: -1Px;
    border: 1Px solid #1991FA;
  }
  .sliderMask {
    border-width: 1Px 0 1Px 1Px;
  }
}
.sliderContainer_success{
  .slider {
    top: -1Px;
    border: 1Px solid #52CCBA;
  }
  .sliderMask {
    border: 1Px solid #52CCBA;
    border-width: 1Px 0 1Px 1Px;
    background-color: #D2F4EF;
  }
}
.sliderContainer_fail {
  .slider {
    top: -1Px;
    border: 1Px solid #f57a7a;

  }
}
.sliderContainer_fail{
  .sliderMask {
    border: 1Px solid #f57a7a;
    background-color: #fce1e1;
    border-width: 1Px 0 1Px 1Px;
  }
}

.sliderContainer_active .sliderText, .sliderContainer_success .sliderText, .sliderContainer_fail .sliderText {
  display: none;
}

.sliderMask {
  position: absolute;
  left: 0;
  top: 0;
  height: $h;
  border: 0 solid #1991FA;
  background: #D1E9FE;
  border-radius: 2Px;
}

.slider {
  position: absolute;
  top: 1Px;
  left: 0;
  width: $h;
  height: $h;
  background: #fff;
  box-shadow: 0 0 3Px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  transition: background .2s linear;
  border-radius: 2Px;
  display: flex;
  align-items: center;
  justify-content: center;
  svg {
    display: block;
    width: 60%;
    height: 60%;
    font-size: unset;
  }
}

.sliderText {
  position: relative;
  font-size:13Px;
  text-align:center;
  color: #999
}
.captcha-box{
  width:312Px;
  padding:0px 6Px;
  margin:0px auto;
  position: relative;
  box-sizing: border-box;

}
.captcha-inner{
  position:relative;
  width:100%;
  overflow: hidden;
  min-height:200Px;
}

.captcha-img{
   max-width:300Px;
  vertical-align: top;

}
.originImage{
  position:absolute;
  left:0px;
  right:0px;
  visibility: hidden;
  width:auto;
  height:auto;
}
.captcha_drop {
  position: fixed;
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,.5);
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  z-index: 1000;
  -webkit-tap-highlight-color: transparent;
}
.modal_popup{
  position: absolute;
  z-index: 9999;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  background:#f8f8f8;
  border-radius: 4Px;
  overflow: hidden;
}
.captcha_header{
  font-size: 15Px;
  line-height: 40Px;
  height: 40Px;
  color: #333;
  text-align: center;
  position: relative;
}
</style>
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容