Vue项目中手搓滑动校验模块-demo

332 篇文章 80 订阅

实现代码

SliderCheck.vue

<template>
  <div class="drag" ref="dragDiv">
    <div class="drag_bg" ref="dragBg"></div>
    <div class="drag_text" ref="dragText">{{ confirmWords }}</div>
    <div
      ref="moveDiv"
      @mousedown="mouseDownFn($event)"
      @touchstart="touchStartFn($event)"
      :class="{ handler_ok_bg: confirmSuccess }"
      class="handler handler_bg flx-center"
      style="position: absolute; top: -1px; left: -1px">
      <icon-arrow-right class="base-icon"></icon-arrow-right>
    </div>
  </div>
</template>

<script setup lang="ts">
// 距离屏幕左端距离
const beginClientX = ref(0)
// 触发拖动状态  判断
const mouseMoveState = ref(false)
// 拖动最大宽度,依据滑块宽度算出来的
const maxWidth = ref("")
// 滑块文字
const confirmWords = ref("请按住滑块,拖动到最右边")
// 验证成功判断
const confirmSuccess = ref(false)
const dragDiv = ref(null)
const dragBg = ref(null)
const dragText = ref(null)
const moveDiv = ref(null)

const emit = defineEmits(["status-changed"])

// 验证成功函数
const successFunction = () => {
  confirmSuccess.value = true
  confirmWords.value = "验证通过"
  // 移除事件监听
  document.getElementsByTagName("html")[0].removeEventListener("mousemove", mouseMoveFn)
  document.getElementsByTagName("html")[0].removeEventListener("mouseup", moseUpFn)

  document.getElementsByTagName("html")[0].removeEventListener("touchmove", touchMoveFn)
  document.getElementsByTagName("html")[0].removeEventListener("touchend", touchEndFn)

  ;(dragText.value as any)!.style.color = "#fff"
  ;(moveDiv.value as any).style.left = `${maxWidth.value}px`
  ;(dragBg.value as any).style.width = `${maxWidth.value}px`

  emit("status-changed", "success")
}

// mouse事件 鼠标按下 开始
const mouseDownFn = (e: any) => {
  if (!confirmSuccess.value) {
    e.preventDefault && e.preventDefault() // 阻止文字选中等 浏览器默认事件
    mouseMoveState.value = true
    beginClientX.value = e.clientX
  }
}

// mousemove事件 移动
const mouseMoveFn = (e: any) => {
  if (mouseMoveState.value) {
    let width = e.clientX - beginClientX.value
    if (width > 0 && width <= Number(maxWidth.value)) {
      ;(moveDiv.value as any).style.left = `${width}px`
      ;(dragBg.value as any).style.width = `${width}px`
    } else if (width > Number(maxWidth.value)) {
      successFunction()
    }
  }
}
// mouseup事件 结束
const moseUpFn = (e: any) => {
  mouseMoveState.value = false
  const width = e.clientX - beginClientX.value
  if (width < Number(maxWidth.value)) {
    ;(moveDiv.value as any).style.left = `${0}px`
    ;(dragBg.value as any).style.width = `${0}px`
  }
}

// =====================兼容移动端移动事件=============================
// touch事件 按下 开始
const touchStartFn = (e: TouchEvent) => {
  if (!confirmSuccess.value) {
    e.preventDefault()
    mouseMoveState.value = true
    beginClientX.value = e.touches[0].clientX
  }
}
// touch事件 移动
const touchMoveFn = (e: TouchEvent) => {
  if (mouseMoveState.value) {
    let width = e.touches[0].clientX - beginClientX.value
    if (width > 0 && width <= Number(maxWidth.value)) {
      ;(moveDiv.value as any).style.left = `${width}px`
      ;(dragBg.value as any).style.width = `${width}px`
    } else if (width > Number(maxWidth.value)) {
      successFunction()
    }
  }
}
// touch事件 结束
const touchEndFn = (e: TouchEvent) => {
  mouseMoveState.value = false
  const width = e.changedTouches[0].clientX - beginClientX.value
  if (width < Number(maxWidth.value)) {
    ;(moveDiv.value as any).style.left = `${0}px`
    ;(dragBg.value as any).style.width = `${0}px`
  }
}
// =====================兼容移动端移动事件end=============================

onMounted(() => {
  maxWidth.value = String((dragDiv.value as any)!.clientWidth - (moveDiv.value as any)!.clientWidth - 1)

  document.getElementsByTagName("html")[0].addEventListener("mousemove", mouseMoveFn)
  document.getElementsByTagName("html")[0].addEventListener("mouseup", moseUpFn)

  document.getElementsByTagName("html")[0].addEventListener("touchmove", touchMoveFn)
  document.getElementsByTagName("html")[0].addEventListener("touchend", touchEndFn)
})
</script>
<style scoped>
.drag {
  position: relative;
  box-sizing: border-box;
  width: 100%;
  height: 39px;
  line-height: 38px;
  text-align: center;
  background-color: rgb(204 204 204 / 20%);
  border: 1px solid #cccccc;
  border-radius: 4px;
}
.handler {
  box-sizing: border-box;
  width: 46px;
  height: 38px;
  cursor: move;
  border: 1px solid #cccccc;
  border-radius: 4px;
}
.handler_bg {
  background: #ffffff;
}
.handler_ok_bg {
  background: #ffffff;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
.drag_bg {
  width: 0;
  height: 38px;
  background-color: #0cc399;
  border-radius: 4px 0 0 4px;
}
.drag_text {
  position: absolute;
  top: 0;
  width: 100%;
  font-size: var(--el-font-size-base);
  font-weight: 400;
  color: var(--el-color-info-light-3);
  text-align: center;
  user-select: none;
}
</style>

使用

<template>
  <a-form class="large-form">
    <a-form-item>
      <SliderCheck ref="sliderCheckRef" @status-changed="changeSliderStatus"></SliderCheck>
    </a-form-item>
  </a-form>
</template>

<script setup lang="ts">
const sliderCheckRef = ref()
const isValidated = ref(false)
const asyncPhoneIsValid = ref(false)
const changeSliderStatus = async (status: string) => {
  isValidated.value = status === "success"
  try {
    asyncPhoneIsValid.value = validateInfos.mobile.validateStatus === "success"
  } catch (err: any) {
    asyncPhoneIsValid.value = false
  }
}
</script>

<style lang="scss" scoped>
</style>

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JackieDYH

谢谢您嘞!我会继续加油地

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值