Spice up the maps with some InfoWindows
This commit is contained in:
21
src/components/Map/Map.css
Normal file
21
src/components/Map/Map.css
Normal file
@@ -0,0 +1,21 @@
|
||||
.root {
|
||||
height: 360px;
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
overflow: hidden;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.map {
|
||||
height: 360px;
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.info {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.infoTitle {
|
||||
margin: 2px 0 10px;
|
||||
}
|
||||
@@ -1,57 +1,103 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { withGoogleMap, GoogleMap, Marker } from 'react-google-maps';
|
||||
import withStyles from 'isomorphic-style-loader/lib/withStyles';
|
||||
import { withGoogleMap, GoogleMap, Marker, InfoWindow } from 'react-google-maps';
|
||||
import s from './Map.css';
|
||||
|
||||
class Map extends React.Component {
|
||||
static propTypes = {
|
||||
defaultZoom: PropTypes.number.isRequired,
|
||||
lat: PropTypes.number.isRequired,
|
||||
lng: PropTypes.number.isRequired,
|
||||
markers: PropTypes.arrayOf(PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
defaultCenter: PropTypes.shape({
|
||||
lat: PropTypes.number.isRequired,
|
||||
lng: PropTypes.number.isRequired,
|
||||
}).isRequired,
|
||||
markers: PropTypes.arrayOf(PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
position: PropTypes.shape({
|
||||
lat: PropTypes.number.isRequired,
|
||||
lng: PropTypes.number.isRequired,
|
||||
}).isRequired,
|
||||
showInfo: PropTypes.boolean,
|
||||
infoContent: PropTypes.string,
|
||||
})).isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
markers: this.props.markers,
|
||||
};
|
||||
}
|
||||
|
||||
handleMarkerClick = (targetMarker) => {
|
||||
this.setState({
|
||||
markers: this.state.markers.map(marker => {
|
||||
if (marker === targetMarker) {
|
||||
return {
|
||||
...marker,
|
||||
showInfo: true,
|
||||
};
|
||||
}
|
||||
return marker;
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
handleMarkerClose = (targetMarker) => {
|
||||
this.setState({
|
||||
markers: this.state.markers.map(marker => {
|
||||
if (marker === targetMarker) {
|
||||
return {
|
||||
...marker,
|
||||
showInfo: false,
|
||||
};
|
||||
}
|
||||
return marker;
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const GMap = withGoogleMap(() => (
|
||||
<GoogleMap
|
||||
defaultZoom={this.props.defaultZoom}
|
||||
defaultCenter={{ lat: this.props.lat, lng: this.props.lng }}
|
||||
defaultCenter={this.props.defaultCenter}
|
||||
>
|
||||
{this.props.markers.map((props, index) => (
|
||||
{this.state.markers.map((marker, index) => (
|
||||
<Marker
|
||||
title={props.title}
|
||||
position={{ lat: props.lat, lng: props.lng }}
|
||||
key={index}
|
||||
/>
|
||||
defaultAnimation="2"
|
||||
{...marker}
|
||||
onClick={() => this.handleMarkerClick(marker)}
|
||||
>
|
||||
{marker.showInfo && (
|
||||
<InfoWindow
|
||||
onCloseClick={() => this.handleMarkerClose(marker)}
|
||||
>
|
||||
<div className={s.info}>
|
||||
<h6 className={s.infoTitle}>
|
||||
{marker.url ? (
|
||||
<a href={marker.url}>{marker.title}</a>
|
||||
) : marker.title }
|
||||
</h6>
|
||||
{marker.infoContent}
|
||||
</div>
|
||||
</InfoWindow>
|
||||
)}
|
||||
</Marker>
|
||||
))}
|
||||
</GoogleMap>
|
||||
));
|
||||
return (
|
||||
<GMap
|
||||
containerElement={
|
||||
<div
|
||||
style={{
|
||||
height: '360px',
|
||||
width: '100%',
|
||||
maxWidth: '480px',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
/>
|
||||
<div className={s.root} />
|
||||
}
|
||||
mapElement={
|
||||
<div
|
||||
style={{
|
||||
height: '360px',
|
||||
width: '100%',
|
||||
maxWidth: '480px',
|
||||
}}
|
||||
/>
|
||||
<div className={s.map} />
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Map;
|
||||
export default withStyles(s)(Map);
|
||||
|
||||
Reference in New Issue
Block a user