diff --git a/src/Geojson.js b/src/Geojson.js new file mode 100644 index 00000000..3567a689 --- /dev/null +++ b/src/Geojson.js @@ -0,0 +1,119 @@ +import React from 'react'; +import MapView from './index'; + +export const makeOverlays = features => { + const points = features + .filter(f => f.geometry && (f.geometry.type === 'Point' || f.geometry.type === 'MultiPoint')) + .map(feature => makeCoordinates(feature).map(coordinates => makeOverlay(coordinates, feature))) + .reduce(flatten, []) + .map(overlay => ({ ...overlay, type: 'point' })); + + const lines = features + .filter( + f => f.geometry && (f.geometry.type === 'LineString' || f.geometry.type === 'MultiLineString') + ) + .map(feature => makeCoordinates(feature).map(coordinates => makeOverlay(coordinates, feature))) + .reduce(flatten, []) + .map(overlay => ({ ...overlay, type: 'polyline' })); + + const multipolygons = features + .filter(f => f.geometry && f.geometry.type === 'MultiPolygon') + .map(feature => makeCoordinates(feature).map(coordinates => makeOverlay(coordinates, feature))) + .reduce(flatten, []); + + const polygons = features + .filter(f => f.geometry && f.geometry.type === 'Polygon') + .map(feature => makeOverlay(makeCoordinates(feature), feature)) + .reduce(flatten, []) + .concat(multipolygons) + .map(overlay => ({ ...overlay, type: 'polygon' })); + + return points.concat(lines).concat(polygons); +}; + +const flatten = (prev, curr) => prev.concat(curr); + +const makeOverlay = (coordinates, feature) => { + let overlay = { + feature, + }; + if (feature.geometry.type === 'Polygon' || feature.geometry.type === 'MultiPolygon') { + overlay.coordinates = coordinates[0]; + if (coordinates.length > 1) { + overlay.holes = coordinates.slice(1); + } + } else { + overlay.coordinates = coordinates; + } + return overlay; +}; + +const makePoint = c => ({ lat: c[1], lng: c[0] }); + +const makeLine = l => l.map(makePoint); + +const makeCoordinates = feature => { + const g = feature.geometry; + if (g.type === 'Point') { + return [makePoint(g.coordinates)]; + } else if (g.type === 'MultiPoint') { + return g.coordinates.map(makePoint); + } else if (g.type === 'LineString') { + return [makeLine(g.coordinates)]; + } else if (g.type === 'MultiLineString') { + return g.coordinates.map(makeLine); + } else if (g.type === 'Polygon') { + return g.coordinates.map(makeLine); + } else if (g.type === 'MultiPolygon') { + return g.coordinates.map(p => p.map(makeLine)); + } else { + return []; + } +}; + +const Geojson = props => { + const overlays = makeOverlays(props.geojson.features); + return ( + + {overlays.map((overlay, index) => { + if (overlay.type === 'point') { + return ( + + ); + } + if (overlay.type === 'polygon') { + return ( + + ); + } + if (overlay.type === 'polyline') { + return ( + + ); + } + })} + + ); +}; + +export default Geojson; diff --git a/src/index.js b/src/index.js index dab5f226..3ff5a50f 100755 --- a/src/index.js +++ b/src/index.js @@ -4,11 +4,26 @@ import { withGoogleMap, GoogleMap } from 'react-google-maps'; import Marker from './Marker'; import Polyline from './Polyline'; import Callout from './Callout'; +import Geojson from './Geojson'; const GoogleMapContainer = withGoogleMap(props => ( )); +function googleToReact(point) { + return { + latitude: point.lat(), + longitude: point.lng(), + }; +} + +function reactToGoogle(point) { + return { + lat: point.latitude, + lng: point.longitude, + }; +} + class MapView extends Component { state = { center: null, @@ -29,23 +44,28 @@ class MapView extends Component { animateCamera(camera) { this.setState({ zoom: camera.zoom }); - this.setState({ center: camera.center }); + this.setState({ center: reactToGoogle(camera.center) }); } animateToRegion(coordinates) { this.setState({ - center: { lat: coordinates.latitude, lng: coordinates.longitude }, + center: reactToGoogle(coordinates), }); } + async getMapBoundaries() { + const bounds = this.map.getBounds(); + return { + northEast: googleToReact(bounds.getNorthEast()), + southWest: googleToReact(bounds.getSouthWest()), + }; + } + onDragEnd = () => { const { onRegionChangeComplete } = this.props; if (this.map && onRegionChangeComplete) { const center = this.map.getCenter(); - onRegionChangeComplete({ - latitude: center.lat(), - longitude: center.lng(), - }); + onRegionChangeComplete(googleToReact(center)); } }; @@ -58,16 +78,10 @@ class MapView extends Component { ? { center } : region ? { - center: { - lat: region.latitude, - lng: region.longitude, - }, + center: reactToGoogle(region), } : { - defaultCenter: { - lat: initialRegion.latitude, - lng: initialRegion.longitude, - }, + defaultCenter: reactToGoogle(initialRegion), }; const zoom = defaultZoom || @@ -102,6 +116,8 @@ class MapView extends Component { MapView.Marker = Marker; MapView.Polyline = Polyline; MapView.Callout = Callout; +MapView.Geojson = Geojson; +export { Marker, Polyline, Callout, Geojson }; const styles = StyleSheet.create({ container: {