Skip to content

Commit b01c359

Browse files
YamanquiTod-Naturlich
authored andcommitted
Added touch controls to navigate presentations. (#876)
Co-authored-by: Tod Naturlich <[email protected]>
1 parent 5b3744c commit b01c359

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

CHANGELOG.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- Add support for mobile navigation of slides.
6+
[#876](https://github.com/FormidableLabs/spectacle/pull/876)
7+
38
## 6.0.2
49

5-
- Allow for `props.fontSize` to override the theme's monospace font size in `CodePane`. [#875](https://github.com/FormidableLabs/spectacle/pull/875)
6-
- Surface `textDecoration` prop from styled-system for `Link`s. [#869](https://github.com/FormidableLabs/spectacle/pull/869)
10+
- Allow for `props.fontSize` to override the theme's monospace font size in `CodePane`.
11+
[#875](https://github.com/FormidableLabs/spectacle/pull/875)
12+
- Surface `textDecoration` prop from styled-system for `Link`s.
13+
[#869](https://github.com/FormidableLabs/spectacle/pull/869)
714

815
## 6.0.1
916

src/components/deck/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import usePresentation, {
1919
MSG_SLIDE_STATE_CHANGE
2020
} from '../../hooks/use-presentation';
2121
import useKeyboardControls from '../../hooks/use-keyboard-controls';
22+
import useTouchControls from '../../hooks/use-touch-controls';
2223
import {
2324
DEFAULT_SLIDE_ELEMENT_INDEX,
2425
DEFAULT_SLIDE_INDEX
@@ -208,6 +209,11 @@ const Deck = props => {
208209
toggleMode
209210
});
210211

212+
useTouchControls({
213+
navigateToNext,
214+
navigateToPrevious
215+
});
216+
211217
const { runTransition } = React.useContext(TransitionPipeContext);
212218
const slideTransitionEffect =
213219
filteredChildren[state.currentSlide].props.transitionEffect || {};

src/hooks/use-touch-controls.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react';
2+
3+
/**
4+
* Hook that navigates to next or previous slide when the user swipes
5+
* left or right in a touch device, where there is no keyboard.
6+
*/
7+
const useTouchControls = ({ navigateToNext, navigateToPrevious }) => {
8+
const touchId = React.useRef(null); // To keep track of which touch started the swipe.
9+
const startTouchX = React.useRef(0); // Where the swipe started.
10+
11+
const threshold = 100; // Pixels the user must drag to trigger a slide swipe.
12+
13+
React.useEffect(() => {
14+
/**
15+
* Keep track of which touch even we're following.
16+
*/
17+
function handleTouchStart(e) {
18+
if (touchId.current === null) {
19+
const touch = e.changedTouches[0];
20+
touchId.current = touch.identifier;
21+
startTouchX.current = touch.clientX;
22+
}
23+
}
24+
25+
/**
26+
* Only care about the touch we're tracking.
27+
* See how much the user swiped, if it's more than
28+
* the threshold, navigate to the previous or next slide.
29+
*/
30+
function handleTouchEnd(e) {
31+
const touchList = e.changedTouches;
32+
for (let i = 0; i < touchList.length; i++) {
33+
const touch = touchList[i];
34+
if (touch.identifier === touchId.current) {
35+
touchId.current = null;
36+
const distance = touch.clientX - startTouchX.current;
37+
if (distance > threshold) {
38+
navigateToPrevious();
39+
} else if (distance < -threshold) {
40+
navigateToNext();
41+
}
42+
break;
43+
}
44+
}
45+
}
46+
47+
window.addEventListener('touchstart', handleTouchStart);
48+
window.addEventListener('touchend', handleTouchEnd);
49+
50+
return () => {
51+
window.removeEventListener('touchstart', handleTouchStart);
52+
window.removeEventListener('touchend', handleTouchEnd);
53+
};
54+
}, [navigateToNext, navigateToPrevious]);
55+
};
56+
57+
export default useTouchControls;

0 commit comments

Comments
 (0)