From 3db7d352dbb546938b4ae7cfe18b2b4fca1c9636 Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 15:37:45 +0100 Subject: [PATCH 1/9] Phase 1 of MarkerClusterer changes - added onCreate callback for child components --- dist/components/entity.js | 1 + dist/components/gmaps.js | 7 ++++++- src/components/entity.js | 3 ++- src/components/gmaps.js | 7 ++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/dist/components/entity.js b/dist/components/entity.js index b05aa1a..0d045f0 100644 --- a/dist/components/entity.js +++ b/dist/components/entity.js @@ -37,6 +37,7 @@ exports['default'] = function (name, latLngProp, events) { var options = this.getOptions(this.props); this.entity = new google.maps[name](options); this.addListeners(this.entity, events); + this.onCreate(name, this.entity); }, componentWillReceiveProps: function componentWillReceiveProps(nextProps) { diff --git a/dist/components/gmaps.js b/dist/components/gmaps.js index 1e0c798..b7757b5 100644 --- a/dist/components/gmaps.js +++ b/dist/components/gmaps.js @@ -102,11 +102,16 @@ var Gmaps = (0, _createReactClass2['default'])({ } return _react2['default'].cloneElement(child, { ref: child.ref, - map: _this.map + map: _this.map, + onCreate: _this.handleChildCreation }); }); }, + handleChildCreation: function handleChildCreation(entityType, entity) { + console.log('handleChildCreation', entityType, entity); + }, + render: function render() { var style = (0, _objectAssign2['default'])({ width: this.props.width, diff --git a/src/components/entity.js b/src/components/entity.js index ccf1be4..65c2e7f 100644 --- a/src/components/entity.js +++ b/src/components/entity.js @@ -14,6 +14,7 @@ export default (name, latLngProp, events) => { const options = this.getOptions(this.props); this.entity = new google.maps[name](options); this.addListeners(this.entity, events); + this.onCreate(name, this.entity); }, componentWillReceiveProps(nextProps) { @@ -53,7 +54,7 @@ export default (name, latLngProp, events) => { break; } }, - + render() { return null; } diff --git a/src/components/gmaps.js b/src/components/gmaps.js index c0e3801..6ebaa27 100644 --- a/src/components/gmaps.js +++ b/src/components/gmaps.js @@ -69,11 +69,16 @@ const Gmaps = createReactClass({ } return React.cloneElement(child, { ref: child.ref, - map: this.map + map: this.map, + onCreate: this.handleChildCreation }); }); }, + handleChildCreation(entityType, entity) { + console.log('handleChildCreation', entityType, entity); + }, + render() { const style = objectAssign({ width: this.props.width, From 7b1b268e2d1451d7a37195fcf4b420c3028baaca Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 15:43:45 +0100 Subject: [PATCH 2/9] Missed usage of 'props' rather than just 'this' in call to onCreate inside a child component --- dist/components/entity.js | 2 +- src/components/entity.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/components/entity.js b/dist/components/entity.js index 0d045f0..6471b64 100644 --- a/dist/components/entity.js +++ b/dist/components/entity.js @@ -37,7 +37,7 @@ exports['default'] = function (name, latLngProp, events) { var options = this.getOptions(this.props); this.entity = new google.maps[name](options); this.addListeners(this.entity, events); - this.onCreate(name, this.entity); + this.props.onCreate(name, this.entity); }, componentWillReceiveProps: function componentWillReceiveProps(nextProps) { diff --git a/src/components/entity.js b/src/components/entity.js index 65c2e7f..e75cb64 100644 --- a/src/components/entity.js +++ b/src/components/entity.js @@ -14,7 +14,7 @@ export default (name, latLngProp, events) => { const options = this.getOptions(this.props); this.entity = new google.maps[name](options); this.addListeners(this.entity, events); - this.onCreate(name, this.entity); + this.props.onCreate(name, this.entity); }, componentWillReceiveProps(nextProps) { From 380959ffad5bc6e37f507e3b0340c415e7f2c643 Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 15:44:15 +0100 Subject: [PATCH 3/9] Minor version increase --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 270b594..9d53344 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-gmaps", - "version": "1.9.0", + "version": "1.9.1", "description": "A Google Maps component for React.js", "main": "dist/index.js", "scripts": { From ba3a03359472830efc3b578c5c3723fb61978524 Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 15:49:21 +0100 Subject: [PATCH 4/9] Phase 2 of marker clusterer - storings markers in an array and calling MarkerClusterer in createMap --- dist/components/gmaps.js | 11 ++++++++++- package.json | 1 + src/components/gmaps.js | 8 +++++++- yarn.lock | 5 +++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dist/components/gmaps.js b/dist/components/gmaps.js index b7757b5..df7f0d3 100644 --- a/dist/components/gmaps.js +++ b/dist/components/gmaps.js @@ -24,6 +24,10 @@ var _objectAssign = require('object-assign'); var _objectAssign2 = _interopRequireDefault(_objectAssign); +var _googleMarkerclusterer = require('@google/markerclusterer'); + +var _googleMarkerclusterer2 = _interopRequireDefault(_googleMarkerclusterer); + var _eventsMap = require('../events/map'); var _eventsMap2 = _interopRequireDefault(_eventsMap); @@ -46,6 +50,8 @@ var Gmaps = (0, _createReactClass2['default'])({ map: null, + markers: [], + getInitialState: function getInitialState() { return { isMapCreated: false @@ -91,6 +97,9 @@ var Gmaps = (0, _createReactClass2['default'])({ if (this.props.onMapCreated) { this.props.onMapCreated(this.map); } + if (this.props.clusterMarkers) { + new _googleMarkerclusterer2['default'](this.map, this.markers); + } }, getChildren: function getChildren() { @@ -109,7 +118,7 @@ var Gmaps = (0, _createReactClass2['default'])({ }, handleChildCreation: function handleChildCreation(entityType, entity) { - console.log('handleChildCreation', entityType, entity); + if (entityType === 'Marker') this.markers.push(entity); }, render: function render() { diff --git a/package.json b/package.json index 9d53344..feeda84 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ ] }, "dependencies": { + "@google/markerclusterer": "^1.0.3", "create-react-class": "^15.5.2", "object-assign": "^4.0.1" }, diff --git a/src/components/gmaps.js b/src/components/gmaps.js index 6ebaa27..7a07b7c 100644 --- a/src/components/gmaps.js +++ b/src/components/gmaps.js @@ -2,6 +2,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import createReactClass from 'create-react-class'; import objectAssign from 'object-assign'; +import MarkerClusterer from '@google/markerclusterer'; import MapEvents from '../events/map'; import Listener from '../mixins/listener'; import GoogleMaps from '../utils/google-maps'; @@ -13,6 +14,8 @@ const Gmaps = createReactClass({ map: null, + markers: [], + getInitialState() { return { isMapCreated: false @@ -60,6 +63,9 @@ const Gmaps = createReactClass({ if (this.props.onMapCreated) { this.props.onMapCreated(this.map); } + if (this.props.clusterMarkers) { + new MarkerClusterer(this.map, this.markers); + } }, getChildren() { @@ -76,7 +82,7 @@ const Gmaps = createReactClass({ }, handleChildCreation(entityType, entity) { - console.log('handleChildCreation', entityType, entity); + if (entityType === 'Marker') this.markers.push(entity); }, render() { diff --git a/yarn.lock b/yarn.lock index 9824ca5..38e89b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@google/markerclusterer@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@google/markerclusterer/-/markerclusterer-1.0.3.tgz#830b9dbba85fae9537a16d17947b484f9e860c65" + integrity sha512-/fRbSPyQKnm43zRnoyMerbiGS3vG3WkZiLgpBF3ovoLO84sKhEAzKMVcyozy/khEHlZoMJ9Axkr0NRVJRAQhcg== + JSONStream@^1.0.3: version "1.3.1" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a" From a6f9cf6d102e5d836a5a305450225b04c30e30e0 Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 15:49:41 +0100 Subject: [PATCH 5/9] minor version increase --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index feeda84..d6e8fc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-gmaps", - "version": "1.9.1", + "version": "1.9.2", "description": "A Google Maps component for React.js", "main": "dist/index.js", "scripts": { From d45a7502599ea309aee22214e1b4534690434c0c Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 16:00:39 +0100 Subject: [PATCH 6/9] MarkerCluster options added --- dist/components/gmaps.js | 4 +--- package.json | 2 +- src/components/gmaps.js | 25 ++++++++++++++++--------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/dist/components/gmaps.js b/dist/components/gmaps.js index df7f0d3..7d81c00 100644 --- a/dist/components/gmaps.js +++ b/dist/components/gmaps.js @@ -45,7 +45,6 @@ var _utilsCompareProps = require('../utils/compare-props'); var _utilsCompareProps2 = _interopRequireDefault(_utilsCompareProps); var Gmaps = (0, _createReactClass2['default'])({ - mixins: [_mixinsListener2['default']], map: null, @@ -98,7 +97,7 @@ var Gmaps = (0, _createReactClass2['default'])({ this.props.onMapCreated(this.map); } if (this.props.clusterMarkers) { - new _googleMarkerclusterer2['default'](this.map, this.markers); + new _googleMarkerclusterer2['default'](this.map, this.markers, typeof this.props.clusterMarkers === 'object' ? this.props.clusterMarkers : null); } }, @@ -133,7 +132,6 @@ var Gmaps = (0, _createReactClass2['default'])({ this.state.isMapCreated ? this.getChildren() : null ); } - }); exports['default'] = Gmaps; diff --git a/package.json b/package.json index d6e8fc8..987862b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-gmaps", - "version": "1.9.2", + "version": "1.9.3", "description": "A Google Maps component for React.js", "main": "dist/index.js", "scripts": { diff --git a/src/components/gmaps.js b/src/components/gmaps.js index 7a07b7c..db14677 100644 --- a/src/components/gmaps.js +++ b/src/components/gmaps.js @@ -9,7 +9,6 @@ import GoogleMaps from '../utils/google-maps'; import compareProps from '../utils/compare-props'; const Gmaps = createReactClass({ - mixins: [Listener], map: null, @@ -64,12 +63,18 @@ const Gmaps = createReactClass({ this.props.onMapCreated(this.map); } if (this.props.clusterMarkers) { - new MarkerClusterer(this.map, this.markers); + new MarkerClusterer( + this.map, + this.markers, + typeof this.props.clusterMarkers === 'object' + ? this.props.clusterMarkers + : null + ); } }, getChildren() { - return React.Children.map(this.props.children, (child) => { + return React.Children.map(this.props.children, child => { if (!React.isValidElement(child)) { return child; } @@ -86,18 +91,20 @@ const Gmaps = createReactClass({ }, render() { - const style = objectAssign({ - width: this.props.width, - height: this.props.height - }, this.props.style); + const style = objectAssign( + { + width: this.props.width, + height: this.props.height + }, + this.props.style + ); return (
{this.props.loadingMessage || 'Loading...'} {this.state.isMapCreated ? this.getChildren() : null}
); - }, - + } }); export default Gmaps; From 4e82036ddb073cd80c0271b0734a39c0280a0298 Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 16:14:10 +0100 Subject: [PATCH 7/9] ReadMe updated --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index db28b17..721cf2c 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,23 @@ class App extends React.Component { ReactDOM.render(, document.getElementById('gmaps')); ``` +MarkerClusterer +---- + +You can cluster markers together (see [Google's docs](https://developers.google.com/maps/documentation/javascript/marker-clustering)) by setting the `clusterMarkers` prop on the `Gmaps` component. By default this will expect icons for the clusters named `m1.png, m2.png, m3.png, m4.png, m5.png` to reside at `your_web_root/images/`. + +You can pass an options object to this prop, allowing you to specify a new location for these cluster icons. The root format will append `1.png`, `2.png`, etc to the supplied path. + +For example if your images reside at `http://localhost:3000/cluster-icons/` and are still called `m1.png`, you would supply a path of `http://localhost:3000/cluster-icons/m` similar to: + +``` + + ... + +``` + Test ---- From 6b2ef2056e49180df1ea5a6a8141f194cddd255a Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 16:19:16 +0100 Subject: [PATCH 8/9] Further readme updates --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 721cf2c..f43db6e 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,8 @@ For example if your images reside at `http://localhost:3000/cluster-icons/` and ``` +At current this is basic implementation and could be improved by adding Events to the clusters, another improvement would be to allow 'de-clustering' based on zoom level so when you have multiple markers with the exact same location you can still separate them and click on them ([stackoverlow example](https://stackoverflow.com/questions/15276908/google-markerclusterer-decluster-markers-below-a-certain-zoom-level?rq=1) or [OverlappingMarkerSpiderfier](https://github.com/jawj/OverlappingMarkerSpiderfier)). + Test ---- From f670e4a5be4731e92e5ed7ad2d27e433bda5209b Mon Sep 17 00:00:00 2001 From: AbeCole Date: Mon, 15 Apr 2019 16:20:42 +0100 Subject: [PATCH 9/9] Minor version decreased so we arn't unnecessarily skipping minor versions --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 987862b..feeda84 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-gmaps", - "version": "1.9.3", + "version": "1.9.1", "description": "A Google Maps component for React.js", "main": "dist/index.js", "scripts": {