Skip to content

Instantly share code, notes, and snippets.

@devknoll
Created July 9, 2015 06:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devknoll/19aeab25bc50f0d70820 to your computer and use it in GitHub Desktop.
Save devknoll/19aeab25bc50f0d70820 to your computer and use it in GitHub Desktop.
class Flix extends Component {
constructor(props) {
super(props);
this.state = {
person: People[0],
};
}
_goToNextPerson() {
let currentPersonIdx = People.indexOf(this.state.person);
let newIdx = currentPersonIdx + 1;
this.setState({
person: People[newIdx > People.length - 1 ? 0 : newIdx]
});
}
render() {
return (
<TinderPanner next={this._goToNextPerson.bind(this)}>
{({pan, enter, panResponder}) => {
let [translateX, translateY] = [pan.x, pan.y];
let rotate = pan.x.interpolate({inputRange: [-200, 0, 200], outputRange: ["-30deg", "0deg", "30deg"]});
let opacity = pan.x.interpolate({inputRange: [-200, 0, 200], outputRange: [0.5, 1, 0.5]})
let scale = enter;
let animatedCardStyles = {transform: [{translateX}, {translateY}, {rotate}, {scale}], opacity};
let yupOpacity = pan.x.interpolate({inputRange: [0, 150], outputRange: [0, 1]});
let yupScale = pan.x.interpolate({inputRange: [0, 150], outputRange: [0.5, 1], extrapolate: 'clamp'});
let animatedYupStyles = {transform: [{scale: yupScale}], opacity: yupOpacity}
let nopeOpacity = pan.x.interpolate({inputRange: [-150, 0], outputRange: [1, 0]});
let nopeScale = pan.x.interpolate({inputRange: [-150, 0], outputRange: [1, 0.5], extrapolate: 'clamp'});
let animatedNopeStyles = {transform: [{scale: nopeScale}], opacity: nopeOpacity};
return (
<View style={styles.container}>
<Animated.View style={[styles.card, animatedCardStyles, {backgroundColor: this.state.person}]} {...this._panResponder.panHandlers}>
</Animated.View>
<Animated.View style={[styles.nope, animatedNopeStyles]}>
<Text style={styles.nopeText}>Nope!</Text>
</Animated.View>
<Animated.View style={[styles.yup, animatedYupStyles]}>
<Text style={styles.yupText}>Yup!</Text>
</Animated.View>
</View>
);
}}
</TinderPanner>
);
}
}
class TinderPanner extends Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY(),
enter: new Animated.Value(0.5)
}
}
componentDidMount() {
this._animateEntrance();
}
_animateEntrance() {
Animated.spring(
this.state.enter,
{ toValue: 1, friction: 8 }
).start();
}
componentWillMount() {
this._panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderGrant: (e, gestureState) => {
this.state.pan.setOffset({x: this.state.pan.x._value, y: this.state.pan.y._value});
this.state.pan.setValue({x: 0, y: 0});
},
onPanResponderMove: Animated.event([
null, {dx: this.state.pan.x, dy: this.state.pan.y},
]),
onPanResponderRelease: (e, {vx, vy}) => {
this.state.pan.flattenOffset();
var velocity;
if (vx > 0) {
velocity = clamp(vx, 3, 5);
} else if (vx < 0) {
velocity = clamp(vx * -1, 3, 5) * -1;
}
if (this.state.pan.x._value > 120 || this.state.pan.x._value < -120) {
Animated.decay(this.state.pan.x, {
velocity: velocity,
deceleration: 0.98,
}).start(this._resetState.bind(this))
Animated.decay(this.state.pan.y, {
velocity: vy,
deceleration: 0.985,
}).start();
} else {
Animated.spring(this.state.pan, {
toValue: {x: 0, y: 0},
friction: 4
}).start()
}
}
})
}
_resetState() {
this.state.pan.setValue({x: 0, y: 0});
this.state.enter.setValue(0);
this.props.next();
this._animateEntrance();
}
render() {
let { pan, enter } = this.state;
let panResponder = this._panResponder;
return this.props.children({ pan, enter, panResponder });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment