CHANGES.md 94.5 KB
Newer Older
Mike Bostock's avatar
Mike Bostock committed
1001
```js
Mike Bostock's avatar
Mike Bostock committed
1002
d3.timeHour.count(d3.timeWeek(now), now); // 64
Mike Bostock's avatar
Mike Bostock committed
1003
```
Mike Bostock's avatar
Mike Bostock committed
1004

Mike Bostock's avatar
Mike Bostock committed
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
Here are all the equivalences from 3.x to 4.0:

* d3.time.dayOfYear ↦ [d3.timeDay](https://github.com/d3/d3-time#timeDay).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.sundayOfYear ↦ [d3.timeSunday](https://github.com/d3/d3-time#timeSunday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.mondayOfYear ↦ [d3.timeMonday](https://github.com/d3/d3-time#timeMonday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.tuesdayOfYear ↦ [d3.timeTuesday](https://github.com/d3/d3-time#timeTuesday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.wednesdayOfYear ↦ [d3.timeWednesday](https://github.com/d3/d3-time#timeWednesday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.thursdayOfYear ↦ [d3.timeThursday](https://github.com/d3/d3-time#timeThursday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.fridayOfYear ↦ [d3.timeFriday](https://github.com/d3/d3-time#timeFriday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.saturdayOfYear ↦ [d3.timeSaturday](https://github.com/d3/d3-time#timeSaturday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.weekOfYear ↦ [d3.timeWeek](https://github.com/d3/d3-time#timeWeek).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.dayOfYear.utc ↦ [d3.utcDay](https://github.com/d3/d3-time#utcDay).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.sundayOfYear.utc ↦ [d3.utcSunday](https://github.com/d3/d3-time#utcSunday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.mondayOfYear.utc ↦ [d3.utcMonday](https://github.com/d3/d3-time#utcMonday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.tuesdayOfYear.utc ↦ [d3.utcTuesday](https://github.com/d3/d3-time#utcTuesday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.wednesdayOfYear.utc ↦ [d3.utcWednesday](https://github.com/d3/d3-time#utcWednesday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.thursdayOfYear.utc ↦ [d3.utcThursday](https://github.com/d3/d3-time#utcThursday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.fridayOfYear.utc ↦ [d3.utcFriday](https://github.com/d3/d3-time#utcFriday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.saturdayOfYear.utc ↦ [d3.utcSaturday](https://github.com/d3/d3-time#utcSaturday).[count](https://github.com/d3/d3-time#interval_count)
* d3.time.weekOfYear.utc ↦ [d3.utcWeek](https://github.com/d3/d3-time#utcWeek).[count](https://github.com/d3/d3-time#interval_count)

Mike Bostock's avatar
Mike Bostock committed
1026
D3 4.0 now also lets you define custom time intervals using [d3.timeInterval](https://github.com/d3/d3-time#timeInterval). The [d3.timeYear](https://github.com/d3/d3-time#timeYear), [d3.utcYear](https://github.com/d3/d3-time#utcYear), [d3.timeMillisecond](https://github.com/d3/d3-time#timeMillisecond) and [d3.utcMillisecond](https://github.com/d3/d3-time#utcMillisecond) intervals have optimized implementations of [*interval*.every](https://github.com/d3/d3-time#interval_every), which is necessary to generate time ticks for very large or very small domains efficiently. More generally, the performance of time intervals has been improved, and time intervals now do a better job with respect to daylight savings in various locales.
Mike Bostock's avatar
Mike Bostock committed
1027

Mike Bostock's avatar
Mike Bostock committed
1028
## [Timers (d3-timer)](https://github.com/d3/d3-timer/blob/master/README.md)
Mike Bostock's avatar
Mike Bostock committed
1029

Mike Bostock's avatar
Mike Bostock committed
1030
In D3 3.x, the only way to stop a timer was for its callback to return true. For example, this timer stops after one second:
Mike Bostock's avatar
Mike Bostock committed
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

```js
d3.timer(function(elapsed) {
  console.log(elapsed);
  return elapsed >= 1000;
});
```

In 4.0, use [*timer*.stop](https://github.com/d3/d3-timer#timer_stop) instead:

```js
var t = d3.timer(function(elapsed) {
  console.log(elapsed);
  if (elapsed >= 1000) {
    t.stop();
  }
});
```

Mike Bostock's avatar
Mike Bostock committed
1050
The primary benefit of *timer*.stop is that timers are not required to self-terminate: they can be stopped externally, allowing for the immediate and synchronous disposal of associated resources, and the separation of concerns. The above is equivalent to:
Mike Bostock's avatar
Mike Bostock committed
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

```js
var t = d3.timer(function(elapsed) {
  console.log(elapsed);
});

d3.timeout(function() {
  t.stop();
}, 1000);
```

Mike Bostock's avatar
Mike Bostock committed
1062
This improvement extends to [d3-transition](#transitions-d3-transition): now when a transition is interrupted, its resources are immediately freed rather than having to wait for transition to start.
Mike Bostock's avatar
Mike Bostock committed
1063

Mike Bostock's avatar
Mike Bostock committed
1064
4.0 also introduces a new [*timer*.restart](https://github.com/d3/d3-timer#timer_restart) method for restarting timers, for replacing the callback of a running timer, or for changing its delay or reference time. Unlike *timer*.stop followed by [d3.timer](https://github.com/d3/d3-timer#timer), *timer*.restart maintains the invocation priority of an existing timer: it guarantees that the order of invocation of active timers remains the same.
Mike Bostock's avatar
Mike Bostock committed
1065
1066
1067
1068
1069
1070
1071
1072
1073

Some usage patterns in D3 3.x could cause the browser to hang when a background page returned to the foreground. For example, the following code schedules a transition every second:

```js
setInterval(function() {
  d3.selectAll("div").transition().call(someAnimation); // BAD
}, 1000);
```

Mike Bostock's avatar
Mike Bostock committed
1074
If such code runs in the background for hours, thousands of queued transitions will try to run simultaneously when the page is foregrounded. D3 4.0 avoids this hang by freezing time in the background: when a page is in the background, time does not advance, and so no queue of timers accumulates to run when the page returns to the foreground. Use d3.timer instead of transitions to schedule a long-running animation, or use [d3.timeout](https://github.com/d3/d3-timer#timeout) and [d3.interval](https://github.com/d3/d3-timer#interval) in place of setTimeout and setInterval to prevent transitions from being queued in the background:
Mike Bostock's avatar
Mike Bostock committed
1075
1076
1077
1078
1079
1080
1081

```js
d3.interval(function() {
  d3.selectAll("div").transition().call(someAnimation); // GOOD
}, 1000);
```

Mike Bostock's avatar
Mike Bostock committed
1082
By freezing time in the background, timers are effectively “unaware” of being backgrounded. It’s like nothing happened! 4.0 also now uses high-precision time ([performance.now](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)) where available; the current time is available as [d3.now](https://github.com/d3/d3-timer#now).
Mike Bostock's avatar
Mike Bostock committed
1083

Mike Bostock's avatar
Mike Bostock committed
1084
The d3.timer.flush method has been renamed to [d3.timerFlush](https://github.com/d3/d3-timer#timerFlush).
Mike Bostock's avatar
Mike Bostock committed
1085

Mike Bostock's avatar
Mike Bostock committed
1086
## [Transitions (d3-transition)](https://github.com/d3/d3-transition/blob/master/README.md)
Mike Bostock's avatar
Mike Bostock committed
1087

Mike Bostock's avatar
Mike Bostock committed
1088
1089
TODO

Mike Bostock's avatar
Mike Bostock committed
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
* transitions are immutable, too; *transition*.merge
* *transition*.each ↦ *transition*.on
* *transition*.each is now the same as *selection*.each
* new d3.active for chaining transitions / modifying in-progress transitions
* new *selection*.transition(*transition*); searches ancestors
* new d3.interrupt
* change *transition*.transition semantics in regards to *transition*.delay
* strict state machine to enforce when transitions can be modified; more robust
* enforces *t* = 1 on end
* functions passed to transition methods take the same standard arguments as selections
* optimize transitions to re-use tweens and interpolators to improve performance!
* *transition*.attrTween gets standard arguments (not current attribute value)
* *transition*.styleTween gets standard arguments (not current style value)
* call *transition*.{tween,attrTween,styleTween} in getter mode
* uses optimized interpolator rather than d3.interpolate
* fix *transition*.remove if multiple transition names are in use
* new *transition*.selection
Mike Bostock's avatar
Mike Bostock committed
1107
1108
1109
* changed *transition*.ease to always take an easing function, not a name
* see also d3-timer, d3-ease, d3-interpolate
* in particular note that transitions are now frozen in the background! and there’s d3.timeout, d3.interval
Mike Bostock's avatar
Mike Bostock committed
1110

Mike Bostock's avatar
Mike Bostock committed
1111
## [Voronoi Diagrams (d3-voronoi)](https://github.com/d3/d3-voronoi/blob/master/README.md)
Mike Bostock's avatar
Mike Bostock committed
1112

Mike Bostock's avatar
Mike Bostock committed
1113
The d3.geom.voronoi method has been renamed to [d3.voronoi](https://github.com/d3/d3-voronoi#voronoi), and the *voronoi*.clipExtent method has been renamed to [*voronoi*.extent](https://github.com/d3/d3-voronoi#voronoi_extent). The undocumented *polygon*.point property in 3.x, which is the element in the input *data* corresponding to the polygon, has been renamed to *polygon*.data.
Mike Bostock's avatar
Mike Bostock committed
1114

Mike Bostock's avatar
Mike Bostock committed
1115
Calling [*voronoi*](https://github.com/d3/d3-voronoi#_voronoi) now returns the full [Voronoi diagram](https://github.com/d3/d3-voronoi#voronoi-diagrams), which includes topological information: each Voronoi edge exposes *edge*.left and *edge*.right specifying the sites on either side of the edge, and each Voronoi cell is defined an array of these edges and a corresponding site. The Voronoi diagram can be used to efficiently compute both the Voronoi and Delaunay tessellations for a set of points: [*diagram*.polygons](https://github.com/d3/d3-voronoi#diagram_polygons), [*diagram*.links](https://github.com/d3/d3-voronoi#diagram_links), and [*diagram*.triangles](https://github.com/d3/d3-voronoi#diagram_triangles). The new topology is also useful in conjunction with TopoJSON; see the [Voronoi topology example](http://bl.ocks.org/mbostock/cd52a201d7694eb9d890).
Mike Bostock's avatar
Mike Bostock committed
1116
1117

The [*voronoi*.polygons](https://github.com/d3/d3-voronoi#voronoi_polygons) and [*diagram*.polygons](https://github.com/d3/d3-voronoi#diagram_polygons) now require an [extent](https://github.com/d3/d3-voronoi#voronoi_extent); there is no longer an implicit extent of ±1e6. The [*voronoi*.links](https://github.com/d3/d3-voronoi#voronoi_links), [*voronoi*.triangles](https://github.com/d3/d3-voronoi#voronoi_triangles), [*diagram*.links](https://github.com/d3/d3-voronoi#diagram_links) and [*diagram*.triangles](https://github.com/d3/d3-voronoi#diagram_triangles) are now affected by the clip extent: as the Delaunay is computed as the dual of the Voronoi, two sites are only linked if the clipped cells are touching. To compute the Delaunay triangulation without respect to clipping, set the extent to null.
Mike Bostock's avatar
Mike Bostock committed
1118

Mike Bostock's avatar
Mike Bostock committed
1119
The Voronoi generator finally has well-defined behavior for coincident vertices: the first of a set of coincident points has a defined cell, while the subsequent duplicate points have null cells. The returned array of polygons is sparse, so by using *array*.forEach or *array*.map, you can easily skip undefined cells. The Voronoi generator also now correctly handles the case where no cell edges intersect the extent.
Mike Bostock's avatar
Mike Bostock committed
1120

Mike Bostock's avatar
Mike Bostock committed
1121
## [Zooming (d3-zoom)](https://github.com/d3/d3-zoom/blob/master/README.md)
Mike Bostock's avatar
Mike Bostock committed
1122

Mike Bostock's avatar
Mike Bostock committed
1123
1124
1125
1126
1127
The zoom behavior d3.behavior.zoom has been renamed to d3.zoom. Zoom behaviors no longer store the active zoom transform (*i.e.*, the visible region; the scale and translate) internally. The zoom transform is now stored on any elements to which the zoom behavior has been applied. The zoom transform is available as *event*.transform within a zoom event or by calling [d3.zoomTransform](https://github.com/d3/d3-zoom#zoomTransform) on a given *element*. To zoom programmatically, use [*zoom*.transform](https://github.com/d3/d3-zoom#zoom_transform) with a given [selection](#selections-d3-selection) or [transition](#transitions-d3-transition); see the [zoom transitions example](http://bl.ocks.org/mbostock/b783fbb2e673561d214e09c7fb5cedee). The *zoom*.event method has been removed.

To make programmatic zooming easier, there are several new convenience methods on top of *zoom*.transform: [*zoom*.translateBy](https://github.com/d3/d3-zoom#zoom_translateBy), [*zoom*.scaleBy](https://github.com/d3/d3-zoom#zoom_scaleBy) and [*zoom*.scaleTo](https://github.com/d3/d3-zoom#zoom_scaleTo). There is also a new API for describing [zoom transforms](https://github.com/d3/d3-zoom#zoom-transforms). Zoom behaviors are no longer dependent on [scales](#scales-d3-scale), but you can use [*transform*.rescaleX](https://github.com/d3/d3-zoom#transform_rescaleX) or [*transform*.rescaleY](https://github.com/d3/d3-zoom#transform_rescaleY), [*transform*.invertX](https://github.com/d3/d3-zoom#transform_invertX) to transform a scale’s domain. 3.x’s *event*.scale is replaced with *event*.transform.k, and *event*.translate is replaced with *event*.transform.x and *event*.transform.y. The *zoom*.center method has been removed in favor of programmatic zooming.

The zoom behavior finally supports simple constraints on panning! The new [*zoom*.translateExtent](https://github.com/d3/d3-zoom#zoom_translateExtent) lets you define the viewable extent of the world: the currently-visible extent (the extent of the viewport, as defined by [*zoom*.extent](https://github.com/d3/d3-zoom#zoom_extent)) is always contained within the translate extent. The *zoom*.size method has been replaced by *zoom*.extent, and the default behavior is now smarter: it defaults to the extent of the zoom behavior’s owner element, rather than being hardcoded to 960×500. (This also improves the default path chosen during smooth zoom transitions!)
Mike Bostock's avatar
Mike Bostock committed
1128

Mike Bostock's avatar
Mike Bostock committed
1129
The zoom behavior’s interaction has also improved. It now correctly handles concurrent wheeling and dragging, as well as concurrent touching and mousing. The zoom behavior now ignores wheel events at the limits of its scale extent, allowing you to scroll past a zoomable area. The *zoomstart* and *zoomend* events have been renamed *start* and *end*. By default, zoom behaviors now ignore right-clicks intended for the context menu; use [*zoom*.filter](https://github.com/d3/d3-zoom#zoom_filter) to control which events are ignored. The zoom behavior also ignores emulated mouse events on iOS. The zoom behavior now consumes handled events, making it easier to combine with other interactive behaviors such as [dragging](#dragging-d3-drag).