I have one draggable car image if i dragging the car first time it works fine after second time re dragging the car image return back to the initial position. I want to drag an image smooth and draggable with finger touch. please help me
import React, { Component } from 'react'; import { StyleSheet, View, Text, PanResponder, Animated, Easing, Dimensions, Image, Button } from 'react-native'; import { ToastAndroid } from 'react-native';
export default class Viewport extends Component {
constructor(props) {
super(props);
this.state = {
disableCar: false,
dropZoneCar: null,
panCar: new Animated.ValueXY(),
};
this.carFunction();
}
carFunction = () => {
this.panResponderCar = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: Animated.event([null, {
dx: this.state.panCar.x,
dy: this.state.panCar.y
}]),
onPanResponderGrant: (evt, gestureState) => {
console.log(evt)
},
onPanResponderRelease: (e, gesture) => {
// console.log(e)
if (this.isDropZoneCar(gesture)) {
ToastAndroid.show('Correct', ToastAndroid.SHORT);
} else {
ToastAndroid.show('Wrong', ToastAndroid.SHORT);
}
}
});
}
isDropZoneCar(gesture) {
var dz = this.state.dropZoneCar;
return gesture.moveY > dz.y && gesture.moveY < dz.y + dz.height;
}
setDropZoneCar(event) {
this.setState({
dropZoneCar: event.nativeEvent.layout
});
}
setDropZoneBike(event) {
this.setState({
dropZoneBike: event.nativeEvent.layout
});
}
render() {
return (
<View style={styles.mainContainer}>
<View style={{ flexDirection: 'row', }}>
<View style={{ flex: 1 }}>
<View
onLayout={this.setDropZoneCar.bind(this)}
style={[styles.dropZone, { backgroundColor: this.state.disableCar ? 'green' : '#2c3e50' }]}>
<Text style={styles.text}>Drop a Car</Text>
</View>
<View
onLayout={this.setDropZoneBike.bind(this)}
style={[styles.dropZone, { backgroundColor: this.state.disableCar ? 'green' : '#2c3e50' }]}>
<Text style={styles.text}>Drop a Bike</Text>
</View>
</View>
<View style={{ flex: 1 }}>
{this.draggableCar()}
</View>
</View>
</View>
);
}
draggableCar() {
return (
<View style={styles.draggableContainer} >
<Animated.View
{...this.panResponderCar.panHandlers}
style={[this.state.panCar.getLayout()]}>
<Image
style={{ position: "absolute", width: 200, height: 100, right: 10, top: 300, }}
source={require('./assets/carr.png')}
/>
</Animated.View>
</View>
);
}
}
let CIRCLE_RADIUS = 36;
let Window = Dimensions.get('window');
let styles = StyleSheet.create({
mainContainer: {
flex: 1
},
dropZone: {
height: 100,
backgroundColor: '#2c3e50',
marginTop: 100
},
text: {
marginTop: 25,
marginLeft: 5,
marginRight: 5,
textAlign: 'center',
color: '#fff'
},
draggableContainer: {
position: 'absolute',
top: Window.height / 2 - CIRCLE_RADIUS,
left: Window.width / 2 - CIRCLE_RADIUS,
},
});
You are listening to the delta of the finger movement dx
and dy
, so whenever you touch again, your pan values drop to 0
's. You should set an offset on your pan values every time you touch to fix this. Add this piece of code:
onPanResponderGrant: (e, gestureState) => {
this.state.panCar.setOffset({x: this.state.panCar.x._value, y: this.state.panCar.y._value});
this.state.panCar.setValue({x: 0, y: 0});
}
This will set the offset for your pan to current position, so it doesn't jump back after consequent touches. Hope this helps.