2020-12-10 09:40:46 +00:00
|
|
|
import supportsPassive from '../../_util/supportsPassive';
|
2021-06-26 01:35:40 +00:00
|
|
|
import type { Ref } from 'vue';
|
|
|
|
import { 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) {
|
2020-12-10 09:40:46 +00:00
|
|
|
element.removeEventListener(
|
|
|
|
'touchmove',
|
|
|
|
onTouchMove,
|
|
|
|
supportsPassive
|
|
|
|
? ({
|
2020-12-18 10:54:18 +00:00
|
|
|
passive: false,
|
2020-12-10 09:40:46 +00:00
|
|
|
} as EventListenerOptions)
|
|
|
|
: false,
|
|
|
|
);
|
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;
|
2020-12-10 09:40:46 +00:00
|
|
|
element!.addEventListener(
|
|
|
|
'touchmove',
|
|
|
|
onTouchMove,
|
|
|
|
supportsPassive
|
|
|
|
? ({
|
2020-12-18 10:54:18 +00:00
|
|
|
passive: false,
|
2020-12-10 09:40:46 +00:00
|
|
|
} as EventListenerOptions)
|
|
|
|
: false,
|
|
|
|
);
|
2020-10-01 09:20:10 +00:00
|
|
|
element!.addEventListener('touchend', onTouchEnd);
|
2020-09-28 11:14:00 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-25 05:37:15 +00:00
|
|
|
onMounted(() => {
|
|
|
|
watch(
|
|
|
|
inVirtual,
|
|
|
|
val => {
|
|
|
|
listRef.value.removeEventListener(
|
|
|
|
'touchstart',
|
|
|
|
onTouchStart,
|
|
|
|
supportsPassive
|
|
|
|
? ({
|
|
|
|
passive: false,
|
|
|
|
} as EventListenerOptions)
|
|
|
|
: false,
|
|
|
|
);
|
|
|
|
cleanUpEvents();
|
|
|
|
clearInterval(interval);
|
|
|
|
if (val) {
|
|
|
|
listRef.value.addEventListener(
|
|
|
|
'touchstart',
|
|
|
|
onTouchStart,
|
|
|
|
supportsPassive
|
|
|
|
? ({
|
|
|
|
passive: false,
|
|
|
|
} as EventListenerOptions)
|
|
|
|
: false,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{ immediate: true },
|
2020-12-10 09:40:46 +00:00
|
|
|
);
|
2020-09-28 11:14:00 +00:00
|
|
|
});
|
|
|
|
}
|