initialCenter={{
lat: lat,
lng: lng
}}
onClick={this.onMapClicked}
zoom={zoom}>
{this.state.marker.map((data, index) => {
return (
<Marker
ref={this.onMarkerMounted}
key={index}
onClick={this.onMarkerClick}
name={data.name}
phone={data.phone}
icon={{
url: data.icon,
anchor: new this.props.google.maps.Point(20, 20),
scaledSize: new this.props.google.maps.Size(80, 80)
}}
position={{"lat": data.lat, "lng": data.lng}}/>
)
}
)}
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}
onClose={this.onClose}
>
<View style={{width: 100, height: 20}}>
<Text style={{
fontWeight: '600',
fontSize: 14,
color: "#54AD58"
}}>{this.state.selectedPlace.phone}</Text>
</View>
</InfoWindow>
</Map>
In React google maps, the Marker Touch event not working in mobile view. Same function works well on Desktop View. But when i call this function for mobileview it does not works properly.
If i changed the function called this.onMarkerClick() this should call the fuction when i touch the map but this will not working properly. onMapclicked event working in mobile view and desktop view. i don't know what's the problem..
Related
I have the below JS code
A map renders just fine and when clicking the 1st click on the map, it creates and pins a marker on the place it was clicked. The 2nd time I click, it creates a 2nd marker and pins to the position that was clicked. Great!
However, when clicking the 3rd time, it doesn't create another marker! It instead moves the 2nd marker to the position of the 3rd click! Why is it doing that? It's supposed to create a 3rd marker, but for some reason, it moves the 2nd marker to a new position which should not be the case.
The marker is inside the tags too <Marker key={i} position={latLng} so it should work properly...
It seems that {props.isMarkerShown && <Marker position={props.markerPosition} />} is not creating a new instance for the marker after the 2nd marker is created for some reason...
import React from 'react';
import { compose, withStateHandlers } from "recompose";
import { InfoWindow, withGoogleMap, withScriptjs, GoogleMap, Marker } from 'react-google-maps';
const Map = compose(
withStateHandlers(() => ({
isMarkerShown: false,
markerPosition: null
}), {
onMapClick: ({ isMarkerShown }) => (e) => ({
markerPosition: e.latLng,
isMarkerShown:true
})
}),
withScriptjs,
withGoogleMap
)
(props =>
<GoogleMap
defaultZoom={8}
defaultCenter={{ lat: -34.397, lng: 150.644 }}
onClick={props.onMapClick}
>
{props.isMarkerShown && <Marker position={props.markerPosition} />}
</GoogleMap>
)
export default class MapContainer extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div style={{ height: '100%' }}>
<Map
googleMapURL="https://maps.googleapis.com/maps/api/js?key=VALIDAPIKEY"
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
{clicks.map((latLng, i) => (
<Marker key={i} position={latLng} />
))}
</div>
)
}
}
https://developers.google.com/maps/documentation/javascript/react-map
I have a google map in react-native. On top of that View I have icons on the map, and these icons are placed on top of each other instead of being placed on either side of the map. I have tried many different settings but it always end up the same. Another thing is that the button reacts when I'm not clicking on it.
I have container and then mapview within the container. Here's the code:
container: {
flex: 1,
flexDirection: 'column'
},
map:{
height: 90+ "%",
flexDirection: 'column'
},
profileBtn:{
position: 'absolute',
top: 25,
right: 30,
width: 25,
height: 15,
borderRadius: 25/2,
},
homeBtn:{
position: 'absolute',
top: 20,
left: 5,
width: 200,
height: 100,
borderRadius: 25/2,
},
<MapView
style={styles.map}
initialRegion={{
latitude:this.state.latitude,
longitude:this.state.longitude,
latitudeDelta: 0.0043,
longitudeDelta: 0.0034
}}
ref={c => this.mapView = c}
onPress={this.onMapPress}
loadingEnabled={true}
>
<View style ={styles.topMap}>
<TouchableOpacity
style={styles.profileBtn}
onPress={()=>{ this.handleClickProfile() }}
>
<Image
source={profile}
borderRadius={17}
/>
</TouchableOpacity>
<TouchableOpacity
style={styles.homeBtn}
onPress={()=>{ this.handleClickFavourite() }}
>
<Image
source={require("./home.png")}
borderRadius={49}
/>
</TouchableOpacity>
</View>
{markers}
I'm not sure exactly why this would happen, but I read the source code from here, when you display a MapView, this gets returned:
return (
<AIRMap
ref={ref => { this.map = ref }}
{...props}
/>
)
Normally, when you write a custom view, you would do it this way:
return (
<AIRMap
ref={ref => { this.map = ref }}
{...props}
>
{children}
</AIRMap>
)
Maybe that's why your MapView's children don't get rendered the way you want it to. However, to solve the problem, you can simply move the views out of MapView, then wrap everything in a View:
return (
<View style={{ flex: 1 }}>
<MapView style={styles.map}>
{markers}
</MapView>
<TouchableOpacity ... />
<TouchableOpacity ... />
</View>
)
But remember, all those TouchableOpacity's must have position: 'absolute', or else your MapView won't take up the whole screen
The buttons are getting added one over the other because you have used position:absolute for the buttons.If you are intenting to use markers over map do it this way
import { Marker } from 'react-native-maps';
<MapView
region={this.state.region}
onRegionChange={this.onRegionChange}
>
{this.state.markers.map(marker => (
<Marker
coordinate={marker.latlng}
title={marker.title}
description={marker.description}
/>
))}
</MapView>
And visit this for more info
I took the react-google-maps MapWithAMarker example :
import React from 'react';
import { compose, withProps, lifecycle} from 'recompose';
import {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
} from 'react-google-maps';
import keys from '../../components/config/keys';
const MapWithAMarker = compose(
withProps({
googleMapURL: `https://maps.googleapis.com/maps/api/js?key=${keys.google_maps_api_key}&v=3.exp&libraries=geometry,drawing,places`,
loadingElement: <div style={{ height: '100%' }} />,
containerElement: <div style={{ height: '400px' }} />,
mapElement: <div style={{ height: '100%' }} />,
}),
withScriptjs,
withGoogleMap
)(props =>
<GoogleMap
defaultZoom={8}
defaultCenter={{ lat: props.lat, lng: props.lng }}>
<Marker position={{ lat: props.lat, lng: props.lng }}/>
</GoogleMap>
);
export default MapWithAMarker;
and I use it like this:
<MapWithAMarker lat={parseFloat(excursion.lat)}
lng={parseFloat(excursion.lng)} />
I use React router in my application.
Observed behaviour :
When i render the page for the first time, the map renders correctly.
If i click on a link to rerender the page with a different marker position, the map fails to load and just renders a empty grey rectangle with only "press ctrl plus scroll to zoom" when i scroll on it.
Solved :
I needed to change the defaultCenter to center and defaultZoom to zoom :
<GoogleMap zoom={8}
center={{ lat: props.lat, lng: props.lng }}>
<Marker position={{ lat: props.lat, lng: props.lng }}/>
</GoogleMap>
When a user presses on a marker I am calling animateToCoordinate to center the marker in the middle of the screen. The problem is that the callout is rendered to the position of the region before animateToCoordinate is done its animation so the callout is displayed somewhat offscreen. is there anyway to delay callout display until animateToRegion is finished? Or is there another way to go about this entirely that I am not seeing?
<MapView
ref = {(mapView) => { _mapView = mapView; }}
style={styles.map}
region={this.state.mapRegion}
showsUserLocation = {true}
showsMyLocationButton = {true}
followUserLocation={true}
onRegionChange={this.onRegionChange.bind(this)}>
{data.near.map(marker =>
{if(marker.posts.length != 0){
return (
<MapView.Marker
coordinate={{latitude: marker.location.latitude,
longitude: marker.location.longitude}}
title={marker.name}
description={marker.description}
onPress={ e => _mapView.animateToCoordinate({
latitude: e.nativeEvent.coordinate.latitude,
longitude: e.nativeEvent.coordinate.longitude
}, 500)}
onCalloutPress={ e => this._onPressItem(marker.id)}
>
<Icon name="ios-pin" style={{ fontSize: 45, color: '#f04c34'}} />
<MapView.Callout
style={{ flex: -1, position: 'absolute', width: width}}>
<ListItem >
<Body >
<View style={{flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',}}>
<Text style={{fontSize: 18, color: '#38383a', marginBottom: 10, fontWeight: 'bold'}}
>{marker.name}</Text>
<Text style={{fontSize: 14, color: '#38383a', fontWeight: 'bold'}}>{marker.distance.toFixed(2)} miles</Text>
</View>
<Text style={{fontSize: 16, fontFamily: 'Avenir', marginBottom: 15}}
>{marker.infoText}</Text>
<Text>
<Text style={{fontSize: 12, color: '#38383a', fontWeight: 'bold'}}
>{marker.address}</Text>
</Text>
</Body>
<Right></Right>
</ListItem>
</MapView.Callout>
</MapView.Marker>
)
}else return null;
})}
</MapView>
I am having this precise issue as well. My current solution is to make my marker's onPress look something like this:
markerOnPress (coord) {
TIME_FOR_ANIMATION = 700;
this.mapview.animateToCoordinate(coord);
setTimeout(() => {
this.markerRef.showCallout();
}, TIME_FOR_ANIMATION);
}
And my marker looks like this:
<Marker
ref={(ref) => { this.markerRef = ref; }}
coordinate={coord}
title={someTitle}
description={someDescription}
onPress={() => this.onMarkerPress(coord)}
/>
This works alright, although there is some unwanted behavior still occurring and I'm not sure why. Now when I click on a marker, the callout appears immediately, then disappears before animating to the coordinate, animates to the coordinate, and then displays the callout as desired. I have no idea why it's still immediately displaying the callout initially. I tried fixing this by making the first line of markerOnPress this.markerRef.hideCallout() but this had no noticeable effect.
I found a make shift way to address this...
Using a state variable, you can hide/show a blank callout and the callout you want to show
{this.state.showCallout == true ? <Callout tooltip={true}>
<View style={{backgroundColor: 'white', width: 'auto', minWidth: 50, paddingVertical: 2}}>
{emp.type == "group" ?
<View>
{emp.employees.map(e => {
return (
<Text style={{marginVertical: 2}}>{e.display_name}</Text>
)
})}
</View>
:
<Text>
</Text>}
</View>
</Callout> : <Callout tooltip={true}>
<View style={{backgroundColor: 'transparent'}}></View>
</Callout>}
Then in onPress, you can setTimeout
this.mapRef.animateCamera({
center: {
latitude: emp.latitude,
longitude: emp.longitude,
},
heading: 0, pitch: 0,
zoom: 32,
altitude: 1000,
}, {duration: 1000});
setTimeout(() => {
this.setState({ showCallout: true })
this.markerRefs[i].showCallout();
},1000)
Then in onCalloutPress you can do
this.markersRefs[i].hideCallout();
this.setState({ showCallout: false )};
i' ve using react-native-map air bnb to render a google map in my native app.
The map and marker is showed up but the marker can't drag.
this is my script
<View style={Style.mapContainer}>
<GeoLocation onSetInitalPos={this.onSetInitialPosition}
onSetLastPos={this.onSetLastPosition}/>
<MapView style={Style.map} region={this.state.region} onRegionChange={this.onRegionChange}>
<MapView.Marker draggable={this.state.draggable}
coordinate={this.state.marker.latlng}
title={this.state.marker.title}
description={this.state.marker.description}
onDrag={() => console.log('onDrag')}
/>
</MapView>
<AutoCompleteMap onSetNewPlace={this.setMarkerPosition}/>
</View>
According to docs of react-native-maps draggable:
This is a non-value based prop. Adding this allows the marker to be draggable (re-positioned).
Instead of draggable={this.state.draggable}, you should be defining it like this
<MapView style={Style.map} region={this.state.region} onRegionChange={this.onRegionChange}>
<MapView.Marker
draggable
coordinate={this.state.marker.latlng}
title={this.state.marker.title}
description={this.state.marker.description}
onDragEnd={this.onUserPinDragEnd.bind(this)} />
</MapView>
Here's a snippet of working draggable marker version of my project. Nothing fancy, just using Exponent Components to import MapView, instead of npm installing and linking.
<Components.MapView
ref={(map) => this.map = map}
style={{width: Metrics.screenWidth, height: mapHeight, zIndex: 0}}
region={{
latitude: this.state.location.coords.latitude,
longitude: this.state.location.coords.longitude,
latitudeDelta: 0.0100,
longitudeDelta: 0.0100,
}}
>
<Components.MapView.Marker
key={'i29'}
draggable
onDragEnd={this.onUserPinDragEnd.bind(this)}
title={'You are here'}
coordinate={{
latitude: this.state.userLocation.coords.latitude,
longitude: this.state.userLocation.coords.longitude,
}}
/>
</Components.MapView>
And just to be sure, have you tried hold pressing the marker to drag it? It's kinda slow.