Skip to content

Commit

Permalink
Added feature: update heat map on data change + fix linting (google-m…
Browse files Browse the repository at this point in the history
…ap-react#593)

* Added feature: update heat map on data change

When prop updateHeatmap is set to true --> map will rerender.
- New render of <GoogleMapReact> and data is changed, prop updateHeatmap should be true
- New render of <GoogleMapReact> and data is not changed, prop updateHeatmap should be false

* Supports multiple google map libraries + update heatmap when prop updateHeatmap equals true

* Updated this.props -> nextProps (rookie mistake...)

* Updated API documentation:
- added info about the use of other libraries in the Google Map API
- added info about the updateHeatmap prop
  • Loading branch information
DonovanDeSmedt authored and itsmichaeldiego committed Nov 8, 2018
1 parent 4a92a42 commit 1ce8726
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 39 deletions.
89 changes: 58 additions & 31 deletions API.md
Expand Up @@ -81,6 +81,7 @@ createMapOptions: function (maps) {

<GoogleMap options={createMapOptions} ... />
```

See "Custom map options example" in Examples below for a further example.
See full options at [Google Maps Javascript API docs](https://developers.google.com/maps/documentation/javascript/controls#ControlOptions)

Expand All @@ -94,19 +95,20 @@ The `event` prop in args is the outer div onClick event, not the gmap-api 'click

Example:

```javascript
_onClick = ({x, y, lat, lng, event}) => console.log(x, y, lat, lng, event)
// ES5 users
function _onClick(obj){ console.log(obj.x, obj.y, obj.lat, obj.lng, obj.event);}
```javascript
_onClick = ({x, y, lat, lng, event}) => console.log(x, y, lat, lng, event)
// ES5 users
function _onClick(obj){ console.log(obj.x, obj.y, obj.lat, obj.lng, obj.event);}

<GoogleMap onClick={_onClick} ... />
```
<GoogleMap onClick={_onClick} ... />
```

#### onBoundsChange (func) (_Deprecated use onChange_)

```
({ center, zoom, bounds, marginBounds })
```

```
[lat, lng] = center;
[topLat, leftLng, bottomLat, rightLng] = bounds;
Expand All @@ -131,29 +133,29 @@ Default: false
#### onZoomAnimationEnd (func)

#### onMapTypeIdChange (func)

When the user changes the map type (HYBRID, ROADMAP, SATELLITE, TERRAIN) this fires

#### distanceToMouse (func)

#### googleMapLoader (func)

#### onGoogleApiLoaded (func)
Directly access the maps API - *use at your own risk!*

Directly access the maps API - _use at your own risk!_

#### onTilesLoaded (func)
This function is called when the visible tiles have finished loading.

```javascript
<GoogleMap onGoogleApiLoaded={({map, maps}) => console.log(map, maps)} />
<GoogleMap onGoogleApiLoaded={({ map, maps }) => console.log(map, maps)} />
```

To prevent warning message add _yesIWantToUseGoogleMapApiInternals_ property to GoogleMap

```javascript
<GoogleMap onGoogleApiLoaded={({map, maps}) => console.log(map, maps)}
yesIWantToUseGoogleMapApiInternals
/>
```
<GoogleMap onGoogleApiLoaded={({ map, maps }) => console.log(map, maps)} yesIWantToUseGoogleMapApiInternals />
```

#### overlayViewDivStyle (object)

Expand All @@ -164,15 +166,19 @@ Add custom style to `div` (marker container element) created by OverlayView, for
### parameters

#### lat (number)

Latitude to place the marker component

#### lng (number)

Longitude to place the marker component

#### $hover (bool) [automatic]

GoogleMap passes a $hover prop to hovered components. To detect hover it an uses internal mechanism, explained in x_distance_hover example

Example:

```javascript
render() {
const style = this.props.$hover ? greatPlaceStyleHover : greatPlaceStyle;
Expand All @@ -183,13 +189,13 @@ render() {
</div>
);
}
```

```

## Utility functions

#### fitBounds (func)
Use fitBounds to get zoom and center.

Use fitBounds to get zoom and center.

Example:

Expand Down Expand Up @@ -222,10 +228,10 @@ const bounds = {

const size = {
width: 640, // Map width in pixels
height: 380, // Map height in pixels
height: 380 // Map height in pixels
};

const {center, zoom} = fitBounds(bounds, size);
const { center, zoom } = fitBounds(bounds, size);
```

#### tile2LatLng (func)
Expand Down Expand Up @@ -285,15 +291,15 @@ export default class SearchBox extends React.Component {
static propTypes = {
placeholder: React.PropTypes.string,
onPlacesChanged: React.PropTypes.func
}
};
render() {
return <input ref="input" {...this.props} type="text"/>;
return <input ref="input" {...this.props} type="text" />;
}
onPlacesChanged = () => {
if (this.props.onPlacesChanged) {
this.props.onPlacesChanged(this.searchBox.getPlaces());
}
}
};
componentDidMount() {
var input = ReactDOM.findDOMNode(this.refs.input);
this.searchBox = new google.maps.places.SearchBox(input);
Expand All @@ -315,14 +321,14 @@ and if so, uses it, so it won't load a second copy of the library.

### Override the default minimum zoom

*WARNING*: Setting this option can break markers calculation, causing no homeomorphism between screen coordinates and map.
_WARNING_: Setting this option can break markers calculation, causing no homeomorphism between screen coordinates and map.

You can use the `minZoom` custom option to prevent our minimum-zoom calculation:

```javascript
function createMapOptions() {
return {
minZoom: 2,
minZoom: 2
};
}
```
Expand All @@ -337,7 +343,7 @@ To resolve this ambigiuity, you can use the custom map option `gestureHandling`
function createMapOptions() {
return {
gestureHandling: 'greedy' // Will capture all touch events on the map towards map panning
}
};
}
```

Expand All @@ -353,20 +359,41 @@ For enabling heatmap layer, just add `heatmapLibrary={true}` and provide data fo

```javascript
<GoogleMapReact
bootstrapURLKeys={{ key: [YOUR_KEY] }}
zoom={zoom}
center={center}
heatmapLibrary={true}
heatmap={{data}}
>
{markers}
</GoogleMapReact>
bootstrapURLKeys={{ key: [YOUR_KEY] }}
zoom={zoom}
center={center}
heatmapLibrary={true}
heatmap={{ data }}
>
{markers}
</GoogleMapReact>
```

#### Update heatmap during runtime

The heatmap can be updated with new positions or with new settings (radius, zoom, ...) during the lifecycle of the `GoogleMapReact` component. This can be done by setting the prop `updateHeatmap` to true. Which will let the heatmap know it has to rerender itself.

#### Important Note

If you have multiple `GoogleMapReact` components in project and you want to use heatmap layer so provide `heatmapLibrary={true}` for all `GoogleMapReact` components so component will load heatmap library at the beginning with google map api.

### Other libraries

Some features of the Google Map Api are available through _libraries_, which are not loaded by default. Offering those components as optional libraries allow the main api to load quickly.

In order to use one of the optional libraries, specify one of the following props in the `GoogleMapReact` component. Multiple libraries can be specified at the time.

**Drawing library:** `drawingLibrary={true}`

**Geometry library:** `geometryLibrary={true}`

**Heatmap library:** `heatmapLibrary={true}`

See [Google documentation](https://developers.google.com/maps/documentation/javascript/libraries) for more info about those libraries.

The library can be used after setting the prop `onGoogleApiLoaded`, which allows to directly access the maps API - _use at your own risk!_
The library is than accessable through the `google.maps.{libraryName}` namespace.

### Localizing the Map

This is done by setting bootstrapURLKeys.[language](https://developers.google.com/maps/documentation/javascript/localization#Language) and bootstrapURLKeys.[region](https://developers.google.com/maps/documentation/javascript/localization#Region). Also notice that setting region to 'cn' is required when using the map from within China, see [google documentation](https://developers.google.com/maps/documentation/javascript/localization#GoogleMapsChina) for more info. Setting 'cn' will result in use of the specific API URL for China.
30 changes: 25 additions & 5 deletions src/google_map.js
Expand Up @@ -155,7 +155,12 @@ export default class GoogleMap extends Component {
},
layerTypes: [],
heatmap: {},
heatmapLibrary: false,
libraries: {
visualization: false,
geometry: false,
places: false,
drawing: false,
},
};

static googleMapLoader = googleMapLoader; // eslint-disable-line
Expand Down Expand Up @@ -266,8 +271,14 @@ export default class GoogleMap extends Component {
...(this.props.apiKey && { key: this.props.apiKey }),
...this.props.bootstrapURLKeys,
};

this.props.googleMapLoader(bootstrapURLKeys, this.props.heatmapLibrary); // we can start load immediatly
const libraries = {
visualization: this.props.heatmapLibrary,
geometry: this.props.geometryLibrary,
places: this.props.placesLibrary,
drawing: this.props.drawingLibrary,
};
this.props.googleMapLoader(bootstrapURLKeys, libraries);
// we can start load immediatly

setTimeout(
() => {
Expand Down Expand Up @@ -303,6 +314,10 @@ export default class GoogleMap extends Component {
}
}

if (nextProps.updateHeatmap) {
setTimeout(() => optionsHeatmap(this.heatmap, nextProps.heatmap));
}

if (
!this._isCenterDefined(this.props.center) &&
this._isCenterDefined(nextProps.center)
Expand Down Expand Up @@ -500,9 +515,14 @@ export default class GoogleMap extends Component {
...(this.props.apiKey && { key: this.props.apiKey }),
...this.props.bootstrapURLKeys,
};

const libraries = {
visualization: this.props.heatmapLibrary,
geometry: this.props.geometryLibrary,
places: this.props.placesLibrary,
drawing: this.props.drawingLibrary,
};
this.props
.googleMapLoader(bootstrapURLKeys, this.props.heatmapLibrary)
.googleMapLoader(bootstrapURLKeys, libraries)
.then(maps => {
if (!this.mounted_) {
return;
Expand Down
16 changes: 13 additions & 3 deletions src/loaders/google_map_loader.js
Expand Up @@ -20,7 +20,7 @@ const _customPromise = new Promise(resolve => {
});

// TODO add libraries language and other map options
export default (bootstrapURLKeys, heatmapLibrary) => {
export default (bootstrapURLKeys, libraries) => {
if (!$script_) {
$script_ = require('scriptjs'); // eslint-disable-line
}
Expand Down Expand Up @@ -71,10 +71,20 @@ export default (bootstrapURLKeys, heatmapLibrary) => {
);

const baseUrl = getUrl(bootstrapURLKeys.region);
const libraries = heatmapLibrary ? '&libraries=visualization' : '';
const librariesUrl = Object.keys(libraries)
.reduce(
(libraryUrl, libraryKey) => {
if (libraries[libraryKey]) {
return `${libraryUrl}${libraryKey},`;
}
return libraryUrl;
},
'&libraries='
)
.slice(0, -1);

$script_(
`${baseUrl}${API_PATH}${params}${libraries}`,
`${baseUrl}${API_PATH}${params}${librariesUrl}`,
() =>
typeof window.google === 'undefined' &&
reject(new Error('google map initialization error (not loaded)'))
Expand Down

0 comments on commit 1ce8726

Please sign in to comment.