import React from 'react'; import PropTypes from 'prop-types'; import {processPoints} from '../utils/utils'; class DataLayer extends React.Component { constructor(props) { super(props); this.displayName = 'DataLayer'; this.state = { data : null } this.initDataLayer = this.initDataLayer.bind(this); //Prop Checking this.checkPropVisibility = this.checkPropVisibility.bind(this); //Style this.styleFeatures = this.styleFeatures.bind(this); //Focus this.focus = this.focus.bind(this); } /** Focus the map on this dataLayer's features. */ focus(){ var {maps,map} = this.props; var bounds = new maps.LatLngBounds(); if(this.state.data) { this.state.data.forEach((feature)=>{ processPoints(feature.getGeometry(), bounds.extend, bounds); }); map.fitBounds(bounds); } } initDataLayer() { var {map, maps} = this.props; var dataOptions = { map } if(this.props.dataOptions) dataOptions = Object.assign(dataOptions, this.props.dataOptions); dataOptions = Object.assign(dataOptions, { style : this.styleFeatures, }) var dataLayer = new maps.Data(dataOptions) //If there is geoJSON, initialize it. if(this.props.geoJson) { var options = { idPropertyName : '_id' }; if(this.props.idPropertyName) options.idPropertyName = this.props.idPropertyName; dataLayer.addGeoJson(this.props.geoJson, options); } // dataLayer.addListener('click', (event) => { // var {feature} = event; // var coords = event.latLng.toJSON() // coords[0] = coords.lng; // coords[1] = coords.lat; // if(this.props.onClick) // this.props.onClick({id : feature.getId(), coords }); // }); this.setState({ data : dataLayer }) } checkPropVisibility(nextProps) { var {visible} = this.props; if(!visible && nextProps.visible) { this.state.data.setMap(this.props.map); } else if(visible && !nextProps.visible) this.state.data.setMap(null); } styleFeatures(feature) { //If they passed in a function to completely overide style features, then do so. if(this.props.styleFeatures) return this.props.styleFeatures(feature); var geo = feature.getGeometry(); var type = null; if(geo) type = geo.getType(); var visible = feature.getProperty('visible'); var zIndex = feature.getProperty('zIndex'); var strokeColor = feature.getProperty('strokeColor'); var fillColor = feature.getProperty('fillColor'); var fillOpacity = this.props.fillOpacity; //Do some logic on the options to make things a bit easier. if(!strokeColor) strokeColor = fillColor; zIndex = zIndex? zIndex : 10; if(this.props.zIndex) zIndex = zIndex + (10000 * this.props.zIndex) //TODO: Find a better way to separate out layer zIndexes. Right now we are defautling to 10000K features in a GeoJson schema. It works, but there should be a better way. switch(type) { case 'Polygon': var polyOptions = { strokeWeight : 1, strokeColor, fillColor, fillOpacity } //Potential Enhancement: Polyoptions could have different defaults. For now, we will leave this. if(typeof visible !== 'undefined') polyOptions.visible = true; if(typeof zIndex !== 'undefined'); polyOptions.zIndex = zIndex; return polyOptions; default: return {} } } componentWillMount() { if(this.props.maps && this.props.map) { this.initDataLayer(); this.checkPropVisibility(this.props); } else console.error(new Error("You must put this compenent in a <Map /> context component or provide the maps and map props manually.")) } componentWillUnmount() { this.state.data.setMap(null); this.setState({data : null}) } componentDidUpdate(prevProps, prevState) { } componentWillReceiveProps(nextProps) { if(typeof nextProps.visible !== 'undefined') { this.checkPropVisibility(nextProps); } } shouldComponentUpdate(nextProps, nextState) { return true; } componentWillUpdate(nextProps, nextState) { } render() { var children = [] if(this.state.data) { children = React.Children.map(this.props.children, child => React.cloneElement(child, { maps : this.props.maps, map : this.props.map, data : this.state.data })); } return <div>{children}</div>; } } DataLayer.propTypes = { maps : PropTypes.object, map : PropTypes.object, dataOptions : PropTypes.object, geoJson : PropTypes.object, visible : PropTypes.bool, onChange : PropTypes.func, styleFeatures : PropTypes.func, zIndex : PropTypes.number.isRequired, fillOpacity : PropTypes.number } export default DataLayer;