vue滑块验证组件(支持自定义图片)

vue滑块验证组件(支持自定义图片)_第1张图片

子组件

<template>
  <div style="padding: 6px 7px">
    <div class="box" :style="getStyle(1)">
      <img :style="getStyle(1)" :src="`data:image/jpeg;base64,${data.image}`" alt="">
      <div class="slids"  :style="{'left': elePos.x + 'px', 'top': elePos.y + 'px', ...getStyle(3) }">
        <img style="width: 100%; height: 100%" :src="`data:image/jpeg;base64,${data.slide}`" alt="">
      </div>
    </div>
    <div class="slidBox" :style="getStyle(2)">
      <div class="slidBoxItem"></div>
      <img  class="slid" :style="{width: '52px', height: '52px', margin: '1px 0 0 0','left': elePos.x + 'px', 'top': elePos.y + 'px' }" 
        src="@/assets/images/saleAndPurchase/handler_bg.png" alt=""
        @mousedown.self="dragStartHandler"
        @touchstart.stop="dragStartHandler"
        @mousemove="draggingHandler"
        @touchmove.stop="draggingHandler"
        @mouseup="dragEndHandler"
        @touchend.stop="dragEndHandler"
      >
      <!-- <div class="slid" :style="{'left': elePos.x + 'px', 'top': elePos.y + 'px' }"
        @mousedown.self="dragStartHandler"
        @touchstart.stop="dragStartHandler"
        @mousemove="draggingHandler"
        @touchmove.stop="draggingHandler"
        @mouseup="dragEndHandler"
        @touchend.stop="dragEndHandler">
      </div> -->
    </div>
    <div class="repossessColse">
      <img @click.stop="close" style="width: 24px; height: 24px; margin: 0 16px" src="@/assets/images/saleAndPurchase/closes.png" alt="">
      <img @click.stop="repossess" style="width: 24px; height: 24px" src="@/assets/images/saleAndPurchase/repossess.png" alt="">
    </div>
  </div>
</template>

<script>
/**
 * 必传参数 data
 * data={ width:number,height:number,randomStr:string,pos:{height:number},slideWidth:number,slideHeight:number,image:string}
 * ******************************
 * 回调方法 callBack(type,distance)
 * type: 按下滑块|拖动滑块|松开滑块
 * distance: 滑块已滑动的距离
 */
export default {
  props:['data'],
  components: {},
  data() {
    return {
      fatherbox: null,
      innerbox: null,
      slidsbox: null,
      width: 300,
      height: 186,
      // width: 300,
      // height: 186,
      // randomStr: '"123540010cdf4d6eb3ce86eee1894d92"',
      // pos:{
      //   height: 42
      //   width: 108
      // },
      // slideWidth:83,
      // slideHeight: 37,
      // 元素位置,用于样式绑定,动态更新位置(:style="{left: `${x}px`, top: `${y}px`}")
      elePos: {
        x: null,
        y: null
      },
      // 手指(鼠标)触摸点[即拖拽开始的位置]距离拖拽元素左上角的距离
      diffOfTarget: {
        x: 0,
        y: 0
      }
    };
  },
  created() {
    console.log(this.data);
  },
  mounted() {
    this.$nextTick(() => {
      this.fatherbox = document.querySelector('.van-popup');
      this.innerbox = document.querySelector('.slid');
      this.slidsbox = document.querySelector('.slids');
    });
  },
  methods: {
    getStyle(e){
      if(e == 1){
        return {
          width: this.data.width+'px',
          height: this.data.height+'px',
        }
      }else if(e == 2){
        return {
          width: this.data.width+'px',
        }
      }else if(e == 3){
        return {
          width: this.data.slideWidth+'px',
          height: this.data.slideHeight+'px',
          top: this.data.pos.height + 6 + 'px',
        }
      }
    },
    dragStartHandler (e) {
      let touch = e
      if (e.touches) {
        touch = e.touches[0]
      }
      this.diffOfTarget.x = touch.clientX - e.target.offsetLeft
      this.diffOfTarget.y = touch.clientY - e.target.offsetTop
      // 解决滑动穿透问题
      let scrollTop = document.scrollingElement.scrollTop
      // console.log(scrollTop)
      // todo 在项目的全局样式下,需要定义一个modal-open的样式类
      /**
       * body.modal-open {
       *   position: fixed;
       *   width: 100%;
       *   min-height: 100%;
       * }
       */
      document.body.classList.add('modal-open')
      document.body.style.top = -scrollTop + 'px'
      // console.log(this.diffOfTarget.y);
      let dragEndHandlerLeft = this.innerbox.offsetLeft-7
      this.$emit('callBack','dragStartHandler',dragEndHandlerLeft)
    },
    draggingHandler (e) {
      let touch = e
      if (e.touches) {
        touch = e.touches[0]
      }
      // 设置拖拽元素的位置
      this.elePos.x = touch.clientX - this.diffOfTarget.x // 左右拖拽
      // this.elePos.y = touch.clientY - this.diffOfTarget.y // 上下拖拽(不需要)

      // let limitWidth = this.data.width-e.target.clientWidth-1 || 244 || window.screen.width
      /**
       * 限制元素不能超过滑道
       * this.slidsbox.offsetWidth | 图片缺块宽度
       * e.target.clientWidth | 滑块宽度
       */
      let limitWidth = this.fatherbox.offsetWidth - this.slidsbox.offsetWidth  - 7 // 滑动距离-滑块宽度-父元素padding | 
      let limitHeight = window.screen.height
      if (this.elePos.x < 7) {
        this.elePos.x = 7
      } else if (this.elePos.x > limitWidth) {
        this.elePos.x = limitWidth
      }
      if (this.elePos.y < 0) {
        this.elePos.y = 0
      } else if (this.elePos.y > limitHeight) {
        this.elePos.y = limitHeight - e.target.clientHeight
      }

      // console.log('limitWidth',limitWidth,'this.elePos.x =',this.elePos.x );
      // console.log('滑动距离',this.innerbox.offsetLeft);
      // console.log('滑块宽度',this.innerbox.offsetWidth);

      // console.log('父元素距离',this.fatherbox.offsetLeft);
      // console.log('父元素宽度',this.fatherbox.offsetWidth);
      let dragEndHandlerLeft = this.innerbox.offsetLeft-7
      this.$emit('callBack','draggingHandler',dragEndHandlerLeft)
    },
    dragEndHandler (e) {
      // console.log('松开距离',this.innerbox.offsetLeft-7);
      let dragEndHandlerLeft = this.innerbox.offsetLeft-7
      document.body.classList.remove('modal-open')
      this.$emit('callBack','dragEndHandler',dragEndHandlerLeft)
    },
    repossess() { // 刷新
      this.elePos.x = null
      this.diffOfTarget.x = 0
      // this.innerbox.offsetLeft = 0

      let scrollTop = document.scrollingElement.scrollTop
      console.log('scrollTop',scrollTop);
      document.body.classList.add('modal-open')
      document.body.style.top = -scrollTop + 'px'
      // this.innerbox.offsetLeft = 7
      document.body.classList.remove('modal-open')
      this.$emit('repossess')
    },
    close() {
      this.$emit('close')
    }
  },
};
</script>

<style lang="scss" scoped>
.box {
  width: 350px;
  height: 100px;
  overflow: hidden;
}
.repossessColse {
  height: 40px;
  display: flex;
  justify-content: flex-end;
  flex-direction: row;
  align-items:flex-end;
}
.slidBox {
  width: 100%;
  height: 52px;
  overflow: none;
  margin: auto;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  .slidBoxItem {
    width: 98%;
    height: 37px;
    background-color: #E6E6E6;
    border-radius: 50px;
  }
  &::-webkit-scrollbar {
    width: 0px; /*对垂直流动条有效*/
    height: 0px; /*对水平流动条有效*/
    // background-color: red;
  }
  .slid {
    width: 52px;
    height: 52px;
  }
}
.slid {
  position: fixed;
  left: 7px;
  bottom: 46px;
  // width: 36px;
  // height: 36px;
  cursor: pointer;
}
.slids {
  position: fixed;
  left: 7px;
  top: 0px;
  width: 50px;
  height: 50px;
  cursor: pointer;
  // background-color: yellow;
}
</style>

父组件

<slide-verification-puzzle
 v-if="show"
 @callBack="callBack"  
 @close="show = false"
 @repossess="repossess()"
 ref="slider"
 :data="encodedImage"
></slide-verification-puzzle>

你可能感兴趣的:(封装组件,vue.js,javascript,前端)