diff --git a/develop/Main.js b/develop/Main.js
index 33d6db6..88250a1 100644
--- a/develop/Main.js
+++ b/develop/Main.js
@@ -4,6 +4,7 @@ import { render } from 'react-dom';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import Layout from './Layout';
import GMap from './GMap';
+import GMapOptim from './GMapOptim';
import 'normalize.css/normalize.css';
import './Main.sass';
@@ -13,7 +14,8 @@ const mountNode = document.getElementById('app');
render(
-
+
+
diff --git a/develop/config/index.babel.js b/develop/config/index.babel.js
index 6244341..a934bab 100644
--- a/develop/config/index.babel.js
+++ b/develop/config/index.babel.js
@@ -1,11 +1,20 @@
import path from 'path'; // eslint-disable-line no-var
import autoprefixer from 'autoprefixer'; // eslint-disable-line no-var
+import webpack from 'webpack';
export default {
devtool: 'cheap-module-eval-source-map',
postcss: [
autoprefixer({ browsers: ['last 2 versions'] }),
],
+ plugins: [
+ new webpack.DefinePlugin(process.env.NODE_ENV
+ ? {
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
+ }
+ : {}
+ ),
+ ],
module: {
loaders: [
{
diff --git a/develop/markers/ClusterMarker.js b/develop/markers/ClusterMarker.js
index ad86742..3aa72ef 100644
--- a/develop/markers/ClusterMarker.js
+++ b/develop/markers/ClusterMarker.js
@@ -7,7 +7,7 @@ import { Motion, spring } from 'react-motion';
import clusterMarkerStyles from './ClusterMarker.sass';
export const clusterMarker = ({
- styles, text, hovered,
+ styles, text, hovered, $hover,
defaultMotionStyle, motionStyle,
}) => (
({
+ $hover,
hovered,
motionStyle: {
scale: spring(
- hovered ? hoveredScale : defaultScale,
+ (hovered || $hover) ? hoveredScale : defaultScale,
{ stiffness, damping, precision }
),
},
diff --git a/develop/markers/ReactiveMarker.js b/develop/markers/ReactiveMarker.js
new file mode 100644
index 0000000..4d566f4
--- /dev/null
+++ b/develop/markers/ReactiveMarker.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import compose from 'recompose/compose';
+import SimpleMarker from './SimpleMarker';
+import stream2Props from '../utils/stream2Props';
+import 'rxjs/add/operator/filter';
+import 'rxjs/add/operator/map';
+import 'rxjs/add/operator/do';
+import 'rxjs/add/operator/scan';
+import 'rxjs/add/operator/distinctUntilChanged';
+// import defaultProps from 'recompose/defaultProps';
+// import reactiveMarkerStyles from './reactiveMarker.scss';
+
+export const reactiveMarker = (props) => (
+
+);
+
+export const reactiveMarkerHOC = compose(
+ stream2Props(({ id, hoveredMarkerId$ }) => (
+ hoveredMarkerId$
+ .map(hoveredMarkerId => hoveredMarkerId === id)
+ .distinctUntilChanged()
+ .map(v => ({ hovered: v }))
+ ))
+);
+
+export default reactiveMarkerHOC(reactiveMarker);
diff --git a/develop/markers/SimpleMarker.js b/develop/markers/SimpleMarker.js
index 78ed36d..fc5d66f 100644
--- a/develop/markers/SimpleMarker.js
+++ b/develop/markers/SimpleMarker.js
@@ -7,7 +7,7 @@ import { clusterMarkerHOC } from './ClusterMarker.js';
import simpleMarkerStyles from './SimpleMarker.sass';
export const simpleMarker = ({
- styles, hovered,
+ styles, hovered, $hover,
defaultMotionStyle, motionStyle,
}) => (
@@ -32,7 +32,7 @@ export const simpleMarker = ({
export const simpleMarkerHOC = compose(
defaultProps({
styles: simpleMarkerStyles,
- initialScale: 0.3,
+ initialScale: 0.6,
defaultScale: 0.6,
hoveredScale: 0.7,
}),
diff --git a/develop/tests/playground.spec.js b/develop/tests/playground.spec.js
new file mode 100644
index 0000000..fcb3aec
--- /dev/null
+++ b/develop/tests/playground.spec.js
@@ -0,0 +1,18 @@
+/* eslint-disable max-len */
+// `npm bin`/mocha --compilers js:babel-register --require babel-polyfill --reporter min --watch './develop/**/*.spec.js'
+/* eslint-enable max-len */
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+import 'rxjs/add/operator/distinctUntilChanged';
+
+describe('Playground', () => {
+ it('Play', async () => {
+ const comparator = (a, b) => a === b;
+ const props$ = (new BehaviorSubject(1))
+ .distinctUntilChanged(comparator);
+
+ props$.subscribe(v => console.log(v));
+ props$.next(1);
+ props$.next(2);
+ props$.next(1);
+ });
+});
diff --git a/develop/utils/omit.js b/develop/utils/omit.js
new file mode 100644
index 0000000..8a27b3c
--- /dev/null
+++ b/develop/utils/omit.js
@@ -0,0 +1,13 @@
+// https://github.com/acdlite/recompose/blob/master/src/packages/recompose/utils/omit.js
+const omit = (obj, keys) => {
+ const { ...rest } = obj;
+ for (let i = 0; i < keys.length; i++) {
+ const key = keys[i];
+ if (rest.hasOwnProperty(key)) {
+ delete rest[key];
+ }
+ }
+ return rest;
+};
+
+export default omit;
diff --git a/develop/utils/pick.js b/develop/utils/pick.js
new file mode 100644
index 0000000..67c9740
--- /dev/null
+++ b/develop/utils/pick.js
@@ -0,0 +1,14 @@
+// https://github.com/acdlite/recompose/blob/master/src/packages/recompose/utils/pick.js
+
+const pick = (obj, keys) => {
+ const result = {};
+ for (let i = 0; i < keys.length; i++) {
+ const key = keys[i];
+ if (obj.hasOwnProperty(key)) {
+ result[key] = obj[key];
+ }
+ }
+ return result;
+};
+
+export default pick;
diff --git a/develop/utils/props2Stream.js b/develop/utils/props2Stream.js
new file mode 100644
index 0000000..34c7878
--- /dev/null
+++ b/develop/utils/props2Stream.js
@@ -0,0 +1,28 @@
+import { Component } from 'react';
+import createEagerFactory from './createEagerFactory';
+import createHelper from 'recompose/createHelper';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+import 'rxjs/add/operator/distinctUntilChanged';
+import omit from './omit';
+
+const prop2Stream = (propName, comparator = (a, b) => a === b) =>
+ BaseComponent => {
+ const factory = createEagerFactory(BaseComponent);
+ return class extends Component {
+ props$ = (new BehaviorSubject(this.props[propName]))
+ .distinctUntilChanged(comparator);
+
+ componentWillReceiveProps(nextProps) {
+ this.props$.next(nextProps[propName]);
+ }
+
+ render() {
+ return factory({
+ ...omit(this.props, [propName]),
+ [`${propName}$`]: this.props$,
+ });
+ }
+ };
+ };
+
+export default createHelper(prop2Stream, 'prop2Stream');
diff --git a/develop/utils/stream2Props.js b/develop/utils/stream2Props.js
new file mode 100644
index 0000000..cbefbfb
--- /dev/null
+++ b/develop/utils/stream2Props.js
@@ -0,0 +1,31 @@
+import { Component } from 'react';
+import createEagerFactory from './createEagerFactory';
+import createHelper from 'recompose/createHelper';
+
+// if stream prop will change this will fail,
+// this is expected behavior
+const stream2Props = (props2Stream) =>
+ BaseComponent => {
+ const factory = createEagerFactory(BaseComponent);
+ return class extends Component {
+ state = {};
+
+ componentWillMount() {
+ this.subscription = props2Stream(this.props)
+ .subscribe(value => this.setState({ value }));
+ }
+
+ componentWillUnmount() {
+ this.subscription.unsubscribe();
+ }
+
+ render() {
+ return factory({
+ ...this.props,
+ ...this.state.value,
+ });
+ }
+ };
+ };
+
+export default createHelper(stream2Props, 'stream2Props');
diff --git a/package.json b/package.json
index 6c26063..c6de2fc 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
"file-loader": "^0.8.5",
"jsdom": "^6.5.1",
"kotatsu": "^0.14.0",
- "lodash": "^4.6.1",
+ "lodash": "^4.13.1",
"mocha": "^2.3.3",
"node-sass": "^3.7.0",
"normalize.css": "^4.1.1",
@@ -82,6 +82,7 @@
"recompose": "^0.19.0",
"reselect": "^2.5.1",
"rimraf": "^2.4.3",
+ "rxjs": "^5.0.0-beta.8",
"sass-loader": "^3.2.0",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
diff --git a/src/google_map.js b/src/google_map.js
index 9f31a5c..bc33166 100644
--- a/src/google_map.js
+++ b/src/google_map.js
@@ -435,6 +435,7 @@ export default class GoogleMap extends Component {
ReactDOM.render(
(
{
+ // layers
+ if (child.props.latLng === undefined &&
+ child.props.lat === undefined &&
+ child.props.lng === undefined) {
+ return;
+ }
+
const childKey = child.key !== undefined && child.key !== null ? child.key : childIndex;
const dist = this.props.distanceToMouse(this.dimesionsCache_[childKey], mp, child.props);
if (dist < hoverDistance) {
@@ -211,14 +226,26 @@ export default class GoogleMapMarkers extends Component {
render() {
const mainElementStyle = this.props.style || mainStyle;
-
this.dimesionsCache_ = {};
const markers = React.Children.map(this.state.children, (child, childIndex) => {
- const pt = this.props.geoService.project({
- lat: child.props.lat,
- lng: child.props.lng,
- }, this.props.projectFromLeftTop);
+ if (child.props.latLng === undefined &&
+ child.props.lat === undefined &&
+ child.props.lng === undefined) {
+ return (
+ React.cloneElement(child, {
+ $geoService: this.props.geoService,
+ $onMouseAllow: this._onMouseAllow,
+ $prerender: this.props.prerender,
+ })
+ );
+ }
+
+ const latLng = child.props.latLng !== undefined
+ ? child.props.latLng
+ : { lat: child.props.lat, lng: child.props.lng };
+
+ const pt = this.props.geoService.project(latLng, this.props.projectFromLeftTop);
const stylePtPos = {
left: pt.x,
@@ -238,11 +265,11 @@ export default class GoogleMapMarkers extends Component {
// to prevent rerender on child element i need to pass
// const params $getDimensions and $dimensionKey instead of dimension object
const childKey = child.key !== undefined && child.key !== null ? child.key : childIndex;
+
this.dimesionsCache_[childKey] = {
x: pt.x + dx,
y: pt.y + dy,
- lat: child.props.lat,
- lng: child.props.lng,
+ ...latLng,
};
return (