vue拖拽图片认证

vue 拖拽图片验证

手机端效果 做了两套事件,没有放到一块做兼容,

拖拽认证

 - 踩到的坑, 范围没有判断好会发生快速滑动卡顿,
 if (moveX < 0) {
                     moveX = 0;
                 } 
if (moveX + this.$refs.block.offsetWidth >= this.$refs.blockimg.offsetWidth) {
       moveX =this.$refs.blockimg.offsetWidth - this.$refs.block.offsetWidth;  // this.$refs.blockimg.offsetWidth  滑动范围  - this.$refs.block.offsetWidth  滑块大小
   }

做了两套事件,没有放到一块做兼容, 有空做兼容
@mousedown=“sliderDown”
@touchstart=“touchStartEvent”
@touchmove=“touchMoveEvent”
@touchend=“touTouchend”

		// 在另一个组件引用
   <getcode ref="skuCard" @success="onSuccess"></getcode>
	// 点击打开弹窗
	   obtainValidateFn(yzmCode) {   // 调取弹窗组件
        // 未输入手机号不能调取组件
        this.$refs.skuCard.openCard();
      
    },
  **页面**
<template>
  <div class="getCode">
    <van-popup  v-model="show" :overlay="false" close-icon="close" position="bottom" >
      <div class="background">
        <div class="top">
          <div class="validation">请完成安全验证</div>
          <van-icon class="vant-icon-cross" @click="cancel" name="cross" />
        </div>
        <div class="image">
          <img class="img" ref="blockimg" :src="captcha.img" alt />
          <van-icon class="vantt-icon-replay" @click="refresh" name="replay" />
          <!-- @touchend="touTouchend" -->
          <img
            ref="block"
            @mousedown="sliderDown"
            @touchstart="touchStartEvent"
            @touchmove="touchMoveEvent"
            @touchend="touTouchend"
            :style="{top:captcha.verify_block_y+'px',left:sliderLeft}"
            class="slide-block-img"
            :src="captcha.slide_block_img"
            alt
          />
        </div>
        <div class="loading" v-if="loading">
          <van-loading class="vant-loading" color="#1989fa" />
        </div>
         <div class="placeholder">{{resultText}}</div>
        <div class="slide-verify-slider-mask" :style="{width: sliderMaskWidth}">
          <!-- slider -->
          <div
            class="slide-verify-slider-mask-item"
            :style="{left: sliderLeft ,}"
            @mousedown="sliderDown"
            @touchstart="touchStartEvent"
            @touchmove="touchMoveEvent"
            @touchend="touTouchend"
          >
            <van-icon class="vant-icon-arrow" name="arrow" />
          </div>
         
        </div>
      </div>
    </van-popup>
  </div>
</template>

**script 代码块**

<script>

import { getcode, checkcode } from "../../server/api/getcode";
import { Toast } from "vant"; // 提示

export default {
  props: {},
  data() {
    return {
    placeholder:'向右滑动滑块',
      show: false,
      sliderLeft: 0, // 滑块的Left
      sliderMaskWidth: 0, // 滑块 阴影的宽
      captcha: {},
      token: "",
      motion_locus: [],
      trail: [],
      isMouseDown: false,
      loading: false, // 控制 loading 显示隐藏
    };
  },
  computed: {
          resultText() {
      let text = this.placeholder;
      if (this.loading) {
        text = '加载中';
      }
      return text;
    },
  },
  created() {
   
  },
  watch: {},
  methods: {
    // 获取滑块信息
    getSliderCode() {
      this.loading = true;
        
      if (document.body.clientWidth >= 1000) {  // 判断页面的宽 分辨是移动端 还是H5端
        getcode(this.$axios, {
          width: 1433,
          height: 665,
        }).then((res) => {
          if (res.code == 200) {
            this.loading = false;
            this.token = res.response.token;
            this.captcha = res.response.captcha;
          }
        });
      } else {
        getcode(this.$axios, {
          width: 280,
          height: 130,
        }).then((res) => {
          if (res.code == 200) {
            this.loading = false;
            this.token = res.response.token;
            this.captcha = res.response.captcha;
          }
        });
      }
    },

    //  手指触摸屏幕
    touchStartEvent(e) {
            var slider = document.querySelector('.slide-verify-slider-mask-item')
            var sliderMaskWidth = document.querySelector('.slide-verify-slider-mask')
            slider.style.transition = "";
            sliderMaskWidth.style.transition = ''
            this.originX = e.changedTouches[0].pageX;
            this.originY = e.changedTouches[0].pageY;
            this.isMouseDown = true;
            console.log(111)
    },

    // 手指移动
    touchMoveEvent(e) {
      if (!this.isMouseDown) return false;
      let moveX = e.changedTouches[0].pageX - this.originX;
      let moveY = e.changedTouches[0].pageY - this.originY;
   
      if (moveX < 0) {
          moveX = 0;
       } 
     if (moveX + this.$refs.block.offsetWidth >= this.$refs.blockimg.offsetWidth) {
                moveX =this.$refs.blockimg.offsetWidth - this.$refs.block.offsetWidth;
        }
     
      this.sliderLeft = moveX + "px";
      this.sliderMaskWidth = moveX + "px";
    //   this.trail.push(moveY);
      // this.positionx =e.clientX - this.originX + this.$refs.block.offsetLeft - 8;
      this.positionx = Math.trunc(e.changedTouches[0].pageX - this.originX); // 取整
      this.positiony = this.captcha.verify_block_y;
      // console.log(this.positionx);
      //   console.log(this.positiony);
      this.motion_locus.push({
        block_position: {
          x: this.positionx,
          y: this.positiony,
        },
        time_stamp: (this.now = Date.parse(new Date())),
      });
    },

    //  手指离开
    touTouchend(e) {
                var sliderLeft = document.querySelector('.slide-verify-slider-mask-item')  // 获取dom元素
                var sliderMaskWidth = document.querySelector('.slide-verify-slider-mask')
                sliderLeft.style.transition = "left 0.4s ease-out 0s"; // 给dom元素添加动画
                sliderMaskWidth.style.transition = 'width 0.4s ease-out 0s'

                this.left_topy = this.positiony;
                this.left_topx = this.positionx;
                //   console.log("this.left_topy", this.left_topy);
                //   console.log("this.left_topx", this.left_topx);
                this.right_topx = this.positionx + this.$refs.block.offsetWidth;
                this.right_topy = this.positiony;
                //   console.log(this.$refs.blockimg.offsetWidth);
                // console.log(this.right_topx);
                // console.log(this.right_topy);

                this.left_bottomy = this.captcha.verify_block_y + this.$refs.block.offsetWidth;
                this.left_bottomx = this.positionx;

                // console.log(this.$refs.blockimg.offsetHeight);
                //   console.log(this.left_bottomy)
                //   console.log(this.left_bottomx)
                this.right_bottomx = this.positionx + this.$refs.block.offsetWidth;
                this.right_bottomy = this.captcha.verify_block_y + this.$refs.block.offsetWidth;


                //   console.log(this.right_bottomx);
                //   console.log(this.right_bottomy);
                this.isMouseDown = false;
                this.setCheckcode();
    },

    //   鼠标按下事件
    sliderDown(e) {
        var slider = document.querySelector('.slide-verify-slider-mask-item')
        var sliderMaskWidth = document.querySelector('.slide-verify-slider-mask')
        slider.style.transition = "";
        sliderMaskWidth.style.transition = ''
        this.originX = e.clientX;
        this.originY = e.clientY;
        this.isMouseDown = true;
      // console.log(this.clientX)

      //   鼠标移动事件

      document.onmousemove = (e) => {
            if (!this.isMouseDown) return false;
            if (!this.isMouseDown) return false;
            const moveX = e.clientX - this.originX;
            const moveY = e.clientY - this.originY;
              if (moveX < 0) {
                     moveX = 0;
                 } 
              if (moveX + this.$refs.block.offsetWidth >= this.$refs.blockimg.offsetWidth) {
                   moveX =this.$refs.blockimg.offsetWidth - this.$refs.block.offsetWidth;
               }
            this.sliderLeft = moveX + "px";
            this.sliderMaskWidth = moveX + "px";
            this.positionx = Math.trunc(e.clientX - this.originX);
            this.positiony = this.captcha.verify_block_y;
            e.preventDefault()
        //   console.log(this.positionx);
        //   console.log(this.positiony);
        this.motion_locus.push({
              block_position: {
                x: this.positionx,
                y: this.positiony,
             },
             time_stamp: (this.now = Date.parse(new Date())),
        });
      },
        //  鼠标释放事件
        document.onmouseup = (e) => {
                    this.isMouseDown = false;
                    var sliderLeft = document.querySelector('.slide-verify-slider-mask-item')  // 获取dom元素
                    var sliderMaskWidth = document.querySelector('.slide-verify-slider-mask')
                    sliderLeft.style.transition = "left 0.4s ease-out 0s"; // 给dom元素添加动画
                    sliderMaskWidth.style.transition = 'width 0.4s ease-out 0s'
                    this.left_topy = this.positiony;
                    this.left_topx = this.positionx;
                    this.right_topx = this.positionx + this.$refs.block.offsetWidth;
                    this.right_topy = this.positiony;
                    this.left_bottomy = this.captcha.verify_block_y + this.$refs.block.offsetWidth;
                    this.left_bottomx = this.positionx;
                    this.right_bottomx = this.positionx + this.$refs.block.offsetWidth;
                    this.right_bottomy =this.captcha.verify_block_y + this.$refs.block.offsetWidth;
                    this.setCheckcode();
        };
    },
    // 打开弹窗
    openCard(type) {
                this.show = true;
                // 获取图片数据
                this.getSliderCode();
    },
    // 刷新
    refresh() {
            this.getSliderCode();
            this.motion_locus = []; // 刷新后清空验证信息
            this.sliderLeft = 0;
            this.sliderMaskWidth = 0;
    },

    // 取消
    cancel() {
      this.sliderLeft = 0;
      this.sliderMaskWidth = 0;
      this.show = false;
    },

    // 提交滑块信息

    setCheckcode() {
      checkcode(this.$axios, {
        token: this.token,
        motion_locus: this.motion_locus,
        block_info: {
          left_top: {
            x: this.left_topx,
            y: this.left_topy,
          },
          right_top: {
            x: this.right_topx,
            y: this.right_topy,
          },
          left_bottom: {
            x: this.left_bottomx,
            y: this.left_bottomy,
          },
          right_bottom: {
            x: this.right_bottomx,
            y: this.right_bottomy,
          },
        },
      }).then((res) => {
        if (res.code == 200) {
          this.$emit("success", res.response.result);
          this.result = res.response.result
          // console.log(this.checkcodes);
          if (res.response.result == true) {
            Toast(res.response.msg);
            (this.motion_locus = []), // 验证成功后清空提交push信息,会影响下次提交
              setTimeout(() => {
                this.cancel();
              }, 500);
          } else {
            Toast("验证失败,请重新验证...");
            this.refresh();
          }
        }
      });
    },
  },
  components: {},
};
</script>

**##	scss代码**


.getCode {
  .background {
    width: 296px;
    height: 231px;
    margin: 0 auto;
    
    // background: #fff;
    .top {
      display: flex;

      .validation {
        font-size: 18px;
        padding: 10px 0 0 20px;
      }
      .vant-icon-cross {
        margin: 10px 0 0 120px;
        font-size: 15px;
      }
    }
    .image {
      width: 280px;
      height: 130px;
      margin: 10px auto;

      .img {
        width: 280px;
        height: 130px;
        position: absolute;
      }
      .slide-block-img {
        position: relative;
        // width: 50px;
        // height: 50px;
        z-index: 99;
      }
      .vantt-icon-replay {
        position: absolute;
        z-index: 99;
        padding-left: 255px;
        color: #fff;
        font-size: 18px;
      }
    }
    .loading {
      position: absolute;
      width: 281px;
      height: 131px;
      z-index: 99;
      top: 40px;
    margin-left: 7px;
      background: #e5e5e5;
      .vant-loading {
        margin: 50px auto;
      }
    }
  .placeholder{
       border: 1px solid #e5e5e5;
        // height: 100%;
        width: 280px;
        text-align: center;
        line-height: 30px;
        font-size: 14px;
        margin: 19px 0 0 7px;
        color: #333;
        box-sizing: border-box;
        border-radius: 2px;
        -webkit-user-select: none;
        -ms-user-select: none;
        user-select: none
            
   }
    .slide-verify-slider-mask {
      position: absolute;
     margin-left: 8px;
      top: 190px;
      height: 30px;
      background: #d1e9fe;
        opacity: .9;
    }
    .slide-verify-slider-mask-item {
      position: absolute;
      top: 0;
      left: 0;
      width: 50px;
      height: 30px;
      background: rgb(14, 77, 165);
      text-align: center;
    }
    .vant-icon-arrow {
      color: #fff;
      line-height: 30px;
      font-size: 14px;
    }
  }
}

> 两个事件放到一块做兼容PC 和 安卓

 methods: {
    bindEvents() {
      this.body.addEventListener("mousedown", handleDragStart);
      this.body.addEventListener("touchstart", handleDragStart);

      document.addEventListener("mousemove", this.handleDragMove);
      document.addEventListener("touchmove", this.handleDragMove);
      document.addEventListener("mouseup", this.handleDragEnd);
      document.addEventListener("touchend", this.handleDragEnd);
    },
    // 获取滑块信息
    getSliderCode() {
      this.loading = true;

      if (document.body.clientWidth >= 1000) {
        // 判断页面的宽 分辨是移动端 还是H5端
        getcode(this.$axios, {
          width: 906,
          height: 420,
        }).then((res) => {
          if (res.code == 200) {
            this.loading = false;
            this.token = res.response.token;
            this.captcha = res.response.captcha;
          }
        });
      } else {
        getcode(this.$axios, {
          width: 280,
          height: 130,
        }).then((res) => {
          if (res.code == 200) {
            this.loading = false;
            this.token = res.response.token;
            this.captcha = res.response.captcha;
          }
        });
      }
    },

    //  手指触摸屏幕
    handleDragStart(e) {
      let slider = document.querySelector(".slide-verify-slider-mask-item");
      let sliderMaskWidth = document.querySelector(".slide-verify-slider-mask");
      slider.style.transition = "";
      sliderMaskWidth.style.transition = "";
      this.originX = e.clientX || e.changedTouches[0].pageX;
      this.originY = e.clientY || e.changedTouches[0].pageY;
      this.isMouseDown = true;
    },

    // 手指移动
    handleDragMove(e) {
      if (!this.isMouseDown) return false;
      let eventX = e.clientX || e.changedTouches[0].pageX;
      let eventY = e.clientY || e.changedTouches[0].pageY;
      let moveX = eventX - this.originX;
      let moveY = eventY - this.originY;
      if (moveX < 0) {
        moveX = 0;
      }
      if (
        moveX + this.$refs.block.offsetWidth >=
        this.$refs.blockimg.offsetWidth
      ) {
        moveX = this.$refs.blockimg.offsetWidth - this.$refs.block.offsetWidth;
      }
      this.sliderLeft = moveX + "px";
      this.sliderMaskWidth = moveX + "px";
      this.trail.push(moveY);
      this.positionx = Math.trunc(eventX - this.originX); // 取整
      this.positiony = this.captcha.verify_block_y;

      this.motion_locus.push({
        block_position: {
          x: this.positionx,
          y: this.positiony,
        },
        time_stamp: (this.now = Date.parse(new Date())),
      });
    },

    //  手指离开
    handleDragEnd(e) {
      this.isMouseDown = false;
      let slider = document.querySelector(".slide-verify-slider-mask-item"); // 获取dom元素
      let sliderMaskWidth = document.querySelector(".slide-verify-slider-mask");
      slider.style.transition = "left 0.4s ease-out 0s"; // 给dom元素添加动画
      sliderMaskWidth.style.transition = "width 0.4s ease-out 0s";
      this.left_topy = this.positiony;
      this.left_topx = this.positionx;

      this.right_topx = this.positionx + this.$refs.block.offsetWidth;
      this.right_topy = this.positiony;

      this.left_bottomy =
        this.captcha.verify_block_y + this.$refs.block.offsetWidth;
      this.left_bottomx = this.positionx;

      this.right_bottomx = this.positionx + this.$refs.block.offsetWidth;
      this.right_bottomy =
        this.captcha.verify_block_y + this.$refs.block.offsetWidth;

      this.setCheckcode();
    },

    // 打开弹窗
    openCard(type) {
      this.show = true;
      // 获取图片数据
      this.getSliderCode();
    },
    // 刷新
    refresh() {
      this.getSliderCode();
      this.motion_locus = []; // 刷新后清空验证信息
      this.sliderLeft = 0;
      this.sliderMaskWidth = 0;
    },

    // 取消
    cancel() {
      this.sliderLeft = 0;
      this.sliderMaskWidth = 0;
      this.show = false;
    },

    // 提交滑块信息

    setCheckcode() {
      checkcode(this.$axios, {
        token: this.token,
        motion_locus: this.motion_locus,
        block_info: {
          left_top: {
            x: this.left_topx,
            y: this.left_topy,
          },
          right_top: {
            x: this.right_topx,
            y: this.right_topy,
          },
          left_bottom: {
            x: this.left_bottomx,
            y: this.left_bottomy,
          },
          right_bottom: {
            x: this.right_bottomx,
            y: this.right_bottomy,
          },
        },
      }).then((res) => {
        if (res.code == 200) {
          this.$emit("success", res.response.result);
          this.result = res.response.result;
          // console.log(this.checkcodes);
          if (res.response.result == true) {
            Toast(res.response.msg);
            (this.motion_locus = []), // 验证成功后清空提交push信息,会影响下次提交
              setTimeout(() => {
                this.cancel();
              }, 500);
          } else {
            Toast("验证失败,请重新验证...");
            this.refresh();
          }
        }
      });
    },
  },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值