123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- <!-- @format -->
- <script lang="ts" setup>
- import { Check, DArrowRight } from '@element-plus/icons-vue'
- defineProps({
- // 成功图标
- successIcon: {
- type: String,
- default: 'iconfont icon-status-nor',
- },
- // 成功文字
- successText: {
- type: String,
- default: '验证成功',
- },
- // 开始的图标
- startIcon: {
- type: String,
- default: 'iconfont icon-login-slid',
- },
- // 开始的文字
- startText: {
- type: String,
- default: '拖动滑块到最右边',
- },
- })
- const modelValue = defineModel('value')
- const verifyResult = ref(false) // 验证结果
- const isTouch = (function () {
- if (typeof document === 'undefined' || !document.documentElement)
- return false
- return 'ontouchstart' in document.documentElement
- })()
- const moveEvent = isTouch ? 'touchmove' : 'mousemove'
- const upEvent = isTouch ? 'touchend' : 'mouseup'
- // 滑块触摸开始
- function onStart(ev: MouseEvent | TouchEvent) {
- let disX = 0 // 滑块移动距离
- const iconWidth = 40 // 滑动图标宽度
- const ele = document.querySelector('.drag-verify .block') as HTMLElement
- const startX
- = (ev as MouseEvent).clientX || (ev as TouchEvent).touches[0].pageX
- const parentWidth = ele.offsetWidth
- const MaxX = parentWidth - iconWidth
- if (verifyResult.value)
- return false
- // 滑块触摸移动
- const onMove = (e: MouseEvent | TouchEvent) => {
- const endX = (e as MouseEvent).clientX || (e as TouchEvent).touches[0].pageX
- disX = endX - startX
- if (disX <= 0)
- disX = 0
- if (disX >= MaxX - iconWidth)
- disX = MaxX
- ele.style.transition = '.1s all'
- ele.style.transform = `translateX(${disX}px)`
- }
- // 滑块触摸结束
- const onEnd = () => {
- if (disX !== MaxX) {
- ele.style.transition = '.5s all'
- ele.style.transform = 'translateX(0)'
- }
- else {
- // 执行成功
- verifyResult.value = true
- // emit('update:value', verifyResult.value)
- modelValue.value = verifyResult.value
- }
- document.removeEventListener(moveEvent, onMove)
- document.removeEventListener(upEvent, onEnd)
- }
- document.addEventListener(moveEvent, onMove)
- document.addEventListener(upEvent, onEnd)
- }
- </script>
- <template>
- <div class="drag-verify">
- <div class="range" :class="verifyResult ? 'success' : ''">
- <div class="block" @mousedown="onStart" @touchstart="onStart">
- <el-icon v-if="verifyResult" class="icon">
- <Check />
- </el-icon>
- <el-icon v-else class="icon">
- <DArrowRight />
- </el-icon>
- </div>
- <span class="text">{{ verifyResult ? successText : startText }}</span>
- </div>
- </div>
- </template>
- <style lang="less" scoped>
- @primary-color: #CC9879;
- .drag-verify {
- width: 100%;
- .range {
- background-color: #ececee;
- position: relative;
- border-radius: 4px;
- transition: 1s all;
- user-select: none;
- color: #666;
- overflow: hidden;
- display: flex;
- justify-content: center;
- align-items: center;
- height: 40px;
- &.success {
- background-color: @primary-color;
- color: #fff;
- .text {
- position: relative;
- z-index: 1;
- }
- .block .icon {
- color: @primary-color;
- }
- }
- .block {
- display: block;
- position: absolute;
- left: calc(-100% + 40px);
- width: 100%;
- height: 100%;
- background: @primary-color;
- border-radius: 4px;
- overflow: hidden;
- .icon {
- position: absolute;
- right: 0;
- width: 40px;
- height: 100%;
- font-size: 20px;
- color: #c8c9cc;
- background-color: #fff;
- border: 1px solid #e5e5e5;
- border-radius: 4px;
- cursor: pointer;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- }
- }
- }
- </style>
|