vue 拖拽滑块验证

651 阅读1分钟

7E25DA~1.PNG 7ACAA1~1.PNG

使用组件

<div style="width: 100%">
    <DragVerify @dragRes="dragRes"></DragVerify>
</div>

dragRes(mark: boolean) {
    console.log('拖拽滑块成功否:', mark)
}

代码块

<template>
    <div :class="['drag-verify', { success: validation }]">
        <div class="solid" @mousedown="solidStar"></div>
        <div class="solid1" id="solid1"></div>

        <span>按住滑块,拖动到最右边</span>
    </div>
</template>

<script lang="ts">
import { Component, Vue, Emit } from 'vue-property-decorator'

@Component({
    name: 'DragVerify',
    components: {},
})
export default class DragVerify extends Vue {
    /** 拖拽成功否 */
    public validation = false
    /** 移动距离 */
    public moveX = 0
    /** 拖拽的成功返回 */
    @Emit('dragRes')
    public dragRes(mark: boolean) {
        return mark
    }

    // 鼠标按下时
    solidStar(e: any) {
        // console.log(e)
        const solid1 = document.getElementById('solid1') as any
        // 获取当前DOM元素宽度 鼠标当前点击位置
        let solidDom = e.target
        let moveStart = e.clientX
        let solidDomWith = solidDom.offsetWidth
        // 父节点减去滑块宽度获取滑块最大移动距离
        let MaxW = e.path[1].clientWidth - solidDomWith
        // 设置判断条件 防止验证成功后鼠标移动方法继续被调用
        if (this.validation === true) {
            return false
        }
        // 鼠标移动
        ;(document.onmousemove = e => {
            // 获取移动时鼠标距离浏览器左上角到当前位置的X轴距离
            let endX = e.clientX
            // 从上面获取到的数据计算出鼠标移动的距离
            this.moveX = endX - moveStart
            // 判断如果用户反方向移动将移动距离赋值为零
            if (this.moveX <= 0) {
                this.moveX = 0
            }
            // 判断如果滑块移动距离大于最大宽度  给其赋值最大宽度
            if (this.moveX >= MaxW) {
                this.moveX = MaxW
            }
            // 为了更好地体验 写上动画 要不都不写  不然其他动画会覆盖向右拖拽动作
            solidDom.style.transition = '0s all'
            solidDom.style.left = this.moveX + 'px'

            solid1.style.transition = '0s all'
            solid1.style.width = this.moveX + 'px'
            // 很关键的地方 e.preventDefault()这个方法会关闭与当前事件关联的其他动作 只执行此事件
            e.preventDefault()
        }),
            // 鼠标抬起
            (document.onmouseup = () => {
                // 如果鼠标抬起后拖拽距离没到可移动距离最大值将返回起点0
                if (this.moveX !== MaxW) {
                    solidDom.style.transition = '.5s linear'
                    solidDom.style.left = 0
                    solid1.style.transition = '.5s linear'
                    solid1.style.width = 0 + 'px'
                    this.dragRes(false)
                } else {
                    // 如果成功设置判断条件
                    this.validation = true
                    this.dragRes(true)
                }
                // 动作完成后将事件清空
                document.onmousemove = null
                document.onmouseup = null
            })
    }
}
</script>

<style lang="less" scoped>
.drag-verify {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 36px;
    background-color: #999;
    color: #fff;
    .solid {
        position: absolute;
        left: 0;
        z-index: 2;
        display: flex;
        align-items: center;
        justify-content: center;
        box-sizing: border-box;
        width: 36px;
        height: 36px;
        border: 1px solid #666;
        background-color: #fff;
        color: #000;
        cursor: pointer;
        &::after {
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            content: '⋙';
            text-align: center;
        }
    }
    .solid1 {
        position: absolute;
        left: 0;
        z-index: 1;
        height: 36px;
        border: 1px solid #358097;
        background: #1aad19;
    }
    &.success {
        .solid {
            &::after {
                color: #1aad19;
                content: '✔';
            }
        }
        .solid1 {
            &::after {
                position: absolute;
                top: 0;
                right: 0;
                bottom: 0;
                left: 0;
                color: #fff;
                content: '验证通过';
                text-align: center;
            }
        }
    }
}
</style>