Skip to content

Commit e1a5e05

Browse files
committed
refactor: 将手势触摸事件统一交给 useSwipeGesture 处理
1 parent 2808b9b commit e1a5e05

2 files changed

Lines changed: 90 additions & 77 deletions

File tree

src/composables/interaction/useSwipeGesture.ts

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,59 +15,84 @@ interface TouchOrigin {
1515
timestamp: number;
1616
}
1717

18-
export function useSwipeGesture(options: SwipeGestureOptions) {
19-
let origin: TouchOrigin | null = null;
18+
interface SwipeGestureState {
19+
options: SwipeGestureOptions;
20+
origin: TouchOrigin | null;
21+
}
22+
23+
export function useSwipeGesture(
24+
options: SwipeGestureOptions | SwipeGestureOptions[],
25+
) {
26+
const states: SwipeGestureState[] = (
27+
Array.isArray(options) ? options : [options]
28+
).map((gestureOptions) => ({
29+
options: gestureOptions,
30+
origin: null,
31+
}));
2032

2133
function onTouchStart(event: TouchEvent) {
22-
if (event.touches.length !== 1 || options.canStart?.(event) === false) {
23-
origin = null;
24-
return;
25-
}
34+
for (const state of states) {
35+
if (
36+
event.touches.length !== 1 ||
37+
state.options.canStart?.(event) === false
38+
) {
39+
state.origin = null;
40+
continue;
41+
}
2642

27-
const touch = event.touches[0];
28-
origin = {
29-
x: touch.clientX,
30-
y: touch.clientY,
31-
timestamp: Date.now(),
32-
};
43+
const touch = event.touches[0];
44+
state.origin = {
45+
x: touch.clientX,
46+
y: touch.clientY,
47+
timestamp: Date.now(),
48+
};
49+
}
3350
}
3451

3552
function onTouchEnd(event: TouchEvent) {
36-
if (!origin || event.changedTouches.length !== 1) {
37-
origin = null;
38-
return;
39-
}
53+
for (const state of states) {
54+
if (!state.origin || event.changedTouches.length !== 1) {
55+
state.origin = null;
56+
continue;
57+
}
4058

41-
const start = origin;
42-
const touch = event.changedTouches[0];
43-
origin = null;
59+
const start = state.origin;
60+
const touch = event.changedTouches[0];
61+
state.origin = null;
4462

45-
if (Date.now() - start.timestamp > (options.maxDuration ?? 700)) return;
63+
if (
64+
Date.now() - start.timestamp >
65+
(state.options.maxDuration ?? 700)
66+
)
67+
continue;
4668

47-
const deltaX = touch.clientX - start.x;
48-
const deltaY = touch.clientY - start.y;
49-
const minDistance = options.minDistance ?? 64;
50-
const axisRatio = options.axisRatio ?? 1.25;
51-
const horizontal = Math.abs(deltaX) > Math.abs(deltaY) * axisRatio;
52-
const vertical = Math.abs(deltaY) > Math.abs(deltaX) * axisRatio;
69+
const deltaX = touch.clientX - start.x;
70+
const deltaY = touch.clientY - start.y;
71+
const minDistance = state.options.minDistance ?? 64;
72+
const axisRatio = state.options.axisRatio ?? 1.25;
73+
const horizontal = Math.abs(deltaX) > Math.abs(deltaY) * axisRatio;
74+
const vertical = Math.abs(deltaY) > Math.abs(deltaX) * axisRatio;
5375

54-
const matched =
55-
(options.direction === 'left' &&
56-
horizontal &&
57-
deltaX <= -minDistance) ||
58-
(options.direction === 'right' &&
59-
horizontal &&
60-
deltaX >= minDistance) ||
61-
(options.direction === 'up' &&
62-
vertical &&
63-
deltaY <= -minDistance) ||
64-
(options.direction === 'down' && vertical && deltaY >= minDistance);
76+
const matched =
77+
(state.options.direction === 'left' &&
78+
horizontal &&
79+
deltaX <= -minDistance) ||
80+
(state.options.direction === 'right' &&
81+
horizontal &&
82+
deltaX >= minDistance) ||
83+
(state.options.direction === 'up' &&
84+
vertical &&
85+
deltaY <= -minDistance) ||
86+
(state.options.direction === 'down' &&
87+
vertical &&
88+
deltaY >= minDistance);
6589

66-
if (matched) options.onSwipe();
90+
if (matched) state.options.onSwipe();
91+
}
6792
}
6893

6994
function onTouchCancel() {
70-
origin = null;
95+
for (const state of states) state.origin = null;
7196
}
7297

7398
return { onTouchStart, onTouchEnd, onTouchCancel };

src/views/MobileEditor.vue

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<template>
22
<div
33
class="mobile-editor"
4-
@touchstart="handleTouchStart"
5-
@touchend="handleTouchEnd"
6-
@touchcancel="handleTouchCancel"
4+
@touchstart="editorGesture.onTouchStart"
5+
@touchend="editorGesture.onTouchEnd"
6+
@touchcancel="editorGesture.onTouchCancel"
77
>
88
<HelpDocument v-if="windowStore.isHelpOpen" />
99
<MobileTopBar />
@@ -59,46 +59,34 @@ const bottomPanelNames: MobileBottomPanelName[] = [
5959
'exportFormat',
6060
];
6161
62-
const openLeftDrawerGesture = useSwipeGesture({
63-
direction: 'right',
64-
canStart: (event) => !hasOpenOverlay() && event.touches[0].clientX <= 24,
65-
onSwipe: mobileUiStore.openLeftDrawer,
66-
});
67-
const openBottomDrawerGesture = useSwipeGesture({
68-
direction: 'up',
69-
canStart: (event) =>
70-
!hasOpenOverlay() &&
71-
event.touches[0].clientY >= window.innerHeight - 72,
72-
onSwipe: () => {
73-
const activePanel = windowStore.activeLeftPanelName;
74-
const panel = bottomPanelNames.includes(
75-
activePanel as MobileBottomPanelName,
76-
)
77-
? (activePanel as MobileBottomPanelName)
78-
: 'chunkList';
79-
windowStore.setLeftPanel(panel, { revealSidebar: false });
80-
mobileUiStore.openBottomPanel();
62+
const editorGesture = useSwipeGesture([
63+
{
64+
direction: 'right',
65+
canStart: (event) =>
66+
!hasOpenOverlay() && event.touches[0].clientX <= 24,
67+
onSwipe: mobileUiStore.openLeftDrawer,
8168
},
82-
});
69+
{
70+
direction: 'up',
71+
canStart: (event) =>
72+
!hasOpenOverlay() &&
73+
event.touches[0].clientY >= window.innerHeight - 72,
74+
onSwipe: () => {
75+
const activePanel = windowStore.activeLeftPanelName;
76+
const panel = bottomPanelNames.includes(
77+
activePanel as MobileBottomPanelName,
78+
)
79+
? (activePanel as MobileBottomPanelName)
80+
: 'chunkList';
81+
windowStore.setLeftPanel(panel, { revealSidebar: false });
82+
mobileUiStore.openBottomPanel();
83+
},
84+
},
85+
]);
8386
8487
function hasOpenOverlay() {
8588
return Boolean(mobileUiStore.activeOverlay || windowStore.isHelpOpen);
8689
}
8790
88-
function handleTouchStart(event: TouchEvent) {
89-
openLeftDrawerGesture.onTouchStart(event);
90-
openBottomDrawerGesture.onTouchStart(event);
91-
}
92-
93-
function handleTouchEnd(event: TouchEvent) {
94-
openLeftDrawerGesture.onTouchEnd(event);
95-
openBottomDrawerGesture.onTouchEnd(event);
96-
}
97-
98-
function handleTouchCancel() {
99-
openLeftDrawerGesture.onTouchCancel();
100-
openBottomDrawerGesture.onTouchCancel();
101-
}
102-
10391
onUnmounted(mobileUiStore.reset);
10492
</script>

0 commit comments

Comments
 (0)