├── LICENSE.md ├── README.md ├── index.html ├── minard.html ├── pathdemo.html └── pathlayout.js /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014, 2015 Benjamin Schmidt 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 13 | all 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 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | D3 Trail layout 2 | ================ 3 | 4 | This is a layout function for creating paths in D3 where (unlike the native d3.svg.line() element) you need to apply specific aesthetics to each element of the line. 5 | 6 | Demos 7 | ====== 8 | 9 | The original use case was trails with decaying opacity to represent movement: here's a sample image: (interactive versions forthcoming). 10 | 11 | For a classical example, see how variable-width, staggered entry lines [make it possible to reproduce Minard's famous Napoleon map in motion](http://benschmidt.org/D3-trail/minard.html). Here's a screenshot, although the whole point is the animation.  12 | 13 | 14 | For a more straightforward demo of staggered entry ([see this demo of a random walk](http://benschmidt.org/D3-trail/pathdemo.html)). 15 | 16 | 17 | Features include: 18 | 19 | 1. Controls to define multiple groups of simultaneous lines by setting `grouping`. 20 | 2. Options to return data either with `x1`,`x2`,`y1`, and `y2` elements to use with svg lines *or* with a `coordinates` object to use with geoprojections by setting `coordType`. 21 | 3. Inbuilt methods to easily define `opacity` in the data as an evaporating trail in time like the frames in [my maps of shipping routes](http://sappingattention.blogspot.com/2012/04/visualizing-ocean-shipping.html). 22 | 4. Control over sorting. 23 | 5. Access to both points in the bound data, so that appearance of a segment can be defined by data about the destination point, the origin, or some interaction of them. 24 | 25 | 26 | Usage 27 | ===== 28 | 29 | You instantiate it by calling the function: once parameters are set, run the `layout()` method to get values back. 30 | 31 | 32 | A bare bones example might be: 33 | 34 | ``` {js} 35 | trail = d3.layout.trail().coordType('xy') 36 | 37 | new = trail.data(whatever).layout() 38 | 39 | paths = svg.selectAll("line").data(new) 40 | 41 | paths.enter() 42 | .append('line') 43 | .attr("x1",function(d) {return d.x1}) 44 | .attr("y1",function(d) {return d.y1}) 45 | .attr("y2",function(d) {return d.y2}) 46 | .attr("x2",function(d) {return d.x2}) 47 | 48 | ``` 49 | 50 | API 51 | === 52 | 53 | Creation 54 | -------- 55 | 56 | Create a trail object 57 | ``` 58 | trail = d3.layout.trail() 59 | ``` 60 | 61 | trail.data() 62 | ----------- 63 | 64 | Set (or with no arguments, return) the data to be plotted. Each object in the return values will correspond to two consecutive points in this array. 65 | 66 | 67 | trail.positioner() 68 | ------------------- 69 | 70 | Set (or with no arguments, return) a function used to specify the x and y values for each **point**. 71 | 72 | By default, it returns simply [x,y] for the data: 73 | 74 | ``` 75 | positioner = function(datum) { return [datum.x,datum.y] } 76 | ``` 77 | 78 | You can also drop in any map projection as the positioner. 79 | 80 | 81 | trail.coordType() 82 | ----------------- 83 | 84 | Set (or with no arguments, return) the format of positions for the return values. Can be either 85 | 86 | 1. `"xy"`, in which case you'll get `x1`,`x2`,`y1`, and `y2` elements suitable for use with svg lines, or 87 | 2. `"coordinates"`, in which case the objection will get a `coordinates` element consisting of an array of points so you can simply create a d3.geo.path() element. (Useful if you want to preserve great circle arcs for your paths, for instance; in this case the positioner should return lat and lon, not the projected values, so you don't project them twice.) 88 | 89 | 90 | trail.grouping() 91 | ---------------- 92 | 93 | Set (or with no arguments, return) the grouping 94 | 95 | 96 | 97 | trail.sort() 98 | ------------- 99 | 100 | Set (or with no arguments, return) the function used to order the points. 101 | 102 | If not set, points will be ordered in the direction they went in. 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | And then set the parameters 111 | 112 | 113 | 114 | 115 | Time-specific elements 116 | ----------------------- 117 | 118 | ### trail.time() 119 | 120 | Set (or with no arguments, return) a function that returns how to access the time data. (Must be numeric: dates not yet supported). 121 | 122 | ### trail.currentTime() 123 | 124 | Set (or with no arguments, return) the current time (ie, that for which opacity should be 1); all times after this will be dropped from the returned set. 125 | 126 | ### trail.decayRange() 127 | 128 | Set (or with no arguments, return) the number of time units to be displayed: The opacity of segments ending at `trail.currentTime() - trail.decayRange()` will be zero, and all earlier segments will not be displayed 129 | 130 | 131 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /minard.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |171 | The "grouping" elements are being used here to draw several 172 | different paths (by color) simultaneously, and set their width by 173 | the size of Napoleon's army. (From a maximum of 340,000 to an end 174 | value of 4,000: no scale displayed for concision.) Data is taken 175 | from here. 176 | 177 |
This is a reimplementation, not a reimagination, 178 | of Minard's diagram. The only significant addition is the temporal 179 | placement of elements. This helps clarify the most confusing elements of 180 | the original (such as the direction of the temperature graph). All 181 | animation timing is done by purely by D3 transitions. This frees 182 | up color from representing the army's direction: 183 | here the different branches of the French force each have their own 184 | color. Even these minor improvements can only mean, though, that 185 | this has now displaced Minard's original as greatest statistical graphic ever 186 | created. (Unless you really miss the original rivers, I guess.) 187 | 188 |