1 | # Documentation
|
2 |
|
3 | Here I'll try to explain why some methods in google map react are needed and how to use them.
|
4 |
|
5 | For all examples I'll use [recompose](github.com/acdlite/recompose)
|
6 | and you must have basic understanding what `css-modules` is.
|
7 |
|
8 | _Looks like to rewrite current api I need to create Documentation about current version,
|
9 | so it will be easier to detect wrong ideas and solutions_
|
10 |
|
11 | ## Simple example.
|
12 |
|
13 | [Simple example](http://www.webpackbin.com/N1N_45Owz)
|
14 |
|
15 | At `Map.js` you will see the smallest possible boilerplate for GoogleMapReact component,
|
16 |
|
17 | And a `MyMarker.js` is a simple React component.
|
18 |
|
19 | Open `Log` tab at the top of `webpackbin` and see the `mapProps` log.
|
20 | (_see the `withProps` at `Map.js`_)
|
21 |
|
22 | First value is the { `center` and `zoom` } which is set by you (_see withState at Map.js_),
|
23 | and second value is the value provided by `GoogleMapReact` component at initialization in `onChange` callback.
|
24 |
|
25 | ```javascript
|
26 | {
|
27 | center: { lat, lng }, // current map center
|
28 | zoom: 4, // current map zoom
|
29 | bounds: { nw, se, sw... }, // map corners in lat lng
|
30 | size: { width, height... } // map size in px
|
31 | }
|
32 | ```
|
33 |
|
34 | Calling `onChange` at initialization is needed because `map bounds` can't be calculated without knowledge of map size,
|
35 | and bounds are really usefull in a lot of situations. (_see Note below_)
|
36 |
|
37 | Please move and zoom the map to see log changes.
|
38 |
|
39 | Be sure that `onChange` callback is not called at realtime, and only at `idle` google map api callback.
|
40 |
|
41 | It's because google api itself provides changes with some delay and to avoid synchronization issues
|
42 | one of the ways was to use `idle` callback.
|
43 |
|
44 | On creation map uses the space of parent container and if parent container has zero height or width
|
45 | the map will be not visible. (_This is one of the most common issue_)
|
46 |
|
47 | If you want to place map inside `display: flex` container you need to pass `style` property
|
48 | with `{ flex: 1 }` to the control as like as [here](https://github.com/google-map-react/google-map-thousands-markers/blob/master/src/Map.js#L32)
|
49 |
|
50 | By default map will not raise `onChange` event if parent size has changed, to change such behavior
|
51 | add `resetBoundsOnResize = {true}` property.
|
52 |
|
53 | _NOTE: Now I think it was wrong decision to call onChange at initialization.
|
54 | In the future releases
|
55 | I'll remove such behavior and will provide helper to calculate size and bounds outside map control.
|
56 | I think about helper similar to [AutoSizer](https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md)
|
57 | it also will allow to remove `resetBoundsOnResize`, `style` properties_
|
58 |
|
59 | PS: I highly recommend you to use GoogleMapReact as a controllable component,
|
60 | and always provide `center`, `zoom` and `onChange` props. (_see withState_)
|
61 |
|
62 | _NOTE: In the future releases I'll remove usage of all `defaultProps` like `defaultCenter`_
|
63 |
|
64 | ## Whats wrong with "Simple example" above
|
65 |
|
66 | The wrong part is that React components are placed on the map positioning from top, left corner.
|
67 |
|
68 | In most cases it's not the expected behaviour, so we need to change the MyMarker position by changing
|
69 | it's `position` and `left`, `top` css properties, or use `flex` as like as in this example.
|
70 |
|
71 | [Good position](http://www.webpackbin.com/VJBKkj_vM)
|
72 |
|
73 | Now `MyMarker` centered well, see the `myMarker.css` css changes and `MyMarker.js` layout change.
|
74 |
|
75 | ## Few markers with hover example.
|
76 |
|
77 | [Few markers with hover example](http://www.webpackbin.com/Ny9EW1cwf)
|
78 |
|
79 | As we use ordinary React components we can use any methods we use for hover effects like
|
80 | - css
|
81 | - onMouseEnter, onMouseLeave
|
82 |
|
83 | But the problem you will see in example that markers are uniformly distributed over the map only in
|
84 | designer pictures. In real life all that markers will be possibly in one place ;-)
|
85 |
|
86 | And with ordinary hovers we have the problem, it's hard and sometimes impossible to hover on some markers.
|
87 | So the solution is to use some algorithm for hovering.
|
88 |
|
89 | (_Note: but I think there are a lot of cases exists there you can use ordinary hovers without any issues.
|
90 | Yes, sometimes real life is like a magazine picture_)
|
91 |
|
92 | ## Few markers with hover example done right.
|
93 |
|
94 | [Few markers with hover example done right](http://www.webpackbin.com/N1Cmhy5wf)
|
95 |
|
96 | Now markers are hoverable even if placed under other marker.
|
97 |
|
98 | Let's see what has changed,
|
99 | - I've added four properties to map control `distanceToMouse`, `hoverDistance`, `onChildMouseEnter`, `onChildMouseLeave`
|
100 | - Instead of using css hovers, I now pass `hover` property to marker directly.
|
101 |
|
102 | So what does that properties means.
|
103 |
|
104 | - `distanceToMouse` you need to pass a distance function which will compute distance based on mouse position,
|
105 | marker position, and any other properties you want.
|
106 |
|
107 | It can be non euclidean distance based on some of your internals.
|
108 | For example you can return a smaller distance for some markers making them more hoverable,
|
109 | or to return infinite distance for other markers making them unhoverable.
|
110 |
|
111 | For circle markers of equal radius it can be euclidean distance
|
112 |
|
113 | ```javascript
|
114 | function distanceToMouse({ x, y }, { x: mouseX, y: mouseY }) {
|
115 | return Math.sqrt((x - mouseX) * (x - mouseX) + (y - mouseY) * (y - mouseY))
|
116 | }
|
117 | ```
|
118 |
|
119 | At the example above I use some kind of rectangular distance.
|
120 |
|
121 | [Other distanceToMouse example](https://github.com/google-map-react/google-map-react-examples/blob/dbfc2fcd381cc39da315875f5a45d4ebee765f26/web/flux/components/examples/x_distance_hover/distance_hover_map_page.jsx#L31-L46)
|
122 |
|
123 |
|
124 | - `hoverDistance: number` distance threshold,
|
125 | system can decide that marker is hovered only if `distanceToMouse` for that marker returns value less than this threshold.
|
126 |
|
127 | - `onChildMouseEnter` - similar to `onMouseEnter` but here it's a callback called with `key` and `props` arguments for marker which have the smallest `distanceToMouse` value below `hoverDistance` threshold.
|
128 |
|
129 | - `onChildMouseLeave` - similar to `onMouseLeave`.
|
130 |
|
131 | Be sure that `onChildMouseEnter`, `onChildMouseLeave` and any other method starting with `onChild*` are useless without `hoverDistance` and `distanceToMouse` props.
|
132 |
|
133 | And even now system uses some defaults for both `distanceToMouse` and `hoverDistance` it's not a good idea to use them for your app.
|
134 |
|
135 | Other `onChild*` methods `onChildClick`, `onChildMouseDown`, `onChildMouseUp`, `onChildMouseMove`.
|
136 |
|
137 | (_`onChildMouseDown`, `onChildMouseUp`, `onChildMouseMove` are usefull for creating draggable markers,
|
138 | to prevent map from moving when you drag something over, you can set `draggable` map property to false
|
139 | _)
|
140 |
|
141 | (_Note: defaults for `distanceToMouse` and `hoverDistance` will be removed in future releases_)
|
142 |
|
143 |
|
144 | ### Helper utilities
|
145 |
|
146 | ```javascript
|
147 | import { meters2ScreenPixels } from 'google-map-react/utils';
|
148 | const { w, h } = meters2ScreenPixels(sizeInMeters, { lat, lng } /* marker coords*/, zoom /* map zoom*/);
|
149 | ```
|
150 |
|
151 | `meters2ScreenPixels` it returns `horizontal - w` and `vertical - h` sizes for given size in meters, point and zoom.
|
152 |
|
153 | Having the mercator map projection for some places w and h will be different, for most places almost the same.
|
154 |
|
155 |
|
156 | ## To be continued
|