├── .editorconfig
├── .eslintrc
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── examples
├── hexbins
│ ├── advanced.html
│ ├── basic.html
│ ├── colors_discrete.html
│ ├── colors_divergent.html
│ ├── custom_scale.html
│ ├── events.html
│ ├── multi_layers.html
│ └── realtime.html
└── pings
│ ├── advanced.html
│ ├── basic.html
│ ├── efficient.html
│ └── high.volume.html
├── index.d.ts
├── package-lock.json
├── package.json
├── rollup.config.js
└── src
└── js
├── hexbin
└── HexbinLayer.js
├── index.js
└── ping
└── PingLayer.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 |
8 | indent_style = tab
9 | tab_width = 4
10 |
11 | insert_final_newline = true
12 | trim_trailing_whitespace = true
13 |
14 | [*.html]
15 | tab_width = 4
16 |
17 | [*.md]
18 | trim_trailing_whitespace = false
19 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parserOptions": {
3 | "sourceType": "module"
4 | },
5 |
6 | "env": {
7 | "es6": true,
8 | "browser": true
9 | },
10 |
11 | "extends": "eslint:recommended",
12 |
13 | "rules": {
14 | "no-unused-vars": [ "error", { "args": "none" } ],
15 |
16 | "no-mixed-spaces-and-tabs": [ "error", "smart-tabs" ],
17 | "array-bracket-spacing": [ "error", "always" ],
18 | "block-spacing": [ "error", "always" ],
19 | "brace-style": [ "error", "stroustrup", { "allowSingleLine": true } ],
20 | "comma-spacing": [ "error" ],
21 | "space-before-blocks": [ "error", "always" ]
22 | },
23 |
24 | "globals": {
25 | "console": true,
26 | "require": true,
27 | "window": true,
28 |
29 | "d3": true,
30 | "d3_hexbin": true,
31 | "L": true,
32 |
33 | "after": true,
34 | "afterEach": true,
35 | "before": true,
36 | "beforeEach": true,
37 | "context": true,
38 | "describe": true,
39 | "it": true,
40 | "should": true
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ###################
2 | # Project Specific
3 | ###################
4 | dist/
5 |
6 | ###################
7 | # Editors
8 | ###################
9 |
10 | # Eclipse
11 | .project
12 | .settings
13 | .classpath
14 |
15 | # IntelliJ
16 | .idea/
17 | *.iml
18 | *.iws
19 |
20 | # Net Beans
21 | nbactions.xml
22 | nb-configuration.xml
23 |
24 | # VS
25 | .vscode
26 |
27 | # Vi, etc
28 | *.swp
29 | *.tmp
30 | *.bak
31 |
32 | # General
33 | *~
34 |
35 |
36 | ###################
37 | # Build
38 | ###################
39 |
40 | # Node
41 | node_modules/
42 | npm-debug.log
43 | *.tgz
44 | yarn.lock
45 |
46 | # Common
47 | bin/
48 | tmp/
49 |
50 | # Apple
51 | *~.nib
52 |
53 |
54 | ###################
55 | # OS
56 | ###################
57 |
58 | # MacOS
59 | .DS_Store
60 |
61 |
62 | ###################
63 | # Tests
64 | ###################
65 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8.9"
4 | cache: yarn
5 | script: npm run build
6 | sudo: false
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2007-2018 Asymmetrik Ltd, a Maryland Corporation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # @asymmetrik/leaflet-d3
2 |
3 | [![Build Status][travis-image]][travis-url]
4 |
5 | > Leaflet D3
6 | > Provides a collection of [D3.js](http://d3js.org) based visualization plugins for [Leaflet](http://leafletjs.com/).
7 | > Now supports D3 v7
8 |
9 | ## Table of Contents
10 | - [Install](#install)
11 | - [Usage](#usage)
12 | - [Hexbins API](#hexbins-api)
13 | - [Pings API](#pings-api)
14 | - [Changelog](#changelog)
15 | - [Contribute](#contribute)
16 | - [License](#license)
17 | - [Credits](#credits)
18 |
19 |
20 | ## Install
21 | Install the package and its peer dependencies via npm:
22 | ```
23 | npm install d3 d3-hexbin leaflet
24 | ```
25 |
26 | If you want to grab the source files directly without using npm, or you want to run the examples, you can build the dist files directly.
27 | Simply check out the repository, and then build it with the following commands:
28 | ```
29 | git clone git@github.com:Asymmetrik/leaflet-d3.git
30 | cd leaflet-d3
31 | npm install
32 | npm run build
33 | ```
34 |
35 | ## Usage
36 |
37 | ### Hexbins
38 | Create dynamic hexbin-based heatmaps on Leaflet maps.
39 | This plugin is based on [the work of Steven Hall](http://www.delimited.io/blog/2013/12/1/hexbins-with-d3-and-leaflet-maps).
40 | The primary difference is that this plugin leverages the data-binding power of d3 to allow you to dynamically update the data and visualize the transitions.
41 |
42 |
43 |
44 | Live Demo: [JSFiddle](http://jsfiddle.net/acjnbu8t/embedded/result/)
45 |
46 | To use, simply declare a hexbin layer and add it to your map.
47 | You can then add data to the layer.
48 |
49 | ```js
50 | // Create the hexbin layer and set all of the accessor functions
51 | var hexLayer = L.hexbinLayer().addTo(map);
52 |
53 | // Set the data (can be set multiple times)
54 | hexLayer.data([[lng1, lat1], [lng2, lat2], ... [lngN, latN]]);
55 |
56 | ```
57 |
58 | #### Styling
59 |
60 | You will likely want to apply your own styles to the hexbin hexagons themselves. To do so, use the ```hexbin-hexagon``` class.
61 | See the following example:
62 |
63 | ```css
64 | .hexbin-hexagon {
65 | stroke: #000;
66 | stroke-width: .5px;
67 | }
68 | ```
69 |
70 | #### Tooltips
71 |
72 | You have a couple options when it comes to providing tooltips for your users.
73 | First, you can register for the appropriate hover events and manually access/manipulate the dom to show/hide tooltips.
74 | Second, you can leverage the built-in hover handlers, which try to encapsulate a lot of this behavior.
75 |
76 | ```
77 | var hexLayer = L.hexbinLayer()
78 | .hoverHandler(L.HexbinHoverHandler.tooltip());
79 | ```
80 |
81 | This handler, combined with CSS, can be used to show a tooltip and highlight the hovered hexbin.
82 | In the following example, we change the stroke color and show a tooltip.
83 |
84 | ```
85 | .hexbin-container:hover .hexbin-hexagon {
86 | transition: 200ms;
87 | stroke: orange;
88 | stroke-width: 1px;
89 | stroke-opacity: 1;
90 | }
91 |
92 | .hexbin-tooltip {
93 | padding: 8px;
94 | border-radius: 4px;
95 | border: 1px solid black;
96 | background-color: white;
97 | }
98 | ```
99 |
100 | There's more documentation on how to customize the behavior of the hover handlers in the API docs below.
101 |
102 |
103 | #### Special Notes
104 |
105 | **Applying Durations:**
106 | If your data is transforming faster than the transition duration, you may encounter unexpected behavior.
107 | This is an artifact of how transitions interact with and cancel each other.
108 | You should reduce the transition duration or eliminate it entirely if you are going to be using this plugin in a realtime manner.
109 |
110 | **Color Scales:**
111 | To use a polylinear color scale, simply provide more than two colors in the range. The domain cardinality will be adjusted automatically.
112 | A minimum of two values is required in the color range, but a single-color range is possible by using `['blue', 'blue']` for example.
113 | See the examples to see how diverging and discrete color scales can be used.
114 |
115 |
116 | ### Pings
117 | Create realtime animated drops/pings/blips on a map.
118 | This plugin can be used to indicate a transient event, such as a real-time occurrance of an event at a specific geographical location.
119 |
120 |
121 |
122 | **Live Demo:** [JSFiddle](http://jsfiddle.net/reblace/7jfhLgnq/embedded/result/)
123 |
124 | To use, simply declare a ping layer and add it to your map.
125 | You can then add data by calling the ping() method.
126 |
127 | ```js
128 | // Create the ping layer and add it to the map
129 | var pingLayer = L.pingLayer().addTo(map);
130 |
131 | // Submit data so that it shows up as a ping with an optional per-ping css class
132 | pingLayer.ping([ 38.991709, -76.886109 ], 'myCustomCssClass');
133 |
134 | ```
135 |
136 | #### Styling
137 |
138 | You will likely want to apply your own styles to the pings themselves. To do so, use the ```ping``` class.
139 | See the following example:
140 |
141 | ```css
142 | .ping {
143 | fill: steelblue;
144 | stroke: #222;
145 | stroke-width: .5px;
146 | }
147 | ```
148 |
149 |
150 | ## Hexbins API
151 |
152 | ### L.hexbinLayer(options?: {}): L.HexbinLayer
153 | Create a Leaflet map layer for visualizing data using colored/sized hexbin-based bins.
154 |
155 | ```js
156 | var hexLayer = L.hexbinLayer().addTo(map);
157 | ```
158 |
159 | ### options
160 | Set of options for customizing the appearance/behavior of the hexbin layer.
161 |
162 | Example:
163 |
164 | ```js
165 | var options = {
166 | radius : 12,
167 | opacity: 0.5,
168 | duration: 200,
169 |
170 | colorScaleExtent: [ 1, undefined ],
171 | radiusScaleExtent: [ 1, undefined ],
172 | colorDomain: null,
173 | radiusDomain: null,
174 | colorRange: [ '#f7fbff', '#08306b' ],
175 | radiusRange: [ 5, 12 ],
176 |
177 | pointerEvents: 'all'
178 | };
179 | ```
180 |
181 | #### radius
182 | Default: 12 - Sets the radius on the hexbin layer (see below for details).
183 |
184 | #### opacity
185 | Default: 0.6 - Sets the opacity on the hexbin layer (see below for details).
186 |
187 | #### duration
188 | Default: 200 - Sets the transition duration for the hexbin layer (see below for details).
189 |
190 | #### colorScaleExtent
191 | Default: [ 1, undefined ] - Sets the extent of the color scale for the hexbin layer (see below for details).
192 |
193 | #### radiusScaleExtent
194 | Default: [ 1, undefined ] - This is the same exact configuration option as ```colorScaleExtent```, only applied to the radius extent.
195 |
196 | #### colorDomain
197 | Default: null - This is used to override the default behavior, which is to derive the color domain from the data.
198 | Normally, you can tweak the generation of the color domain using the colorScaleExtent option.
199 | However, if you want to set a completely custom domain, you can provide it as an array of values with this option.
200 | The array of values will be passed directly into the domain of the color scale before rendering.
201 |
202 | #### radiusDomain
203 | Default: null - This is used to override the default behavior, which is to derive the radius domain from the data.
204 | Normally, you can tweak the generation of the radius domain using the radiusScaleExtent option.
205 | However, if you want to set a completely custom domain, you can provide it as an array of values with this option.
206 | The array of values will be passed directly into the domain of the radius scale before rendering.
207 |
208 | #### colorRange
209 | Default: [ '#f7fbff', '#08306b' ] - Sets the range of the color scale used to fill the hexbins on the layer.
210 |
211 | #### radiusRange
212 | Default: [ 4, 12 ] - Sets the range of the radius scale used to size the hexbins on the layer.
213 |
214 | #### pointerEvents
215 | Default: 'all' - This value is passed directly to an element-level css style for ```pointer-events```.
216 |
217 | You should only modify this config option if you want to change the mouse event behavior on hexbins.
218 | This will modify when the events are propagated based on the visibility state and/or part of the hexbin being hovered.
219 |
220 |
221 | ### L.HexbinLayer
222 |
223 | #### hexbinLayer.data(value?: any[])
224 | Setter/getter for the data bound to the hexbin layer.
225 | The default data schema for the hexin layer is:
226 |
227 | ```[ [ lng1, lat1 ], [ lng2, lat2 ], [ lng3, lat3 ]... [ lngN, latN ] ]```
228 |
229 | Where the hexbin size is fixed at the radius and the color is linearly scaled and based on the bin count (the number of points contained in the bin).
230 |
231 |
232 | #### hexbinLayer.redraw()
233 | Triggers a redraw of the hexbin layer.
234 | You should only need to use this function if you are modifying several aspects of the layer.
235 | The only function in the API that automatically redraws is ```.data()```
236 |
237 |
238 | #### hexbinLayer.radius(value?: number)
239 | Setter/getter for the radius configuration option.
240 | Radius of the hexagon grid cells in pixels.
241 |
242 | This value should be a positive number.
243 | This radius controls the radius of the hexagons used to bin the data but not necessarily to draw each individual hexbin.
244 |
245 |
246 | #### hexbinLayer.opacity(value?: number)
247 | Setter/getter for the opacity configuration option.
248 | The opacity of the visible hexagons.
249 |
250 | This value should be a number between 0 and 1.
251 | Since we are transitioning opacity as part of d3 rendering the hexbins, this is not currently controlled by CSS.
252 | Future iterations may make this purely CSS based with the transitions applied to groups.
253 |
254 |
255 | #### hexbinLayer.duration(value?: number)
256 | Setter/getter for the durations configuration option. The millisecond duration of d3 transitions between states.
257 | This value should be a non-negative number.
258 | A value of 0 means that transitions will be instantaneous.
259 |
260 | *Note:* The transition duration should be set to a value lower than the minimum refresh interval of your data.
261 | What this means is that if you are going to be updating the data for the hexbin layer every 100 ms, you should keep this duration at a value of less than 100ms.
262 | The consequence of not doing this is that hexbins will not fully complete their transitions in between changes.
263 |
264 |
265 | #### hexbinLayer.colorScaleExtent(value?: [ number, number ])
266 | Setter/getter for the colorScaleExtent configuration option.
267 | This is used to override the derived extent of the color values and is specified as a tuple of the form [ min: number, max: number ].
268 | A value of ```undefined`` for either min or max indicates that the derived value should be retained.
269 |
270 | What this means is we derive the color value extent of the data (the min/max values in the data array) as an array of the form [ min, max ].
271 | Once we have that tuple, we override those values with the values provided by this config option.
272 | For example, if the derived min/max is [5, 102] and ```colorScaleExtent``` is [ 1, undefined ], the resulting extent used as the domain of the colorScale will be [ 1, 102 ].
273 | This setting is useful when you want to be explicit about the domain of values for the hexbins.
274 | For example, when you want consistent color scales between multiple maps or within the same map.
275 |
276 |
277 | #### hexbinLayer.radiusScaleExtent(value?: [ number, number ])
278 | Setter/getter for the radiusScaleExtent configuration option.
279 | This is the same exact configuration option as ```colorScaleExtent```, only applied to the radius extent.
280 |
281 |
282 | #### hexbinLayer.colorRange(value?: [ number, number ])
283 | Setter/getter for the colorRange configuration option.
284 | This value is used to specify the range of the color scale used to determine the fill colors of the hexbins.
285 |
286 | There are a lot of different ways you can specify the color range.
287 | One option is monotone: ```[ '#f7fbff', '#f7fbff' ]```.
288 | The most common option is a linear transition between two colors: ```[ '#f7fbff', '#08306b' ]```
289 | You can also create divering and discrete color scales by providing more than two values (see the examples for details).
290 |
291 |
292 | #### hexbinLayer.radiusRange(value?: [ number, number ])
293 | Setter/getter for the radiusRange configuration option.
294 | This value is used to specify the range of the radius scale used to size the drawn hexbins.
295 | This is relevant if you are providing a custom ```radiusValue``` function and want to specify the minimum and maximum drawn hexbin size.
296 |
297 | *Note:* Overriding this value will have no effect unless you provide a custom ```radiusValue``` function.
298 |
299 |
300 | #### hexbinLayer.colorScale(value?: d3.scale)
301 | Default: d3.scaleLinear - Setter/getter for the d3 scale used to map the color of each hexbin from the color value.
302 | If you override the scale, the color range will be ignored.
303 |
304 |
305 | #### hexbinLayer.radiusScale(value?: d3.scale)
306 | Default: d3.scaleLinear - Setter/getter for the d3 scale used to map the radius of each hexbin from the radius value.
307 | If you override the scale, the radius range will be ignored.
308 |
309 |
310 | #### hexbinLayer.lng(value?: function(d, i) {})
311 | Default: function(d) { return d[0]; } - Setter/getter for the function used to derive the value of the longitude for each object in the data array.
312 |
313 |
314 | #### hexbinLayer.lat(value?: function(d, i) {})
315 | Default: function(d) { return d[1]; } - Setter/getter for the function used to derive the value of the latitude for each object in the data array.
316 |
317 |
318 | #### hexbinLayer.colorValue(value?: function(d, i) {})
319 | Default: function(d) { return d.length; } - Setter/getter for the function used to derive the value of the color for each object in the data array.
320 |
321 |
322 | #### hexbinLayer.radiusValue(value?: function(d, i) {})
323 | Default: function(d) { return 1; } - Setter/getter for the function used to derive the value of the radius for each object in the data array.
324 |
325 |
326 | #### hexbinLayer.fill(value?: function(d, i) {})
327 | Setter/getter for the function used to derive the fill for each hexbin given the object generated by the d3 hexbin layout.
328 | The default fill function will simply map to the colorScale, but use 'none' when there is an undefined or null value.
329 |
330 |
331 | #### hexbinLayer.dispatch()
332 | Getter for the d3 dispatch object that exposes mouse events for the hexbins.
333 |
334 | Example:
335 | ```js
336 | hexLayer.dispatch()
337 | .on('mouseover', function(d, i) {
338 | console.log({ type: 'mouseover', event: d, index: i, context: this });
339 | })
340 | .on('mouseout', function(d, i) {
341 | console.log({ type: 'mouseout', event: d, index: i, context: this });
342 | })
343 | .on('click', function(d, i) {
344 | console.log({ type: 'click', event: d, index: i, context: this });
345 | });
346 | ```
347 |
348 | #### hexbinLayer.hoverHandler()
349 | Default: None - Setter/getter for the hover behavior.
350 |
351 | Hover handlers help you customize hexbin hover behavior.
352 | Examples include growing the size of the hexbin in various ways or showing a tooltip.
353 | If the hover handlers don't do what you want, you can always handle events yourself or implement your own hover handler.
354 | For more details, see the section on hover handlers below.
355 |
356 |
357 | ### L.HexbinHoverHandler
358 | All handlers are under the ```L.HexbinHoverHandler``` namespace.
359 |
360 | Handlers are created as follows:
361 |
362 | ```js
363 | L.HexbinHoverHandler.ResizeFill(options)
364 | ```
365 |
366 | Here's a basic example:
367 | ```js
368 | // Create a hexbin layer where hexbins that are hovered will grow from their
369 | // current radius up to the maximum radius (in this case 11)
370 | var hexLayer = L.hexbinLayer({ duration: 400, radiusRange: [ 5, 11 ] })
371 | .radiusValue(function(d) { return d.length; })
372 | .hoverHandler(L.HexbinHoverHandler.resizeFill());
373 | ```
374 |
375 | You can combine hover handlers with CSS to achieve interesting effects.
376 | The above hover handler combined with the below CSS will grow hexbins on hover using a smooth animation
377 | and will change the stroke to orange.
378 |
379 | ```css
380 | .hexbin-container:hover .hexbin-hexagon {
381 | transition: 200ms;
382 | stroke: orange;
383 | stroke-width: 1px;
384 | stroke-opacity: 1;
385 | }
386 | ```
387 |
388 |
389 | There are several provided hover handlers and they each may take options. They are described below.
390 |
391 | #### HoverHandler.tooltip(options)
392 | Shows a basic tooltip centered above the hexbin.
393 |
394 | Options:
395 | * **tooltipContent** - function(d) { return 'tooltip content here'; }
396 |
397 |
398 | #### HoverHandler.resizeFill()
399 | Resize the hovered hexagon to fill the current hexbin.
400 |
401 | No options required.
402 |
403 | #### HoverHandler.resizeScale(options)
404 | Resize the hovered hexagon by scaling it to be a percentage larger than the maximum drawn hexagon radius.
405 |
406 | Options:
407 | * **radiusScale** - provides the scale factor by which to increase the radius of the hexbin. Example: ```radiusScale: 0.5``` will result in a hovered hexbin radius that is 50% larger than the maximum hexagon radius.
408 |
409 | #### HoverHandler.compound(options)
410 | Combine multiple hover handlers.
411 |
412 | Options:
413 | * **handlers** - Array of hover handlers to combine.
414 |
415 | #### Customizing your own Hover Handler
416 | If you want to implement (or contribute) your own hover handler, the interface is pretty simple:
417 |
418 | ```js
419 | L.HexbinHoverHandler.myHoverHandler = function() {
420 |
421 | // return the handler instance
422 | return {
423 | mouseover: function (hexLayer, data) {
424 | // hexLayer - reference to the L.HexbinLayer instance
425 | // data - reference to the data bound to the hovered hexbin
426 | // this - D3 wrapped DOM element for hovered hexbin
427 | },
428 | mouseout: function (hexLayer, data) {}
429 | };
430 |
431 | };
432 | ```
433 |
434 | ## Pings API
435 |
436 | ### L.pingLayer(options?: {}): L.PingLayer
437 | Create a Leaflet map layer for visualizing transient event data using animated expanding circles.
438 |
439 | ```js
440 | var pingLayer = L.pingLayer().addTo(map);
441 | ```
442 |
443 | ### options
444 | Set of options for customizing the appearance/behavior of the ping layer.
445 |
446 | Example:
447 |
448 | ```js
449 | var options = {
450 | duration: 800,
451 | fps : 32,
452 | opacityRange: [ 1, 0 ],
453 | radiusRange: [ 5, 12 ]
454 | };
455 | ```
456 |
457 | #### duration
458 | Default: 800 - Sets the transition duration for the ping layer (see below for details).
459 |
460 | #### fps
461 | Default: 32 - Sets the target framerate for the ping animation (see below for details).
462 |
463 | #### opacityRange
464 | Default: [ 1, 0 ] - Sets the range of the opacity scale used to fade out the pings as they age (see below for details).
465 |
466 | #### radiusRange
467 | Default: [ 3, 15 ] - Sets the range of the radius scale used to size the pings as they age (see below for details).
468 |
469 |
470 | ### L.PingLayer
471 |
472 | #### pingLayer.ping(value: {})
473 | Submit a ping to the layer.
474 | The default data schema for the ping layer is:
475 |
476 | ```[ [ lng1, lat1 ], [ lng2, lat2 ], [ lng3, lat3 ]... [ lngN, latN ] ]```
477 |
478 | Where the ping radius scale factor is fixed at 1.
479 |
480 |
481 | #### pingLayer.duration(value?: number)
482 | Setter/getter for the durations configuration option.
483 | The millisecond duration of each ping's lifecycle.
484 |
485 | This value should be a non-negative number.
486 | The pings will grow from their initial size/opacity to their final size/opacity over this period of time.
487 | After this duration, the pings are removed from the map.
488 |
489 |
490 | #### pingLayer.fps(value?: number)
491 | Setter/getter for the fps configuration option.
492 | The animation loop will limit DOM changes to this frequency in order to reduce the impact to the CPU.
493 |
494 |
495 | #### pingLayer.radiusRange(value?: [ number, number ])
496 | Setter/getter for the radiusRange configuration option.
497 | The start/end radius applied during each ping's lifecycle.
498 |
499 | This value should be a tuple of size two.
500 | The pings will start at a pixel radius equal to the first number in the tuple and animate to the second number in the tuple.
501 |
502 |
503 | #### pingLayer.opacityRange(value?: [ number, number ])
504 | Setter/getter for the opacityRange configuration option.
505 | The start/end opacity state applied during each ping's lifecycle.
506 |
507 | This value should be a tuple of size two.
508 | The pings will start at an opacity equal to the first number in the tuple and animate to the second number in the tuple.
509 |
510 |
511 | #### pingLayer.radiusScale(value?: d3.scale)
512 | Default: d3.scalePow().exponent(0.35) - Setter/getter for the scale used to determine the radius during the ping lifecycle.
513 | If you override the scale, the radius range will be ignored.
514 |
515 |
516 | #### pingLayer.opacityScale(value?: d3.scale)
517 | Default: d3.scaleLinear() - Setter/getter for the scale used to determine the opacity during the ping lifecycle.
518 | If you override the scale, the opacity range will be ignored.
519 |
520 | #### pingLayer.radiusScaleFactor(function(d) {})
521 | Default: function(d) { return 1; } - Setter/getter for the scale factor applied to the radius of each ping.
522 | This can be used to differentiate different events by size.
523 |
524 |
525 | #### pingLayer.lng(value?: function(d) {})
526 | Default: function(d) { return d[0]; } - Setter/getter for the function used to derive the value of the longitude for each object in the data array.
527 |
528 |
529 | #### pingLayer.lat(value?: function(d) {})
530 | Default: function(d) { return d[1]; } - Setter/getter for the function used to derive the value of the latitude for each object in the data array.
531 |
532 |
533 | #### pingLayer.data()
534 | Getter for the set of currently alive pings.
535 |
536 |
537 | #### pingLayer.getActualFps()
538 | Getter for the actual fps (based on the actual time between the last two animation frames).
539 |
540 |
541 | ## Changelog
542 |
543 | ### Version 6.x
544 | - Upgrade to d3 v7
545 |
546 | ### Version 5.x
547 | Skipped
548 |
549 | ### Version 4.x
550 |
551 | #### 4.4.0
552 | - Minor version updates for d3 and leaflet.
553 |
554 | #### 4.2.0
555 | - Corrected the algorithm that filters out hexbins to avoid drawing those that fall outside of the visible bounds of the map.
556 |
557 | #### 4.1.0
558 | - Added Hexbin Layer options for colorDomain and radiusDomain. See README docs for details.
559 |
560 | #### 4.0.0
561 | - D3 v5: We now support D3 v5. Only minor changes were required.
562 | - Fix for Leaflet > 1.2 Mixins Deprecation Warning: Updated the events include reference to remove the warning about using L.Mixins.Events
563 | - Fixes for Hover Handlers Data and Tooltip positions: See Issue #45 and #50, thanks @ninio for finding these.
564 | - Migrated to npm run based build: Not really an external facing thing, but matters if you're trying to build the library.
565 |
566 |
567 | ### Version 3.x
568 |
569 | #### Dropping Support for Leaflet 0.7.x
570 | We added some functionality that made it hard to backward support Leaflet 0.7.x.
571 | You can continue to use our 2.x release for Leaflet 0.7.x support, but it's unlikely that branch will see any further development/releases.
572 | This is the primary reason for increasing the major version as this is the only change that is not backwards compatible.
573 |
574 | #### Hexbins/Pings now Zoom with Map Before Redrawing
575 | We switched the HebinLayer to extend the built-in Leaflet SVG layer.
576 | This provides a bunch of advantages, including that the SVG layer is zoom-transformed with the other layers on the map.
577 | This allowed us to leave the hexbins on the map until the zoom animation is complete, at which point the hexbin grid is recalculated and redrawn.
578 |
579 | #### Automatic Filtering of Off-Map Hexbins
580 | We updated the Hexbin layer code to automatically filter out points that fall outside of the visible bounds of the map.
581 | This _dramatically_ improves performance at high zoom levels where we used to draw A LOT of paths off the map for no reason.
582 |
583 | #### Built-in Support for Tooltips and Other Hover Events
584 | While you could always manually manage a tooltip or some kind of hexbin hover event, we've added some code to make it easier.
585 | Now, you can pretty easily enable some built-in tooltip/highlight behavior or implement your own.
586 | See the API docs on HoverHandlers and the advanced hexbin example for details.
587 |
588 |
589 |
590 | ### Version 2.x
591 |
592 | #### Lots of API changes
593 | Read through the API changes.
594 | A lot of things were moved from config options to being configurable via chained function call.
595 |
596 | #### You can now bind data to the radius of Hexbins!
597 | You can now provide a radius value function to map a dimension of your data to the size of each hexbin.
598 |
599 | #### We changed the Hexbin event dispatch
600 | For Hexbins, we've changed the way that events are handled. Previously, you provided callback methods.
601 | Now, we expose a d3 dispatch object:
602 |
603 | ```js
604 | ...
605 | var hexLayer = L.hexbinLayer(options).addTo(map);
606 |
607 | // Set up events
608 | hexLayer.dispatch()
609 | .on('mouseover', function(d, i) { })
610 | .on('mouseout', function(d, i) { })
611 | .on('click', function(d, i) { });
612 | ```
613 |
614 | #### Pings now track the map when panning!
615 | We've changed pings so that they track the map when as it pans.
616 | The pan changes are applied immediately even when manually setting a low fps.
617 |
618 | #### You can now size pings independently using a scale factor callback function
619 | We've added a configurable option (pingLayer.radiusScaleFactor(...)) to provide a function that returns a data element-specific scale factor for the ping radius.
620 |
621 |
622 | ## Contribute
623 | PRs accepted. If you are part of Asymmetrik, please make contributions on feature branches off of the ```develop``` branch. If you are outside of Asymmetrik, please fork our repo to make contributions.
624 |
625 |
626 | ## License
627 | See LICENSE in repository for details.
628 |
629 |
630 | ## Credits
631 | The hexbin portion of this plugin was based on [the work of Steven Hall](http://www.delimited.io/blog/2013/12/1/hexbins-with-d3-and-leaflet-maps). Check out his other awesome work at [Delimited](http://www.delimited.io/)
632 |
633 | D3.js was created by the legendary [Mike Bostock](https://github.com/mbostock).
634 |
635 | [Leaflet](http://leafletjs.com/) is maintained by [lots of cool people](https://github.com/Leaflet/Leaflet/graphs/contributors).
636 |
637 |
638 | [travis-url]: https://travis-ci.org/Asymmetrik/leaflet-d3/
639 | [travis-image]: https://travis-ci.org/Asymmetrik/leaflet-d3.svg
640 |
--------------------------------------------------------------------------------
/examples/hexbins/advanced.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Demonstrates advanced functionality
38 | 39 | 40 | 41 | 42 |