1 封装一个函数swipe
type Point = {
x: number;
y: number;
}
export const useSwipe = (element: Ref<HTMLElement | undefined>) => {
const start = ref<Point>()
const end = ref<Point>()
const swiping = ref(false)
const distance = computed(() => {
if (!start.value || !end.value) { return null }
return {
x: end.value.x - start.value.x,
y: end.value.y - start.value.y,
}
})
const direction = computed(() => {
if (!distance.value) { return '' }
const { x, y } = distance.value
if (Math.abs(x) > Math.abs(y)) {
return x > 0 ? 'right' : 'left'
} else {
return y > 0 ? 'down' : 'up'
}
})
const onStart = (e: TouchEvent) => {
options?.beforeStart?.(e)
swiping.value = true
end.value = start.value = { x: e.touches[0].screenX, y: e.touches[0].screenY }
options?.afterStart?.(e)
}
const onMove = (e: TouchEvent) => {
options?.beforeMove?.(e)
if (!start.value) { return }
end.value = { x: e.touches[0].screenX, y: e.touches[0].screenY, }
options?.afterMove?.(e)
}
const onEnd = (e: TouchEvent) => {
options?.beforeEnd?.(e)
swiping.value = false
options?.afterEnd?.(e)
}
onMounted(() => {
if (!element.value) { return }
element.value.addEventListener('touchstart', onStart)
element.value.addEventListener('touchmove', onMove)
element.value.addEventListener('touchend', onEnd)
})
onUnmounted(() => {
if (!element.value) { return }
element.value.removeEventListener('touchstart', onStart)
element.value.removeEventListener('touchmove', onMove)
element.value.removeEventListener('touchend', onEnd)
})
return {
swiping,
direction,
distance,
}
}
2. 在组件中使用swipe
export const Welcome = defineComponent({
setup: (props, context) => {
const main = ref<HTMLElement>()
const { direction, swiping } = useSwipe(main)
const route = useRoute()
const router = useRouter()
const replace = throttle(() => {
const name = (route.name || 'Welcome1').toString()
router.replace(pushMap[name])
}, 500)
watchEffect(() => {
if (swiping.value && direction.value === 'left') {
replace()
}
})
return () => <div class={s.wrapper}>
<header>
<span>我是标题</span>
</header>
<main class={s.main} ref={main}>
<RouterView name="main">
{({ Component: X, route: R }: { Component: VNode, route: RouteLocationNormalizedLoaded }) =>
<Transition enterFromClass={s.slide_fade_enter_from} enterActiveClass={s.slide_fade_enter_active}
leaveToClass={s.slide_fade_leave_to} leaveActiveClass={s.slide_fade_leave_active}>
{X}
</Transition>
}
</RouterView>
</main>
</div>
}
})