Support center prop as {lat, lng} object

Closes #15
This commit is contained in:
cybice 2015-10-03 22:16:40 +03:00
parent 5ddec4280b
commit 765d7672b8
3 changed files with 83 additions and 11 deletions

View File

@ -49,11 +49,21 @@ const style = {
position: 'relative',
};
const latLng2Obj = (latLng) => isPlainObject(latLng)
? latLng
: {lat: latLng[0], lng: latLng[1]};
export default class GoogleMap extends Component {
static propTypes = {
apiKey: PropTypes.string,
center: PropTypes.array.isRequired,
center: React.PropTypes.oneOfType([
PropTypes.array,
PropTypes.shape({
lat: PropTypes.number,
lng: PropTypes.number,
}),
]).isRequired,
zoom: PropTypes.number.isRequired,
onBoundsChange: PropTypes.func,
onClick: PropTypes.func,
@ -101,8 +111,11 @@ export default class GoogleMap extends Component {
this.markersDispatcher_ = new MarkerDispatcher(this);
this.geoService_ = new Geo(K_GOOGLE_TILE_SIZE);
this.centerIsObject_ = isPlainObject(this.props.center);
if (this._isCenterDefined(this.props.center)) {
this.geoService_.setView(this.props.center, this.props.zoom, 0);
const propsCenter = latLng2Obj(this.props.center);
this.geoService_.setView(propsCenter, this.props.zoom, 0);
}
this.zoomAnimationInProgress_ = false;
@ -135,9 +148,10 @@ export default class GoogleMap extends Component {
if (this.map_) {
const centerLatLng = this.geoService_.getCenter();
if (nextProps.center) {
if (Math.abs(nextProps.center[0] - centerLatLng.lat) +
Math.abs(nextProps.center[1] - centerLatLng.lng) > kEPS) {
this.map_.panTo({lat: nextProps.center[0], lng: nextProps.center[1]});
const nextPropsCenter = latLng2Obj(nextProps.center);
if (Math.abs(nextPropsCenter.lat - centerLatLng.lat) +
Math.abs(nextPropsCenter.lng - centerLatLng.lng) > kEPS) {
this.map_.panTo({lat: nextPropsCenter.lat, lng: nextPropsCenter.lng});
}
}
@ -179,8 +193,8 @@ export default class GoogleMap extends Component {
}
_initMap = () => {
const center = this.props.center;
this.geoService_.setView(center, this.props.zoom, 0);
const propsCenter = latLng2Obj(this.props.center);
this.geoService_.setView(propsCenter, this.props.zoom, 0);
this._onBoundsChanged(); // now we can calculate map bounds center etc...
@ -405,7 +419,9 @@ export default class GoogleMap extends Component {
if (callExtBoundsChange !== false) {
const marginBounds = this.geoService_.getBounds(this.props.margin);
this.props.onBoundsChange(
[centerLatLng.lat, centerLatLng.lng],
this.centerIsObject_
? {...centerLatLng}
: [centerLatLng.lat, centerLatLng.lng],
zoom,
bounds,
marginBounds
@ -493,9 +509,10 @@ export default class GoogleMap extends Component {
}
}
_isCenterDefined = (center) => {
return center && center.length === 2 && isNumber(center[0]) && isNumber(center[1]);
}
_isCenterDefined = (center) => center && (
(isPlainObject(center) && isNumber(center.lat) && isNumber(center.lng)) ||
(center.length === 2 && isNumber(center[0]) && isNumber(center[1]))
)
render() {
const mapMarkerPrerender = !this.state.overlayCreated ? (

View File

@ -5,9 +5,15 @@ export default class LatLng {
if (a instanceof LatLng) {
return a;
}
if (Array.isArray(a)) {
return new LatLng(a[0], a[1]);
}
if ('lng' in a && 'lat' in a) {
return new LatLng(a.lat, a.lng);
}
return a;
}

View File

@ -56,6 +56,55 @@ describe('Components', () => {
expect(marker.parentNode.style.top).toEqual('-12.62811732746195px');
});
it('Should accept center prop as lat lng object', () => {
const mapMarkerClassName = 'mapMarkerClassName';
class MapMarker extends Component { // eslint-disable-line react/no-multi-comp
render() {
return (
<div className={mapMarkerClassName}>Marker</div>
);
}
}
class MapHolder extends Component { // eslint-disable-line react/no-multi-comp
static propTypes = {
center: PropTypes.array,
zoom: PropTypes.number,
greatPlaceCoords: PropTypes.any,
};
static defaultProps = {
center: {lat: 59.938043, lng: 30.337157},
zoom: 9,
};
constructor(props) {
super(props);
}
render() {
return (
<GoogleMap
center={this.props.center}
zoom={this.props.zoom}
>
<MapMarker lat={59.955413} lng={30.337844} />
</GoogleMap>
);
}
}
const mapHolder = TestUtils.renderIntoDocument(
<MapHolder />
);
const marker = TestUtils.findRenderedDOMComponentWithClass(mapHolder, 'mapMarkerClassName');
expect(marker.parentNode.style.left).toEqual('0.250129066669615px');
expect(marker.parentNode.style.top).toEqual('-12.62811732746195px');
});
it('Should call custom loader', () => {
const API_KEY = 'API_KEY';
const spy = expect.createSpy(() => {});