@@ -114,18 +114,6 @@ const FoliateViewer: React.FC<{
|
||||
const detail = (event as CustomEvent).detail;
|
||||
if (detail.reason !== 'scroll' && detail.reason !== 'page') return;
|
||||
|
||||
if (detail.reason === 'scroll') {
|
||||
const renderer = viewRef.current?.renderer;
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
if (renderer && viewSettings.continuousScroll) {
|
||||
if (renderer.start <= 0) {
|
||||
viewRef.current?.prev(1);
|
||||
// sometimes viewSize has subpixel value that the end never reaches
|
||||
} else if (renderer.end + 1 >= renderer.viewSize) {
|
||||
viewRef.current?.next(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
const parallelViews = getParallels(bookKey);
|
||||
if (parallelViews && parallelViews.size > 0) {
|
||||
parallelViews.forEach((key) => {
|
||||
@@ -140,7 +128,7 @@ const FoliateViewer: React.FC<{
|
||||
};
|
||||
|
||||
const { handlePageFlip } = usePageFlip(bookKey, viewRef, containerRef);
|
||||
useTouchEvent(bookKey, viewRef);
|
||||
const { onTouchStart, onTouchMove, onTouchEnd } = useTouchEvent(bookKey, viewRef);
|
||||
useClickEvent(bookKey, handlePageFlip);
|
||||
|
||||
useFoliateEvents(viewRef.current, {
|
||||
@@ -226,6 +214,9 @@ const FoliateViewer: React.FC<{
|
||||
<div
|
||||
className='foliate-viewer h-[100%] w-[100%]'
|
||||
onClick={(event) => handlePageFlip(event)}
|
||||
onTouchStart={onTouchStart}
|
||||
onTouchMove={onTouchMove}
|
||||
onTouchEnd={onTouchEnd}
|
||||
ref={containerRef}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -29,25 +29,25 @@ export const useTouchEvent = (
|
||||
viewRef: React.MutableRefObject<FoliateView | null>,
|
||||
) => {
|
||||
const { hoveredBookKey, setHoveredBookKey, getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
|
||||
let touchStart: IframeTouch | null = null;
|
||||
let touchEnd: IframeTouch | null = null;
|
||||
|
||||
const onTouchStart = (e: IframeTouchEvent) => {
|
||||
const onTouchStart = (e: IframeTouchEvent | React.TouchEvent<HTMLDivElement>) => {
|
||||
touchEnd = null;
|
||||
const touch = e.targetTouches[0];
|
||||
if (!touch) return;
|
||||
touchStart = touch;
|
||||
};
|
||||
|
||||
const onTouchMove = (e: IframeTouchEvent) => {
|
||||
const onTouchMove = (e: IframeTouchEvent | React.TouchEvent<HTMLDivElement>) => {
|
||||
if (!touchStart) return;
|
||||
const touch = e.targetTouches[0];
|
||||
if (touch) {
|
||||
touchEnd = touch;
|
||||
}
|
||||
if (hoveredBookKey && touchEnd) {
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const deltaY = touchEnd.screenY - touchStart.screenY;
|
||||
const deltaX = touchEnd.screenX - touchStart.screenX;
|
||||
if (!viewSettings!.scrolled && !viewSettings!.vertical) {
|
||||
@@ -60,7 +60,7 @@ export const useTouchEvent = (
|
||||
}
|
||||
};
|
||||
|
||||
const onTouchEnd = (e: IframeTouchEvent) => {
|
||||
const onTouchEnd = (e: IframeTouchEvent | React.TouchEvent<HTMLDivElement>) => {
|
||||
if (!touchStart) return;
|
||||
|
||||
const touch = e.targetTouches[0];
|
||||
@@ -70,6 +70,7 @@ export const useTouchEvent = (
|
||||
|
||||
const windowWidth = window.innerWidth;
|
||||
if (touchEnd) {
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const deltaY = touchEnd.screenY - touchStart.screenY;
|
||||
const deltaX = touchEnd.screenX - touchStart.screenX;
|
||||
// also check for deltaX to prevent swipe page turn from triggering the toggle
|
||||
@@ -87,6 +88,34 @@ export const useTouchEvent = (
|
||||
setHoveredBookKey(null);
|
||||
}
|
||||
}
|
||||
const renderer = viewRef.current?.renderer;
|
||||
if (renderer && viewSettings.scrolled && viewSettings.continuousScroll) {
|
||||
const SCROLL_THRESHOLD = 30;
|
||||
const doScroll = () => {
|
||||
// may have overscroll where the start is greater than 0
|
||||
if (renderer.start <= deltaY && deltaY > SCROLL_THRESHOLD) {
|
||||
setTimeout(() => {
|
||||
viewRef.current?.prev(renderer.start + 1);
|
||||
}, 100);
|
||||
// sometimes viewSize has subpixel value that the end never reaches
|
||||
} else if (
|
||||
Math.ceil(renderer.end) - deltaY >= renderer.viewSize &&
|
||||
deltaY < -SCROLL_THRESHOLD
|
||||
) {
|
||||
setTimeout(() => {
|
||||
viewRef.current?.next(renderer.viewSize - Math.floor(renderer.end) + 1);
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
if (renderer.size >= renderer.viewSize) {
|
||||
doScroll();
|
||||
} else {
|
||||
const handleRelocate = () => {
|
||||
doScroll();
|
||||
};
|
||||
renderer.addEventListener('relocate', handleRelocate, { once: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
touchStart = null;
|
||||
@@ -112,4 +141,10 @@ export const useTouchEvent = (
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [hoveredBookKey, viewRef.current]);
|
||||
|
||||
return {
|
||||
onTouchStart,
|
||||
onTouchMove,
|
||||
onTouchEnd,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -48,7 +48,11 @@ export interface FoliateView extends HTMLElement {
|
||||
goTo?: (params: { index: number; anchor: number }) => void;
|
||||
setStyles?: (css: string) => void;
|
||||
getContents: () => { doc: Document; index?: number }[];
|
||||
addEventListener: (type: string, listener: EventListener) => void;
|
||||
addEventListener: (
|
||||
type: string,
|
||||
listener: EventListener,
|
||||
option?: AddEventListenerOptions,
|
||||
) => void;
|
||||
removeEventListener: (type: string, listener: EventListener) => void;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user