在vue3+vant的h5项目开发中,被产品经理要求在PC上实现拼图验证码登录的功能,无奈vant组件只支持touch事件,不支持鼠标的mousedown,mousemove,mouseup事件,只能自己写一个兼容mouse和touch事件的功能。
本着能省则省的原则,代码尽量少写,多余的功能一概不要,直接上代码
<!-- 滑块 -->
<img
:style="{ left: delta + 'px' }"
class="slide-pic-pc"
:src="slide"
alt=""
@mousedown="startDrag"
@touchstart="startDrag"
@mousemove="onDrag"
@touchmove="onDrag"
@mouseup="stopDrag"
@touchend="stopDrag"
/>
<!--进度条 -->
<div class="step-line">
<div class="step-line-active" :style="{ width: delta + 'px' }"></div>
</div>
<script lang="ts">
import { defineComponent, ref, watch, onMounted } from 'vue'
// 省略若干代码
export default defineComponent({
setup() {
const canvasW = ref() // 主图宽度
const blockOffsetX = ref(0) // 小图偏移量
// 校验位置
const validPosition = () => {...}
// 兼容鼠标操作
const start = ref(0)
const end = ref(0)
const isDragging = ref(false) // 是否正在拖动
const delta = ref(0) // 偏移量
// 开始拖拽
const startDrag = (e: any) => {
e.preventDefault() // 阻止默认操作
// 详见 MDN [event.preventDefault - Web API 接口参考 | MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault)
e = e.changedTouches ? e.changedTouches[0] : e // changedTouches为移动端的触摸属性,若没有则为pc端鼠标操作
isDragging.value = true
start.value = Math.round(e.clientX)
}
// 拖拽中
const onDrag = (e: any) => {
e.preventDefault()
e = e.changedTouches ? e.changedTouches[0] : e
if (
isDragging.value &&
e.clientX > start.value && // 控制滑动范围
e.clientX < canvasW.value * 0.9 + start.value // 这里*0.9 是因为进度条的宽度为页面的90%
) {
delta.value = Math.round(e.clientX) - start.value
}
}
// 结束拖拽
const stopDrag = (e: any) => {
e.preventDefault()
e = e.changedTouches ? e.changedTouches[0] : e
isDragging.value = false
end.value = Math.round(e.clientX)
delta.value = Math.abs(start.value - end.value)
validPosition() // 校验位置信息
}
watch(
() => [delta.value],
() => {
blockOffsetX.value = delta.value
},
{ immediate: true }
)
return {...}
},
})
</script>