使用组件
<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>