markersArr - an array of objects containing the title, latitude, and longitude:
Array [
Object {
"latitude": 31.74972996282075,
"longitude": 35.23612361202195,
"title": "ארמון הנציב",
},
Object {
"latitude": 31.779044392761453,
"longitude": 35.18955094821394,
"title": "בית הכרם",
},
Object {
"latitude": 31.765429951578884,
"longitude": 35.231964301905144,
"title": "אבו תור",
},
Object {
"latitude": 31.748258119122376,
"longitude": 35.21971512763567,
"title": "ארנונה",
},
]
The hardcoded Marker shows but the other doesn't and I can't figure out why.
The data in the array is correct.
This is the return statement:
return (
<SafeAreaView style={globalStyles.mapScreenContainer}>
<MapView
style={globalStyles.map}
region={mapRegion}
provider={null}
onMarkerPress={(e) => handleMarkerPressed(e)}
>
<Marker
coordinate={{ latitude: 31.7851951925, longitude: 35.2060641757 }}
pinColor={"purple"}
title={"מרכז מאי"}
description={"מיקום העמותה"}
onPress={() => {
console.log("");
}}
/>
{markersArr.map((marker) => {
console.log(marker);
<Marker
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
pinColor={"purple"}
title={marker.title}
onPress={() => {
handleMarkerPressed();
}}
/>;
})}
</MapView>
</SafeAreaView>
);
and the whole component if necessary:
import React, { useState, useEffect, Component } from "react";
import MapView, { Marker } from "react-native-maps";
import { SafeAreaView } from "react-native-safe-area-context";
import { globalStyles } from "../../styles/global";
import { useData } from "../../AuthProvider/UserDataProvider";
const MapScreen = () => {
const { markers, getMarkers } = useData();
const [markersArr, setMarkersArr] = useState([]);
const [mapRegion, setmapRegion] = useState({
latitude: 31.7851951925,
longitude: 35.2060641757,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
});
const handleMarkerPressed = (event) => {
// console.log(event.nativeEvent);
};
useEffect(() => {
getMarkers().then(() => {
for (const marker in markers) {
if (markers.hasOwnProperty.call(markers, marker)) {
setMarkersArr((prev) => [
...prev,
{
title: marker,
latitude: markers[marker].latitude,
longitude: markers[marker].longitude,
},
]);
}
}
});
return () => {};
}, []);
return (
<SafeAreaView style={globalStyles.mapScreenContainer}>
<MapView
style={globalStyles.map}
region={mapRegion}
provider={null}
onMarkerPress={(e) => handleMarkerPressed(e)}
>
<Marker
coordinate={{ latitude: 31.7851951925, longitude: 35.2060641757 }}
pinColor={"purple"}
title={"מרכז מאי"}
description={"מיקום העמותה"}
onPress={() => {
console.log("");
}}
/>
{markersArr.map((marker) => {
console.log(marker);
<Marker
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
pinColor={"purple"}
title={marker.title}
onPress={() => {
handleMarkerPressed();
}}
/>;
})}
</MapView>
</SafeAreaView>
);
};
export default MapScreen;
I get no errors when rendering the map
I've forgotten the return inside the map, added it and now it's working
Related
I am doing a RN project using Geolocation to get the current location, but I don't know what's wrong in this.
Here is my code:
import React, { Component } from 'react';
// Import required component
import { SafeAreaView, StyleSheet, Text, Alert, TouchableOpacity, Image, View } from 'react-native';
import { request, PERMISSIONS } from 'react-native-permissions';
// Import vector icons
import Icon from 'react-native-vector-icons/FontAwesome';
import MapView, { PROVIDER_GOOGLE, Platform, Marker, Callout, Circle } from 'react-native-maps';
import coordinate from '../../api/binLocationData';
import Geolocation from '#react-native-community/geolocation';
export class Home extends Component {
componentDidMount() {
this.requestLocationPermission();
}
requestLocationPermission = async () => {
if (Platform.OS === 'IOS') {
var response = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);
console.log('IOS: ' + response);
if (response === 'granted') {
this.locateCurrentPosition();
}
} else {
var response = await request(PERMISSIONS.ANDROID.LOCATION_WHEN_IN_USE);
console.log('Android: ' + response);
if (response === 'granted') {
this.locateCurrentPosition();
}
}
};
locateCurrentPosition = () => {
Geolocation.getCurrentPosition(
(position) => {
console.log(JSON.stringify(position));
let initialPosition = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
};
this.setState({ initialPosition });
},
(error) => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 1000, maximumAge: 1000 },
);
};
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
ref={(map) => (this._map = map)}
showsUserLocation={true}
style={styles.maps}
initialRegion={this.state.initialPosition}
// initialRegion={{
// latitude: 16.0599,
// longitude: 108.2438,
// latitudeDelta: 0.05,
// longitudeDelta: 0.05,
// }}
>
<Circle
radius={1000}
center={{ latitude: 16.0599, longitude: 108.2438 }}
fillColor={'rgba(51,150,152,0.3)'}
/>
<Marker coordinate={{ latitude: 16.0599, longitude: 108.2438 }}>
<Callout>
<Text>Bin 1</Text>
</Callout>
{/* <Image source={require('./src/assets/icons/bin.png')} /> */}
</Marker>
{coordinate.map((marker) => (
<Marker
key={marker.id}
coordinate={{ latitude: marker.latitude, longitude: marker.longitude }}
title={marker.name}
/>
))}
</MapView>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
maps: {
...StyleSheet.absoluteFillObject,
},
});
export default Home;
And the debugging show:
TypeError: null is not an object (evaluating 'this.state.initialPosition')
How can I fix it?
You forget to initialise state. You should add this to your class component:
constructor(props) {
this.state = {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0,
};
}
This should works:
import React, { Component } from "react";
// Import required component
import {
SafeAreaView,
StyleSheet,
Text,
Alert,
TouchableOpacity,
Image,
View,
} from "react-native";
import { request, PERMISSIONS } from "react-native-permissions";
// Import vector icons
import Icon from "react-native-vector-icons/FontAwesome";
import MapView, {
PROVIDER_GOOGLE,
Platform,
Marker,
Callout,
Circle,
} from "react-native-maps";
import coordinate from "../../api/binLocationData";
import Geolocation from "#react-native-community/geolocation";
export class Home extends Component {
constructor(props) {
this.state = {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0,
};
}
componentDidMount() {
this.requestLocationPermission();
}
requestLocationPermission = async () => {
if (Platform.OS === "IOS") {
var response = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);
console.log("IOS: " + response);
if (response === "granted") {
this.locateCurrentPosition();
}
} else {
var response = await request(PERMISSIONS.ANDROID.LOCATION_WHEN_IN_USE);
console.log("Android: " + response);
if (response === "granted") {
this.locateCurrentPosition();
}
}
};
locateCurrentPosition = () => {
Geolocation.getCurrentPosition(
(position) => {
console.log(JSON.stringify(position));
let initialPosition = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
};
this.setState({
latitude: initialPosition.latitude,
longitude: initialPosition.longitude,
latitudeDelta: initialPosition.latitudeDelta,
longitudeDelta: initialPosition.longitudeDelta,
});
},
(error) => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 1000, maximumAge: 1000 }
);
};
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapView
provider={PROVIDER_GOOGLE}
ref={(map) => (this._map = map)}
showsUserLocation={true}
style={styles.maps}
initialRegion={this.state.initialPosition}
// initialRegion={{
// latitude: 16.0599,
// longitude: 108.2438,
// latitudeDelta: 0.05,
// longitudeDelta: 0.05,
// }}
>
<Circle
radius={1000}
center={{ latitude: 16.0599, longitude: 108.2438 }}
fillColor={"rgba(51,150,152,0.3)"}
/>
<Marker coordinate={{ latitude: 16.0599, longitude: 108.2438 }}>
<Callout>
<Text>Bin 1</Text>
</Callout>
{/* <Image source={require('./src/assets/icons/bin.png')} /> */}
</Marker>
{coordinate.map((marker) => (
<Marker
key={marker.id}
coordinate={{
latitude: marker.latitude,
longitude: marker.longitude,
}}
title={marker.name}
/>
))}
</MapView>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
maps: {
...StyleSheet.absoluteFillObject,
},
});
export default Home;
Unable to drag the map around, after using google auto complete to search for the location. The map is able to change to the location. However I am unable to drag the map around, its stuck to the center of the location that I searched.
MapContainer.js is used to render the map and componentdidmount is used to retrieve the coordinates of busstops which will be displayed as markers under the render below
import { View } from "react-native";
import MapInput from "./MapInput";
import { getLocation, geocodeLocationByName } from "./location-service";
import React, { Component } from "react";
import MapView, { Marker, StyleSheet } from "react-native-maps";
const MyMapView = (props) => {
return (
<MapView
style={{ flex: 1 }}
region={props.region}
showsUserLocation={true}
onRegionChange={(reg) => props.onRegionChange(reg)}
>
{props.busstopArray.map((item) => {
return (
<Marker
key={item.bus_stop_id}
coordinate={{
latitude: Number(item.latitude),
longitude: Number(item.longitude),
}}
title={item.name}
></Marker>
);
})}
</MapView>
);
};
class MapContainer extends React.Component {
state = {
region: {},
busstop: [], //busstop is an empty array, in which the JSON values will be added, to be used later in the code.
};
componentDidMount() {
this.getInitialState();
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ route_id: "1" }, { route_id: "2" }),
};
fetch(
"https://laravelsyd-fypfinalver.herokuapp.com/getBusStop",
requestOptions
)
.then((response) => response.json())
.then((data) => {
this.setState({ busstop: data });
});
}
getInitialState() {
getLocation().then((data) => {
//import locationservice
console.log(data); //prints out intial region coords
this.setState({
region: {
latitude: data.latitude,
longitude: data.longitude,
latitudeDelta: 0.003,
longitudeDelta: 0.003,
},
});
});
}
getCoordsFromName(loc) {
this.setState({
region: {
latitude: loc.lat,
longitude: loc.lng,
latitudeDelta: 0.003,
longitudeDelta: 0.003,
},
});
}
onMapRegionChange(region) {
this.setState({ region });
}
render() {
const bus_stop = [...this.state.busstop];
// console.log(bus_stop); //testing to see if can display the json objects and it can
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<MapInput notifyChange={(loc) => this.getCoordsFromName(loc)} />
</View>
{this.state.region["latitude"] ? (
<View style={{ flex: 1 }}>
<MyMapView
region={this.state.region}
onRegionChange={(reg) => this.onMapRegionChange(reg)}
busstopArray={bus_stop}
/>
</View>
) : null}
</View>
);
}
}
export default MapContainer;
you have to add draggable in Marker:
<Marker
draggable
coordinate={{
latitude: Number(this.state.location.latitude),
longitude: Number(this.state.location.longitude),
}}
onDragEnd={e =>
this.setState({location: e.nativeEvent.coordinate})
}
/>
I created the map using react-native-maps.Now i need to get latitude & longitude as a text when click on map.
I tried this way but it gives an error"Can't find variable:coordinate".
export default class Location extends Component {
constructor(props) {
super(props);
this.state = {
markers: []
};
this.handlePress = this.handlePress.bind(this);
}
handlePress(e) {
this.setState({
markers: [
...this.state.markers,
{
coordinate: e.nativeEvent.coordinate,
key: coordinate,
color: randomColor()
}
]
});
console.log(e.nativeEvent);
}
render() {
return (
<MapView
style={styles.map}
initialRegion={{
latitude: 7.8731,
longitude: 80.7718,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421
}}
onPress={e => this.handlePress(e)}
>
{this.state.markers.map(marker => (
<Marker
key={marker.key}
coordinate={marker.coordinate}
pinColor={marker.color}
>
<View style={styles.marker}>
<Text style={styles.text}>{marker.coordinate}</Text>
</View>
</Marker>
))}
</MapView>
);
}
}
How i fix it?
I solved it.
export default class Location extends Component {
constructor(props) {
super(props);
this.state = {
region: {
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
},
markers: {
coordinate: {
latitude: 4,
longitude: 4,
},
key: id,
color: randomColor(),
}
};
}
onMapPress(e) {
this.setState({
markers:
{
coordinate: e.nativeEvent.coordinate,
key: id++,
color: randomColor(),
},
});
SaveAddress=()=>{
console.log(JSON.stringify(this.state.markers[0].coordinate.latitude))
}
}
render() {
return (
<MapView
provider={this.props.provider}
style={styles.map}
initialRegion={this.state.region}
onPress={e => this.onMapPress(e)}
>
<Marker
key={this.state.markers.key}
coordinate={this.state.markers.coordinate}
pinColor={this.state.markers.color}
>
<View style={styles.marker}>
<Text style={styles.text}>
{JSON.stringify(this.state.markers.coordinate)}</Text>
</View>
</Marker>
</MapView>
);
}
}
Add an onPress event to the map. like below. It will return the coordinates of pressed location in the map.
onPress={ (event) => console.log(event.nativeEvent.coordinate) }
So the code will be,
<MapView style = {styles.map}
initialRegion = {{
latitude: 7.8731,
longitude: 80.7718,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421, }}
onPress={ (event) => console.log(event.nativeEvent.coordinate) }
/>
I use DefaultMarkers to get location from user.
I have a button and a function. In the function I use a code to show latitude in console. Now When I press the button, in console not happening but for second press I can see latitude in console.
If I change location and try again, I should press button for twice to see latitude in console.
constructor(props){
super(props);
this.state={
markers: [],
}
}
onMapPress(e) {
this.setState({
markers: [
{
coordinate: e.nativeEvent.coordinate,
key: 0,
},
],
});
}
SaveAddress=()=>{
console.log(JSON.stringify(this.state.markers[0].coordinate.latitude);
}
<Button onPress={this.SaveAddress}>
<Text>Save</Text>
</Button>
<MapView
style={styles.map}
initialRegion={{
latitude: 28.95761453,
longitude: 50.83710976,
latitudeDelta: 0.0040,
longitudeDelta: 0.0040,
}}
provider={this.props.provider}
onPress={(e) => this.onMapPress(e)}
>
{this.state.markers.map(marker => (
<Marker
key={marker.key}
coordinate={marker.coordinate}
/>
))}
</MapView>
Because, when you first-time press that button to execute this function
SaveAddress=()=>{console.log(JSON.stringify(this.state.markers[0].coordinate.latitude);}
The state is empty so you don't get any value. On your first press, it just starts to save the state and start to render. But on your second press, rendering is complete and the states became set then you got the value.
You can do instead
import React, { Component } from 'react';
import { View, Text, TouchableOpacity, WebView, StyleSheet,KeyboardAvoidingView, ActivityIndicator,Platform,TextInput,Dimensions} from 'react-native'
import MapView, { PROVIDER_GOOGLE, Region,Marker } from 'react-native-maps';
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
markers: [
{
coordinate: { latitude: 28.95761453,
longitude: 50.83710976,
},
key: 0,
},
],
}
}
onMapPress(e) {
this.setState({
markers: [
{
coordinate: e.nativeEvent.coordinate,
key: 0,
},
],
});
}
SaveAddress=()=>{
console.log(JSON.stringify(this.state.markers[0].coordinate.latitude))
}
render() {
return (
<View style={{flex:1}}>
<MapView
style={[styles.map]}
initialRegion={{
latitude: 28.95761453,
longitude: 50.83710976,
latitudeDelta: 0.0040,
longitudeDelta: 0.0040,
}}
// onMapReady={this.onMapReady}
provider={ PROVIDER_GOOGLE}
onPress={(e) => this.onMapPress(e)}
>
{this.state.markers.map(marker => (
<Marker
key={marker.key}
coordinate={marker.coordinate}
/>
))}
</MapView>
<TouchableOpacity onPress={()=>this.SaveAddress()}>
<Text>Save</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
map: {
...StyleSheet.absoluteFillObject,
},
});
I'm trying to limit how much a user can pan when using Mapview from React Native Maps. There is no reason for the user to pan outside of the city and, I believe that the more the use pans outside of the city - the more of my daily request allotment would be used.
I've tried using the Mapview method, setMapBoundaries() but, that doesn't seem to work. Does anyone know how I can control this?
export class MapOfHalifax extends React.Component {
constructor(args) {
super(args);
this.state = {
markers: this.props.markers,
latitude: null,
longitude: null,
error: null,
}
}
componentDidMount() {
this.map.setMapBoundaries(
northEast = {
latitude: 44.722476,
longitude: -63.554658,
},southWest = {
latitude: 44.600546,
longitude: -63.613286,
}
)
}
componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchId);
navigator.geolocation.stopObserving();
}
toggleSelect(id) {
this.props.toggleMarkerState(id)
}
checkDistanceFromSignificantLocation(currentPosition) {
this.state.markers.map((marker, index) => {
const START = {
latitude: currentPosition.coords.latitude,
longitude: currentPosition.coords.longitude
}
const END = {
latitude: marker.latitude,
longitude: marker.longitude
}
if (haversine(START, END, { threshold: MAX_DISTANCE_FROM_LOCATION, unit: PREFERED_DISTANCE_UNIT })
&& (!this.props.markers[index].locationPassedBy)){
this.props.updatePassedByTime(index, moment.utc())
NotificationsAndroid.localNotification({
title: "Approaching:",
body: marker.name + "!"
});
} else if (haversine(START, END, { threshold: MAX_DISTANCE_FROM_LOCATION, unit: PREFERED_DISTANCE_UNIT })
&& (moment().diff(this.props.markers[index].locationPassedBy,'minutes') > 60)){
NotificationsAndroid.localNotification({
title: "Approaching:",
body: marker.name + "!"
});
}
});
}
render() {
return (
<View style={styles.container}>
<MapView
ref={ref => { this.map = ref; }}
showsUserLocation={true}
showsMyLocationButton={true}
style={styles.map}
initialRegion={{
latitude: LATITUDE,
longitude: LONGITUDE,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
}}>
{this.props.markers.map((marker, index) => {
return (<MapView.Marker
coordinate={{
latitude: parseFloat(marker.latitude),
longitude: parseFloat(marker.longitude)
}}
title={marker.name}
key={marker.id}
onPress={() => {
const marker = this.state.markers[index]
marker.mapMarkerIsSelected = !marker.mapMarkerIsSelected
this.setState({
markers: [
...this.state.markers.slice(0, index),
marker,
...this.state.markers.slice(index + 1)
]
})
this.props.toggleMarkerState(marker.id)
}}
pinColor={
marker.mapMarkerIsSelected ? '#3590ea' : '#f06f77'
}>
</MapView.Marker>)
})}
</MapView>
</View>
);
}
}