Skip to content

Instantly share code, notes, and snippets.

@seveves
Last active August 5, 2019 18:22
Show Gist options
  • Save seveves/fd42b65fe3a6dfcbe5ca8e6402df9a90 to your computer and use it in GitHub Desktop.
Save seveves/fd42b65fe3a6dfcbe5ca8e6402df9a90 to your computer and use it in GitHub Desktop.
Preact swipe recognizer
import { Component, h, cloneElement } from 'preact';
export default class SwipeRecognizer extends Component {
tolerance = 100;
gesture = { x: [], y: [], match: '' };
componentDidMount() {
this.base.addEventListener('touchstart', this.capture);
this.base.addEventListener('touchmove', this.capture);
this.base.addEventListener('touchend', this.compute)
}
componentWillUnmount() {
this.base.removeEventListener('touchstart', this.capture);
this.base.removeEventListener('touchmove', this.capture);
this.base.removeEventListener('touchend', this.compute);
}
capture = (event) => {
event.preventDefault()
this.gesture.x.push(event.touches[0].clientX)
this.gesture.y.push(event.touches[0].clientY)
};
compute = (event) => {
let xStart = this.gesture.x[0];
let yStart = this.gesture.y[0];
let xEnd = this.gesture.x.pop();
let yEnd = this.gesture.y.pop();
let xTravel = xEnd - xStart;
let yTravel = yEnd - yStart;
if (xTravel < this.tolerance &&
xTravel >= this.tolerance &&
yTravel <= this.tolerance) {
this.gesture.match = 'up';
}
if (xTravel < this.tolerance &&
xTravel >= this.tolerance &&
yTravel > this.tolerance) {
this.gesture.match = 'down'
}
if (yTravel < this.tolerance &&
yTravel >= this.tolerance &&
xTravel <= this.tolerance) {
this.gesture.match = 'left'
}
if (yTravel < this.tolerance &&
yTravel >= this.tolerance &&
xTravel > this.tolerance) {
this.gesture.match = 'right'
}
if (this.gesture.match !== ''){
this.onSwipe(this.gesture.match);
}
this.gesture.x = []
this.gesture.y = []
this.gesture.match = '';
};
onSwipe = (direction) => {
if (this.props.onSwipe) {
this.props.onSwipe(direction);
}
this.setState({ swipe: direction });
};
render({ children }, state) {
return cloneElement(children[0], state);
}
}
import { Component, h, cloneElement } from 'preact';
export default class SwipeRecognizer extends Component<{ onSwipe?: (direction: string) => string },{ swipe: string }> {
private tolerance = 100;
private gesture = { x: [], y: [], match: '' };
private componentDidMount() {
this.base.addEventListener('touchstart', this.capture);
this.base.addEventListener('touchmove', this.capture);
this.base.addEventListener('touchend', this.compute)
}
private componentWillUnmount() {
this.base.removeEventListener('touchstart', this.capture);
this.base.removeEventListener('touchmove', this.capture);
this.base.removeEventListener('touchend', this.compute);
}
private capture = (event: TouchEvent) => {
event.preventDefault()
this.gesture.x.push(event.touches[0].clientX)
this.gesture.y.push(event.touches[0].clientY)
};
private compute = (event: TouchEvent) => {
let xStart = this.gesture.x[0];
let yStart = this.gesture.y[0];
let xEnd = this.gesture.x.pop();
let yEnd = this.gesture.y.pop();
let xTravel = xEnd - xStart;
let yTravel = yEnd - yStart;
if (xTravel < this.tolerance &&
xTravel >= this.tolerance &&
yTravel <= this.tolerance) {
this.gesture.match = 'up';
}
if (xTravel < this.tolerance &&
xTravel >= this.tolerance &&
yTravel > this.tolerance) {
this.gesture.match = 'down'
}
if (yTravel < this.tolerance &&
yTravel >= this.tolerance &&
xTravel <= this.tolerance) {
this.gesture.match = 'left'
}
if (yTravel < this.tolerance &&
yTravel >= this.tolerance &&
xTravel > this.tolerance) {
this.gesture.match = 'right'
}
if (this.gesture.match !== ''){
this.onSwipe(this.gesture.match);
}
this.gesture.x = []
this.gesture.y = []
this.gesture.match = '';
};
onSwipe = (direction: string) => {
if (this.props.onSwipe) {
this.props.onSwipe(direction);
}
this.setState({ swipe: direction });
};
render({ children }, state) {
return cloneElement(children[0], state);
}
}
@talvasconcelos
Copy link

Hi man, ty for this Recognizer but, can i have this in .js format? I tried to "transform" it but i don't know how Typescript really works.

Thanks. I'll try to do it in JS from "scratch" to see if i can do it...

@seveves
Copy link
Author

seveves commented Nov 9, 2017

Just let me know if the jsx version is fine for you @talvasconcelos

@RyuSLunK
Copy link

Works great, but I had to modify the gesture recognition logic to get it to work.

if (Math.abs(xTravel) < this.tolerance && yTravel > this.tolerance) {
      this.gesture.match = "down";
    } else if (
      yTravel < this.tolerance &&
      Math.abs(xTravel) < this.tolerance &&
      Math.abs(yTravel) > this.tolerance
    ) {
      this.gesture.match = "up";
    } else if (
      xTravel < this.tolerance &&
      Math.abs(xTravel) > this.tolerance &&
      Math.abs(yTravel) < this.tolerance
    ) {
      this.gesture.match = "left";
    } else if (xTravel > this.tolerance && Math.abs(yTravel) < this.tolerance) {
      this.gesture.match = "right";
    }
    if (this.gesture.match !== "") {
      this.onSwipe(this.gesture.match);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment