Reputation: 87
i have problem with Maps & Markers.
I'm loading the markers from a GeoJson file. I only want to display the markers which are inside my current Position like 500m radius (In the Circle). Is this Possible? I dont want to load all the 700 markers bc of the performance. I hope you guys can help me.
This is my code
import React from 'react';
import MapView from 'react-native-maps';
import Marker from 'react-native-maps';
import {
View,
Text,
StyleSheet,
Button,
} from "react-native";
class Spielplaetze extends React.Component {
constructor() {
super();
this.state = {
markers: [],
loaded: false
}
}
componentDidMount() {
this.getLocations();
this.getPosition();
}
getPosition(){
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position);
this.setState({
region: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.020,
longitudeDelta: 0.020,
}
});
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 },
);
}
getLocations(){
return fetch('http://media-panda.de/cologne.geojson')
.then(response => response.json())
.then(responseData =>{
var markers = [];
for (var i = 0; i < responseData.features.length; i++) {
if (responseData.features[i].properties.Torwand != '<Null>'){
var coords = responseData.features[i].geometry.coordinates;
var marker = {
coordinate: {
latitude: coords[1],
longitude: coords[0],
}
}
markers.push(marker);
}
}
this.setState({
markers: markers,
loaded: true,
});
}
).done();
}
render() {
return (
<View style={styles.container}>
<MapView.Animated
style={styles.map}
region={this.state.region}
showsUserLocation={true}
>
{this.state.markers.map(marker => (
<MapView.Marker
coordinate={marker.coordinate}
/>
))}
</MapView.Animated>
</View>
);
}
}
export default Spielplaetze;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
},
map: {
width: "100%",
height: "100%",
},
})
Upvotes: 2
Views: 4792
Reputation: 1
I had the same issue and this question helped me a lot. One thing to note though: there is a typo in the answer.
The code should be:
coordinate: {
latitude: coords.latitude,
longitude: coords.longitude,
}
And not:
coordinate: {
latitude: coords[1],
longitude: coords[0],
}
I hope that this will help others as well.
Upvotes: 0
Reputation: 28539
There is a great dependency called geolib
that allows you to perform calculations such as distances between coordinates.
You can install it will npm i geolib
. Using the .getDistance
function that it provides you could filter the markers based on how far they are from your "center" point.
const geolib = require('geolib');
...
getLocations() {
let { region } = this.state;
let { latitude, longitude } = region;
fetch('http://media-panda.de/cologne.geojson')
.then(response => response.json())
.then(responseData => {
let markers = responseData.features.map(feature => {
let coords = feature.geometry.coordinates
return {
coordinate: {
latitude: coords[1],
longitude: coords[0],
}
}
}).filter(marker => {
let distance = this.calculateDistance(latitude, longitude, marker.coordinate.latitude, marker.coordinate.longitude);
return distance <= 500;
});
this.setState({
markers: markers,
loaded: true,
});
}).done(); // should probably have a catch on here otherwise you've got no way to handle your errors
}
// this function uses geolib to calculate the distance between the points
calculateDistance(origLat, origLon, markerLat, markerLon) {
return geolib.getDistance(
{latitude: origLat, longitude: origLon},
{latitude: markerLat, longitude: markerLon}
);
}
Basically what I am doing is mapping over the markers that are returned by your fetch
request and turning them each into the following object
{ coordinate: { latitude: number, longitude: number } }
Then I am filtering them, using geolib
to remove any that are further than 500m away from the center point.
Though one thing you should note is that in your current code setup you could get the GeoJson before you get the coordinates of the user's location. You may want to consider refactoring your getLocations
and getPosition
functions so that the getLocations
will only run after the getPosition
function has returned the region. Otherwise you won't be able to filter because the state value for region
will not exist.
You may wish to call getLocations
after you have gotten the region from getPosition
, perhaps something like this, using the callback property of setState
. That way the region will be in the state and you should be able to filter without any issues.
getPosition(){
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position);
this.setState({
region: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.020,
longitudeDelta: 0.020,
}
}, () => this.getLocations());
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 },
);
}
This is by no means the only way to do this. It really depends on your use case, but it should give you enough of an idea of what to do.
Upvotes: 3