Skip to content
This repository has been archived by the owner on Feb 12, 2021. It is now read-only.

Commit

Permalink
Swipe working in all directions
Browse files Browse the repository at this point in the history
TODO:
- Add a "with no displacement" option
- Add an option to use distance threshold instead of velocity threshold"
  • Loading branch information
Fernando Via Canel committed Jun 14, 2017
1 parent 585e172 commit 0483a88
Showing 1 changed file with 134 additions and 87 deletions.
221 changes: 134 additions & 87 deletions src/withSwipe.js
Original file line number Diff line number Diff line change
@@ -1,98 +1,145 @@
import React, { Component } from 'react'

const initialState = {
position: {
startX: '',
startY: '',
deltaDistance: 0,
previousDeltaY: 0,
},
time: {
startTime: null,
},
}
export default ({ velocityThreshold }) => {
const handleTouchMove = component => e => {
const { position, style } = component.state

export default ({ velocityThreshold }) => Target =>
class App extends Component {
constructor() {
super()
e.persist()
const changeX = e.touches[0].clientX - position.mouseStartX,
changeY = e.touches[0].clientY - position.mouseStartY
const translateX = position.previousDeltaX + changeX,
translateY = position.previousDeltaY + changeY

this.state = initialState
}
TouchStart(e) {
this.setState({
time: {
...this.state.time,
startTime: new Date().getTime(),
},
position: {
...this.state.position,
mouseStartX: e.touches[0].clientX,
mouseStartY: e.touches[0].clientY,
boxX: e.target.getBoundingClientRect().left,
boxY: e.target.getBoundingClientRect().top,
deltaDistance: 0,
},
})
}
TouchMove(e) {
e.persist()
console.log('touchY', e.touches[0].clientY)
console.log('mouseStartY', this.state.position.mouseStartY)
console.log('boxY', this.state.position.boxY)
console.log('deltaY', e.touches[0].clientY - this.state.position.mouseStartY)
const changeX = e.touches[0].clientX - this.state.position.mouseStartX,
changeY = e.touches[0].clientY - this.state.position.mouseStartY
component.setState({
position: {
...position,
deltaDistanceX: e.touches[0].clientX - position.mouseStartX,
deltaDistanceY: e.touches[0].clientY - position.mouseStartY,
},
style: {
...style,
transform: `translate( ${translateX}px, ${translateY}px)`,
},
})
}

this.setState({
position: {
...this.state.position,
deltaDistance: e.touches[0].clientY - this.state.position.mouseStartY,
},
style: {
...this.state.style,
transform: `translate( ${0}px, ${this.state.position.previousDeltaY + changeY}px)`,
},
})
const maybeTriggerGestures = ({
onSwipeUp,
onSwipeDown,
onSwipeLeft,
onSwipeRight,
velocityX,
velocityY,
}) => {
switch (true) {
case velocityY < -velocityThreshold:
onSwipeUp && onSwipeUp()
break
case velocityY > velocityThreshold:
onSwipeDown && onSwipeDown()
break
case velocityX < -velocityThreshold:
onSwipeLeft && onSwipeLeft()
break
case velocityX > velocityThreshold:
onSwipeRight && onSwipeRight()
break
default:
console.log('INVALID_SWIPE')
}
TouchEnd(e) {
const deltaTime = new Date().getTime() - this.state.time.startTime
const velocity = this.state.position.deltaDistance / deltaTime
this.gestureHandler(velocity)
console.log('new boxY', this.state.position.boxY + this.state.position.deltaDistance)
this.setState({
position: {
...this.state.position,
previousDeltaY: this.state.position.previousDeltaY + this.state.position.deltaDistance,
},
})
}

const initialState = {
position: {
startX: '',
startY: '',
deltaDistanceX: 0,
deltaDistanceY: 0,
previousDeltaX: 0,
previousDeltaY: 0,
},
time: {
startTime: null,
},
}

const getBoxCoordinates = domElement => {
const { left, top } = domElement.getBoundingClientRect()

return {
boxX: left,
boxY: top,
}
}

gestureHandler(velocity) {
const THRESHOLD = velocityThreshold
const handleTouchStart = component => e => {
const { position, time } = component.state

switch (true) {
case velocity < -THRESHOLD:
this.props.onSwipeUp && this.props.onSwipeUp()
break
case velocity > THRESHOLD:
this.props.onSwipeUp && this.props.onSwipeDown()
break
default:
console.log('INVALID_SWIPE')
component.setState({
time: {
...time,
startTime: new Date().getTime(),
},
position: {
...position,
mouseStartX: e.touches[0].clientX,
mouseStartY: e.touches[0].clientY,
deltaDistanceX: 0,
deltaDistanceY: 0,
...(position.boxY == null && getBoxCoordinates(e.target)),
},
})
}

const handleTouchEnd = component => e => {
const { position, time } = component.state
const { onSwipeUp, onSwipeRight, onSwipeDown, onSwipeLeft } = component.props
const deltaTime = new Date().getTime() - time.startTime
const velocityX = position.deltaDistanceX / deltaTime
const velocityY = position.deltaDistanceY / deltaTime
maybeTriggerGestures({
velocityX,
velocityY,
onSwipeUp,
onSwipeDown,
onSwipeLeft,
onSwipeRight,
})
console.log('new boxX', position.boxX + position.deltaDistanceX)
console.log('new boxY', position.boxY + position.deltaDistanceY)
component.setState({
position: {
...position,
previousDeltaX: position.previousDeltaX + position.deltaDistanceX,
previousDeltaY: position.previousDeltaY + position.deltaDistanceY,
},
})
}

return Target =>
class App extends Component {
constructor() {
super()

this.state = initialState

this.handleTouchStart = handleTouchStart(this)
this.handleTouchMove = handleTouchMove(this)
this.handleTouchEnd = handleTouchEnd(this)
}

render() {
const { onSwipeUp, onSwipeDown, ...props } = this.props
return (
<div
style={this.state.style}
onTouchStart={this.handleTouchStart}
onTouchEnd={this.handleTouchEnd}
onTouchMove={this.handleTouchMove}
>
<Target {...props} />
</div>
)
}
}
render() {
const { onSwipeUp, onSwipeDown, ...props } = this.props
return (
<div
style={this.state.style}
onTouchStart={e => this.TouchStart(e)}
onTouchEnd={e => this.TouchEnd(e)}
onTouchMove={e => this.TouchMove(e)}
>
<Target {...props} />
</div>
)
}
}
}

0 comments on commit 0483a88

Please sign in to comment.