Mehmet Özden
Mehmet Özden

Reputation: 87

React-Native-Maps | Display Markers inside a Circle / inside my Radius?

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

Answers (2)

VRDemon
VRDemon

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

Andrew
Andrew

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

Related Questions