尝试移动图钉和标记时 MapView 地图出现故障——React-native
MapView map glitches when trying to move the pin and marker -- React-native
我正在尝试创建一个 Swiggy/Zomato/FoodPanda 类似的应用程序,我正在尝试获取用户位置或在地图上设置送货位置。
问题发生在 Android。
但是我在移动标记位置时感觉不流畅,尤其是在放大和缩小时。
尝试移动图钉标记位置时出现地图故障
请建议我改进并获得流畅的体验。
我正在尝试很多逻辑,但没有获得任何期望的性能。
这是我实现的代码,
这是我对构造函数的初始设置
constructor(props) {
super(props);
this.latDelta = 0.00922 * 1.5;
this.longDelta = 0.00421 * 1.5;
this.state = {
visible: false,
address: {},
lastLat: 24.8076793,
lastLong: 93.9360916,
mapRegion: new AnimatedRegion({
latitude: 24.8076793,
longitude: 93.9360916,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta
}),
marker: null,
region: new AnimatedRegion({
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
latitude: 24.8076793,
longitude: 93.9360916
}),
autoGeoMarker: {
latitude: 24.8076793,
longitude: 93.9360916,
autoMapAddress: '',
autoMapArea: ''
},
setGeoMarker: {
latitude: 24.8076793,
longitude: 93.9360916,
setMapAddress: '',
setMapArea: ''
},
mapIndicator: false,
mapAddress: '',
mapArea: '',
//-----
indicator: true,
searchModal: false
};
}
componentDidMount() {
this.getPermissionLocation();
}
在此请求许可
getPermissionLocation = () => {
try {
request(
Platform.select({
android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
})
).then(res => {
if (res == 'granted') {
this.setState({
searchModal: false
});
Geolocation.getCurrentPosition(
//Will give you the current location
position => {
let region = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta
};
Alert.alert('', 'Pin Your Delivery point by moving map');
this.setState({
autoGeoMarker: region,
mapIndicator: false,
indicator: false
});
this.onRegionChange(region);
this.getAutoDetectAddress(region.latitude, region.longitude);
},
error => {
//setLocationStatus(error.message);
console.log('error ... 1 ' + error.message);
},
{
enableHighAccuracy: false,
timeout: 30000,
maximumAge: 1000
}
);
} else {
console.log('Location is not enabled');
Alert.alert(
'Enable Your Location:',
'Can not proceed, Please allow your Location permissioin.',
[{ text: 'OK', onPress: () => RNRestart.Restart() }]
);
}
});
} catch (error) {
console.log('location set error:', error);
}
};
//Get Auto Geolocation address
getAutoDetectAddress = (latitude, longitude) => {
Geocoder.from(latitude, longitude)
.then(json => {
let region = {
latitude: latitude,
longitude: longitude,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
autoMapAddress: json.results[0].formatted_address,
autoMapArea: json.results[0].address_components[1].short_name
};
this.setState({
autoGeoMarker: region
});
})
.catch(error => console.warn(error));
//-----------------------
};
onRegionChange = region => {
this.setState({
region: region,
lastLat: region.latitude,
lastLong: region.longitude
});
this.getAddressInfo(region.latitude, region.longitude);
};
getAddressInfo = (latitude, longitude) => {
Geocoder.from(latitude, longitude)
.then(json => {
this.setState({
mapAddress: json.results[0].formatted_address,
mapArea: json.results[0].address_components[1].short_name
});
let region = {
latitude: json.results[0].geometry.location.lat,
longitude: json.results[0].geometry.location.lng,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
setMapAddress: json.results[0].formatted_address,
setMapArea: json.results[0].address_components[1].short_name
};
this.setState({
setGeoMarker: region
});
})
.catch(error => console.warn(error));
};
render() {
return this.state.indicator ? (
<View style={{ flex: 1 }}>
<ActivityIndicator size="large" color="#ff6a00" />
</View>
) : (
<View style={{ flex: 1, flexDirection: 'column' }}>
<StatusBar backgroundColor="#ff6a00" />
<View style={styles.map}>
<MapView
style={styles.map}
region={this.state.region}
onRegionChangeComplete={this.onRegionChange}
/>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
position: 'absolute',
top: '4%',
left: '-3%'
}}
>
<TouchableOpacity
onPress={() => {
{
this.props.navigation.navigate('HomeScreen');
}
}}
>
<Image
style={{ width: 71, height: 51 }}
source={require('../../assets/app/mapback.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.markerFixed}>
<Image style={styles.marker} source={marker} />
</View>
</View>
<View
style={{
flex: 1,
padding: 4,
backgroundColor: '#FFFFFF'
// borderTopColor: 'black',
// borderTopWidth: 1
}}
>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginTop: 15,
marginLeft: 20
}}
>
<View
style={{ flex: 0.8, alignItems: 'center', flexDirection: 'row' }}
>
<Image
style={{ width: 15, height: 20 }}
source={require('../../assets/app/mapmark.png')}
/>
<Text
style={{
fontSize: 18,
marginLeft: 15,
fontFamily: 'Nunito-Black'
}}
>
{this.state.mapArea}
</Text>
</View>
</View>
<Text
style={{
marginTop: 20,
marginLeft: 20,
fontSize: 12,
fontFamily: 'Poppins-Regular'
}}
>
{this.state.mapAddress}
</Text>
</View>
</View>
);
}
这里我有点疑惑这两个功能应该在哪里设置好
this.onRegionChange(region);
this.getAutoDetectAddress(region.latitude, region.longitude);
也许如果这两个功能,但我不确定。在何处正确实施以获得最佳性能。
地图故障或弹跳(pinching/zooming 进出)问题是由使用 region={this.state.region}
引起的
所以,我使用 initialRegion={this.state.region}
而不是 region
这是完整的例子
onChangeValue = region => {
this.setState({
region
});
Geocoder.from(region.latitude, region.longitude)
.then(json => {
this.setState({
mapAddress: json.results[0].formatted_address,
mapArea: json.results[0].address_components[1].short_name
});
let region = {
latitude: json.results[0].geometry.location.lat,
longitude: json.results[0].geometry.location.lng,
latitudeDelta: 0.021,
longitudeDelta: 0.021,
setMapAddress: json.results[0].formatted_address,
setMapArea: json.results[0].address_components[1].short_name
};
this.setState({
setGeoMarker: region
});
// this.map.animateToRegion(region);
})
.catch(error => console.warn(error));
};
...
<MapView
style={{
flex: 1,
height: Dimensions.get('screen').height / 1.5,
position: 'relative',
marginBottom: this.state.marginBottom
}}
showsUserLocation={true}
initialRegion={this.state.region}
// region={this.state.region}
showsMyLocationButton={true}
onRegionChangeComplete={this.onChangeValue}
ref={ref => (this.map = ref)}
/>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
position: 'absolute',
top: '4%',
left: '-3%'
}}
>
<TouchableOpacity
onPress={() => {
{
this.props.navigation.navigate('MainTabScreen');
this.props.navigation.navigate('HomeScreen');
}
}}
>
{/*<Icon.MaterialIcons name="arrow-back" size={28} color="black" />*/}
<Image
style={{ width: 71, height: 51 }}
source={require('../../assets/app/mapback.png')}
/>
</TouchableOpacity>
</View>
...
我正在尝试创建一个 Swiggy/Zomato/FoodPanda 类似的应用程序,我正在尝试获取用户位置或在地图上设置送货位置。
问题发生在 Android。
但是我在移动标记位置时感觉不流畅,尤其是在放大和缩小时。
尝试移动图钉标记位置时出现地图故障
请建议我改进并获得流畅的体验。
我正在尝试很多逻辑,但没有获得任何期望的性能。
这是我实现的代码,
这是我对构造函数的初始设置
constructor(props) {
super(props);
this.latDelta = 0.00922 * 1.5;
this.longDelta = 0.00421 * 1.5;
this.state = {
visible: false,
address: {},
lastLat: 24.8076793,
lastLong: 93.9360916,
mapRegion: new AnimatedRegion({
latitude: 24.8076793,
longitude: 93.9360916,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta
}),
marker: null,
region: new AnimatedRegion({
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
latitude: 24.8076793,
longitude: 93.9360916
}),
autoGeoMarker: {
latitude: 24.8076793,
longitude: 93.9360916,
autoMapAddress: '',
autoMapArea: ''
},
setGeoMarker: {
latitude: 24.8076793,
longitude: 93.9360916,
setMapAddress: '',
setMapArea: ''
},
mapIndicator: false,
mapAddress: '',
mapArea: '',
//-----
indicator: true,
searchModal: false
};
}
componentDidMount() {
this.getPermissionLocation();
}
在此请求许可
getPermissionLocation = () => {
try {
request(
Platform.select({
android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
})
).then(res => {
if (res == 'granted') {
this.setState({
searchModal: false
});
Geolocation.getCurrentPosition(
//Will give you the current location
position => {
let region = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta
};
Alert.alert('', 'Pin Your Delivery point by moving map');
this.setState({
autoGeoMarker: region,
mapIndicator: false,
indicator: false
});
this.onRegionChange(region);
this.getAutoDetectAddress(region.latitude, region.longitude);
},
error => {
//setLocationStatus(error.message);
console.log('error ... 1 ' + error.message);
},
{
enableHighAccuracy: false,
timeout: 30000,
maximumAge: 1000
}
);
} else {
console.log('Location is not enabled');
Alert.alert(
'Enable Your Location:',
'Can not proceed, Please allow your Location permissioin.',
[{ text: 'OK', onPress: () => RNRestart.Restart() }]
);
}
});
} catch (error) {
console.log('location set error:', error);
}
};
//Get Auto Geolocation address
getAutoDetectAddress = (latitude, longitude) => {
Geocoder.from(latitude, longitude)
.then(json => {
let region = {
latitude: latitude,
longitude: longitude,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
autoMapAddress: json.results[0].formatted_address,
autoMapArea: json.results[0].address_components[1].short_name
};
this.setState({
autoGeoMarker: region
});
})
.catch(error => console.warn(error));
//-----------------------
};
onRegionChange = region => {
this.setState({
region: region,
lastLat: region.latitude,
lastLong: region.longitude
});
this.getAddressInfo(region.latitude, region.longitude);
};
getAddressInfo = (latitude, longitude) => {
Geocoder.from(latitude, longitude)
.then(json => {
this.setState({
mapAddress: json.results[0].formatted_address,
mapArea: json.results[0].address_components[1].short_name
});
let region = {
latitude: json.results[0].geometry.location.lat,
longitude: json.results[0].geometry.location.lng,
latitudeDelta: this.latDelta,
longitudeDelta: this.longDelta,
setMapAddress: json.results[0].formatted_address,
setMapArea: json.results[0].address_components[1].short_name
};
this.setState({
setGeoMarker: region
});
})
.catch(error => console.warn(error));
};
render() {
return this.state.indicator ? (
<View style={{ flex: 1 }}>
<ActivityIndicator size="large" color="#ff6a00" />
</View>
) : (
<View style={{ flex: 1, flexDirection: 'column' }}>
<StatusBar backgroundColor="#ff6a00" />
<View style={styles.map}>
<MapView
style={styles.map}
region={this.state.region}
onRegionChangeComplete={this.onRegionChange}
/>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
position: 'absolute',
top: '4%',
left: '-3%'
}}
>
<TouchableOpacity
onPress={() => {
{
this.props.navigation.navigate('HomeScreen');
}
}}
>
<Image
style={{ width: 71, height: 51 }}
source={require('../../assets/app/mapback.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.markerFixed}>
<Image style={styles.marker} source={marker} />
</View>
</View>
<View
style={{
flex: 1,
padding: 4,
backgroundColor: '#FFFFFF'
// borderTopColor: 'black',
// borderTopWidth: 1
}}
>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginTop: 15,
marginLeft: 20
}}
>
<View
style={{ flex: 0.8, alignItems: 'center', flexDirection: 'row' }}
>
<Image
style={{ width: 15, height: 20 }}
source={require('../../assets/app/mapmark.png')}
/>
<Text
style={{
fontSize: 18,
marginLeft: 15,
fontFamily: 'Nunito-Black'
}}
>
{this.state.mapArea}
</Text>
</View>
</View>
<Text
style={{
marginTop: 20,
marginLeft: 20,
fontSize: 12,
fontFamily: 'Poppins-Regular'
}}
>
{this.state.mapAddress}
</Text>
</View>
</View>
);
}
这里我有点疑惑这两个功能应该在哪里设置好
this.onRegionChange(region);
this.getAutoDetectAddress(region.latitude, region.longitude);
也许如果这两个功能,但我不确定。在何处正确实施以获得最佳性能。
地图故障或弹跳(pinching/zooming 进出)问题是由使用 region={this.state.region}
所以,我使用 initialRegion={this.state.region}
而不是 region
这是完整的例子
onChangeValue = region => {
this.setState({
region
});
Geocoder.from(region.latitude, region.longitude)
.then(json => {
this.setState({
mapAddress: json.results[0].formatted_address,
mapArea: json.results[0].address_components[1].short_name
});
let region = {
latitude: json.results[0].geometry.location.lat,
longitude: json.results[0].geometry.location.lng,
latitudeDelta: 0.021,
longitudeDelta: 0.021,
setMapAddress: json.results[0].formatted_address,
setMapArea: json.results[0].address_components[1].short_name
};
this.setState({
setGeoMarker: region
});
// this.map.animateToRegion(region);
})
.catch(error => console.warn(error));
};
...
<MapView
style={{
flex: 1,
height: Dimensions.get('screen').height / 1.5,
position: 'relative',
marginBottom: this.state.marginBottom
}}
showsUserLocation={true}
initialRegion={this.state.region}
// region={this.state.region}
showsMyLocationButton={true}
onRegionChangeComplete={this.onChangeValue}
ref={ref => (this.map = ref)}
/>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
position: 'absolute',
top: '4%',
left: '-3%'
}}
>
<TouchableOpacity
onPress={() => {
{
this.props.navigation.navigate('MainTabScreen');
this.props.navigation.navigate('HomeScreen');
}
}}
>
{/*<Icon.MaterialIcons name="arrow-back" size={28} color="black" />*/}
<Image
style={{ width: 71, height: 51 }}
source={require('../../assets/app/mapback.png')}
/>
</TouchableOpacity>
</View>
...