vue3 Element-plus setup ts 滑动组件验证

效果如下:

vue3 滑块验证演示


<template>
  <div class="slider-verification" ref="sliderContainer">
    <div class="slider-left-bg" :style="sliderLeftWidthStyle"></div>
    <div class="prompt-text" :style="verifySuccess ? promptTextStyleSuccess: {}">
      {
   
   { verifySuccess ? '验证通过' : '向右拖动滑块进行验证' }}
    </div>
    <div ref="slider" @mousedown="mouseDownHandler($event)" :class="{'slider-verify-success':verifySuccess}"
      class="slider" :style="sliderToLeftStyle">
      <el-icon v-if="verifySuccess" :size="iconSize" color="#fff">
        <CircleCheck />
      </el-icon>
      <el-icon v-else :size="iconSize" color="#fff">
        <DArrowRight />
      </el-icon>
    </div>
  </div>
</template>

<script  setup lang="ts">
interface Props {
  multiple: number,
  promptTextStyleSuccess: Record<any, any>
}

interface Emits {
  (e: 'statusChange', val: boolean): void
}

const props = withDefaults(defineProps<Props>(), {
  multiple: 2,
  promptTextStyleSuccess: () => ({
    color: '#ffffff'
  })
})
const emits = defineEmits<Emits>()


let sliderState = ref(false)
let verifySuccess = ref(false)
let beginClientX = ref(0)
let maxWidth = ref(0)
const iconSize = ref(22)
const slideWidth = ref(0)

//鼠标移动
const mouseMoveHandler = (e) => {
  if (sliderState.value) {
    let width = (e.clientX - beginClientX.value) / props.multiple;
    if (width > 0 && width <= maxWidth.value) {
      slideWidth.value = width
    } else if (width > maxWidth.value) {
      slideWidth.value = maxWidth.value
      verifySuccessFun();
    }
  }
}

//鼠标松开
const mouseUpHandler = (e) => {
  sliderState.value = false;
  let width = (e.clientX - beginClientX.value) / props.multiple;
  if (width < maxWidth.value) {
    slideWidth.value = 0
  }
}

//验证通过
const verifySuccessFun = () => {
  verifySuccess.value = true
  emits('statusChange', true)
  document.getElementsByTagName('html')[0].removeEventListener('mousemove', mouseMoveHandler);
  document.getElementsByTagName('html')[0].removeEventListener('mouseup', mouseUpHandler);
  slideWidth.value = maxWidth.value
}
const slider = ref(null)
const sliderContainer = ref(null)


//事件监听
const addListener = () => {
  document.getElementsByTagName('html')[0].addEventListener('mousemove', mouseMoveHandler);
  document.getElementsByTagName('html')[0].addEventListener('mouseup', mouseUpHandler)
}

// 重置
const reset = () => {
  addListener()
  emits('statusChange', false)
  beginClientX.value = 0
  sliderState.value = false
  verifySuccess.value = false
  slideWidth.value = 0
}
// 鼠标在滑块上按下事件
const mouseDownHandler = (e) => {
  if (!verifySuccess.value) {
    sliderState.value = true;
    beginClientX.value = e.clientX;
  }
}

onMounted(() => {
  maxWidth.value = sliderContainer.value.offsetWidth - slider.value.offsetWidth;
  addListener()
})
const sliderToLeftStyle = computed(() => ({ left: slideWidth.value + 'px' }))
const sliderLeftWidthStyle = computed(() => ({ width: slideWidth.value + 'px' }))

defineExpose({
  reset
})
</script>

.slider-verification {
  position: relative;
  background-color: var(--ep-color-primary);
  width: 100%;
  height: 100%;
  line-height: 48px;
  text-align: center;
  user-select: none;
}

.slider {
  position: absolute;
  top: 0;
  width: 42px;
  height: 48px;
  cursor: move;
  background: var(--ep-color-primary-light-5);
  background-size: 30px 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.slider-verify-success {
  background: var(--ep-color-primary-light-5);
  background-size: 30px 30px;
}

//滑块滑过区域的样式
.slider-left-bg {
  // background-color: rgba(0, 235, 255, 0.42);
  background: rgba(0, 235, 255, 0.3);
  width: 0;
  height: 100%;
}

//提示文本样式
.prompt-text {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 48px;
  text-align: center;
  font-size: 14px;
  line-height: 48px;
  color: #ffffff;
}

猜你喜欢

转载自blog.csdn.net/qq_38902432/article/details/126893929