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;