ant-design-vue/components/vc-virtual-list/hooks/useMobileTouchMove.ts

86 lines
2.1 KiB
TypeScript
Raw Normal View History

2021-06-26 01:35:40 +00:00
import type { Ref } from 'vue';
2022-01-22 06:19:36 +00:00
import { onBeforeUnmount, watch, onMounted } from 'vue';
2020-09-28 11:14:00 +00:00
const SMOOTH_PTG = 14 / 15;
2020-10-01 09:20:10 +00:00
export default function useMobileTouchMove(
inVirtual: Ref<boolean>,
2020-10-17 04:14:13 +00:00
listRef: Ref<HTMLDivElement | undefined>,
2020-10-01 09:20:10 +00:00
callback: (offsetY: number, smoothOffset?: boolean) => boolean,
) {
2020-09-28 11:14:00 +00:00
let touched = false;
let touchY = 0;
2020-10-01 09:20:10 +00:00
let element: HTMLElement | null = null;
2020-09-28 11:14:00 +00:00
// Smooth scroll
2020-10-01 09:20:10 +00:00
let interval: any = null;
2020-09-28 11:14:00 +00:00
2020-10-01 09:20:10 +00:00
const cleanUpEvents = () => {
if (element) {
2022-01-22 06:19:36 +00:00
element.removeEventListener('touchmove', onTouchMove);
2020-10-01 09:20:10 +00:00
element.removeEventListener('touchend', onTouchEnd);
}
};
2020-09-28 11:14:00 +00:00
2020-10-01 09:20:10 +00:00
const onTouchMove = (e: TouchEvent) => {
2020-09-28 11:14:00 +00:00
if (touched) {
const currentY = Math.ceil(e.touches[0].pageY);
let offsetY = touchY - currentY;
touchY = currentY;
if (callback(offsetY)) {
e.preventDefault();
}
// Smooth interval
clearInterval(interval);
interval = setInterval(() => {
offsetY *= SMOOTH_PTG;
if (!callback(offsetY, true) || Math.abs(offsetY) <= 0.1) {
clearInterval(interval);
}
}, 16);
}
};
const onTouchEnd = () => {
touched = false;
cleanUpEvents();
};
2020-10-01 09:20:10 +00:00
const onTouchStart = (e: TouchEvent) => {
2020-09-28 11:14:00 +00:00
cleanUpEvents();
if (e.touches.length === 1 && !touched) {
touched = true;
touchY = Math.ceil(e.touches[0].pageY);
2020-10-01 09:20:10 +00:00
element = e.target as HTMLElement;
2022-01-22 06:19:36 +00:00
element!.addEventListener('touchmove', onTouchMove, { passive: false });
2020-10-01 09:20:10 +00:00
element!.addEventListener('touchend', onTouchEnd);
2020-09-28 11:14:00 +00:00
}
};
2022-01-22 06:19:36 +00:00
const noop = () => {};
2020-09-28 11:14:00 +00:00
2021-02-25 05:37:15 +00:00
onMounted(() => {
2022-01-22 06:19:36 +00:00
document.addEventListener('touchmove', noop, { passive: false });
2021-02-25 05:37:15 +00:00
watch(
inVirtual,
val => {
2022-01-22 06:19:36 +00:00
listRef.value.removeEventListener('touchstart', onTouchStart);
2021-02-25 05:37:15 +00:00
cleanUpEvents();
clearInterval(interval);
if (val) {
2022-01-22 06:19:36 +00:00
listRef.value.addEventListener('touchstart', onTouchStart, { passive: false });
2021-02-25 05:37:15 +00:00
}
},
{ immediate: true },
2020-12-10 09:40:46 +00:00
);
2020-09-28 11:14:00 +00:00
});
2022-01-22 06:19:36 +00:00
onBeforeUnmount(() => {
document.removeEventListener('touchmove', noop);
});
2020-09-28 11:14:00 +00:00
}