CHANGES.md 108 KB
Newer Older
Mike Bostock's avatar
Mike Bostock committed
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
Pursuant to the great namespace flattening, the local time intervals have been renamed:

* ADDED ↦ [d3.timeMillisecond](https://github.com/d3/d3-time#timeMillisecond)
* d3.time.second ↦ [d3.timeSecond](https://github.com/d3/d3-time#timeSecond)
* d3.time.minute ↦ [d3.timeMinute](https://github.com/d3/d3-time#timeMinute)
* d3.time.hour ↦ [d3.timeHour](https://github.com/d3/d3-time#timeHour)
* d3.time.day ↦ [d3.timeDay](https://github.com/d3/d3-time#timeDay)
* d3.time.sunday ↦ [d3.timeSunday](https://github.com/d3/d3-time#timeSunday)
* d3.time.monday ↦ [d3.timeMonday](https://github.com/d3/d3-time#timeMonday)
* d3.time.tuesday ↦ [d3.timeTuesday](https://github.com/d3/d3-time#timeTuesday)
* d3.time.wednesday ↦ [d3.timeWednesday](https://github.com/d3/d3-time#timeWednesday)
* d3.time.thursday ↦ [d3.timeThursday](https://github.com/d3/d3-time#timeThursday)
* d3.time.friday ↦ [d3.timeFriday](https://github.com/d3/d3-time#timeFriday)
* d3.time.saturday ↦ [d3.timeSaturday](https://github.com/d3/d3-time#timeSaturday)
* d3.time.week ↦ [d3.timeWeek](https://github.com/d3/d3-time#timeWeek)
* d3.time.month ↦ [d3.timeMonth](https://github.com/d3/d3-time#timeMonth)
* d3.time.year ↦ [d3.timeYear](https://github.com/d3/d3-time#timeYear)

Mike Bostock's avatar
Mike Bostock committed
1019
The UTC time intervals have likewise been renamed:
Mike Bostock's avatar
Mike Bostock committed
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

* ADDED ↦ [d3.utcMillisecond](https://github.com/d3/d3-time#utcMillisecond)
* d3.time.second.utc ↦ [d3.utcSecond](https://github.com/d3/d3-time#utcSecond)
* d3.time.minute.utc ↦ [d3.utcMinute](https://github.com/d3/d3-time#utcMinute)
* d3.time.hour.utc ↦ [d3.utcHour](https://github.com/d3/d3-time#utcHour)
* d3.time.day.utc ↦ [d3.utcDay](https://github.com/d3/d3-time#utcDay)
* d3.time.sunday.utc ↦ [d3.utcSunday](https://github.com/d3/d3-time#utcSunday)
* d3.time.monday.utc ↦ [d3.utcMonday](https://github.com/d3/d3-time#utcMonday)
* d3.time.tuesday.utc ↦ [d3.utcTuesday](https://github.com/d3/d3-time#utcTuesday)
* d3.time.wednesday.utc ↦ [d3.utcWednesday](https://github.com/d3/d3-time#utcWednesday)
* d3.time.thursday.utc ↦ [d3.utcThursday](https://github.com/d3/d3-time#utcThursday)
* d3.time.friday.utc ↦ [d3.utcFriday](https://github.com/d3/d3-time#utcFriday)
* d3.time.saturday.utc ↦ [d3.utcSaturday](https://github.com/d3/d3-time#utcSaturday)
* d3.time.week.utc ↦ [d3.utcWeek](https://github.com/d3/d3-time#utcWeek)
* d3.time.month.utc ↦ [d3.utcMonth](https://github.com/d3/d3-time#utcMonth)
* d3.time.year.utc ↦ [d3.utcYear](https://github.com/d3/d3-time#utcYear)

Mike Bostock's avatar
Mike Bostock committed
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
The local time range aliases have been renamed:

* d3.time.seconds ↦ [d3.timeSeconds](https://github.com/d3/d3-time#timeSeconds)
* d3.time.minutes ↦ [d3.timeMinutes](https://github.com/d3/d3-time#timeMinutes)
* d3.time.hours ↦ [d3.timeHours](https://github.com/d3/d3-time#timeHours)
* d3.time.days ↦ [d3.timeDays](https://github.com/d3/d3-time#timeDays)
* d3.time.sundays ↦ [d3.timeSundays](https://github.com/d3/d3-time#timeSundays)
* d3.time.mondays ↦ [d3.timeMondays](https://github.com/d3/d3-time#timeMondays)
* d3.time.tuesdays ↦ [d3.timeTuesdays](https://github.com/d3/d3-time#timeTuesdays)
* d3.time.wednesdays ↦ [d3.timeWednesdays](https://github.com/d3/d3-time#timeWednesdays)
* d3.time.thursdays ↦ [d3.timeThursdays](https://github.com/d3/d3-time#timeThursdays)
* d3.time.fridays ↦ [d3.timeFridays](https://github.com/d3/d3-time#timeFridays)
* d3.time.saturdays ↦ [d3.timeSaturdays](https://github.com/d3/d3-time#timeSaturdays)
* d3.time.weeks ↦ [d3.timeWeeks](https://github.com/d3/d3-time#timeWeeks)
* d3.time.months ↦ [d3.timeMonths](https://github.com/d3/d3-time#timeMonths)
* d3.time.years ↦ [d3.timeYears](https://github.com/d3/d3-time#timeYears)

Mike Bostock's avatar
Mike Bostock committed
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
The UTC time range aliases have been renamed:

* d3.time.seconds.utc ↦ [d3.utcSeconds](https://github.com/d3/d3-time#utcSeconds)
* d3.time.minutes.utc ↦ [d3.utcMinutes](https://github.com/d3/d3-time#utcMinutes)
* d3.time.hours.utc ↦ [d3.utcHours](https://github.com/d3/d3-time#utcHours)
* d3.time.days.utc ↦ [d3.utcDays](https://github.com/d3/d3-time#utcDays)
* d3.time.sundays.utc ↦ [d3.utcSundays](https://github.com/d3/d3-time#utcSundays)
* d3.time.mondays.utc ↦ [d3.utcMondays](https://github.com/d3/d3-time#utcMondays)
* d3.time.tuesdays.utc ↦ [d3.utcTuesdays](https://github.com/d3/d3-time#utcTuesdays)
* d3.time.wednesdays.utc ↦ [d3.utcWednesdays](https://github.com/d3/d3-time#utcWednesdays)
* d3.time.thursdays.utc ↦ [d3.utcThursdays](https://github.com/d3/d3-time#utcThursdays)
* d3.time.fridays.utc ↦ [d3.utcFridays](https://github.com/d3/d3-time#utcFridays)
* d3.time.saturdays.utc ↦ [d3.utcSaturdays](https://github.com/d3/d3-time#utcSaturdays)
* d3.time.weeks.utc ↦ [d3.utcWeeks](https://github.com/d3/d3-time#utcWeeks)
* d3.time.months.utc ↦ [d3.utcMonths](https://github.com/d3/d3-time#utcMonths)
* d3.time.years.utc ↦ [d3.utcYears](https://github.com/d3/d3-time#utcYears)

Mike Bostock's avatar
Mike Bostock committed
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
The behavior of [*interval*.range](https://github.com/d3/d3-time#interval_range) (and the convenience aliases such as [d3.timeDays](https://github.com/d3/d3-time#timeDays)) has been changed when *step* is greater than one. Rather than filtering the returned dates using the field number, *interval*.range now behaves like [d3.range](https://github.com/d3/d3-array#range): it simply skips, returning every *step*th date. For example, the following code in 3.x returns only odd days of the month:

```js
d3.time.days(new Date(2016, 4, 28), new Date(2016, 5, 5), 2);
// [Sun May 29 2016 00:00:00 GMT-0700 (PDT),
//  Tue May 31 2016 00:00:00 GMT-0700 (PDT),
//  Wed Jun 01 2016 00:00:00 GMT-0700 (PDT),
//  Fri Jun 03 2016 00:00:00 GMT-0700 (PDT)]
```

Mike Bostock's avatar
Mike Bostock committed
1081
Note the returned array of dates does not start on the *start* date because May 28 is even. Also note that May 31 and June 1 are one day apart, not two! The behavior of d3.timeDays in 4.0 is probably closer to what you expect:
Mike Bostock's avatar
Mike Bostock committed
1082
1083
1084
1085
1086
1087
1088
1089
1090

```js
d3.timeDays(new Date(2016, 4, 28), new Date(2016, 5, 5), 2);
// [Sat May 28 2016 00:00:00 GMT-0700 (PDT),
//  Mon May 30 2016 00:00:00 GMT-0700 (PDT),
//  Wed Jun 01 2016 00:00:00 GMT-0700 (PDT),
//  Fri Jun 03 2016 00:00:00 GMT-0700 (PDT)]
```

Mike Bostock's avatar
Mike Bostock committed
1091
If you want a filtered view of a time interval (say to guarantee that two overlapping ranges are consistent, such as when generating [time scale ticks](https://github.com/d3/d3-scale#time_ticks)), you can use the new [*interval*.every](https://github.com/d3/d3-time#interval_every) method or its more general cousin [*interval*.filter](https://github.com/d3/d3-time#interval_filter):
Mike Bostock's avatar
Mike Bostock committed
1092
1093
1094
1095
1096
1097
1098
1099
1100

```js
d3.timeDay.every(2).range(new Date(2016, 4, 28), new Date(2016, 5, 5));
// [Sun May 29 2016 00:00:00 GMT-0700 (PDT),
//  Tue May 31 2016 00:00:00 GMT-0700 (PDT),
//  Wed Jun 01 2016 00:00:00 GMT-0700 (PDT),
//  Fri Jun 03 2016 00:00:00 GMT-0700 (PDT)]
```

Mike Bostock's avatar
Mike Bostock committed
1101
Time intervals now expose an [*interval*.count](https://github.com/d3/d3-time#interval_count) method for counting the number of interval boundaries after a *start* date and before or equal to an *end* date. This replaces d3.time.dayOfYear and related methods in 3.x. For example, this code in 3.x:
Mike Bostock's avatar
Mike Bostock committed
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120

```js
var now = new Date;
d3.time.dayOfYear(now); // 165
```

Can be rewritten in 4.0 as:

```js
var now = new Date;
d3.timeDay.count(d3.timeYear(now), now); // 165
```

Likewise, in place of 3.x’s d3.time.weekOfYear, in 4.0 you would say:

```js
d3.timeWeek.count(d3.timeYear(now), now); // 24
```

Mike Bostock's avatar
Mike Bostock committed
1121
The new *interval*.count is of course more general. For example, you can use it to compute hour-of-week for a heatmap:
Mike Bostock's avatar
Mike Bostock committed
1122
1123

```js
Mike Bostock's avatar
Mike Bostock committed
1124
d3.timeHour.count(d3.timeWeek(now), now); // 64
Mike Bostock's avatar
Mike Bostock committed
1125
```
Mike Bostock's avatar
Mike Bostock committed
1126

Mike Bostock's avatar
Mike Bostock committed
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
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
1148
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
1149

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

Mike Bostock's avatar
Mike Bostock committed
1152
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
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171

```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
1172
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
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183

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

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

Mike Bostock's avatar
Mike Bostock committed
1184
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
1185

Mike Bostock's avatar
Mike Bostock committed
1186
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
1187
1188
1189
1190
1191
1192
1193
1194
1195

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
1196
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
1197
1198
1199
1200
1201
1202
1203

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

Mike Bostock's avatar
Mike Bostock committed
1204
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
1205

Mike Bostock's avatar
Mike Bostock committed
1206
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
1207

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

Mike Bostock's avatar
Mike Bostock committed
1210
As described in [What Makes Software Good?](https://medium.com/@mbostock/what-makes-software-good-943557f8a488) the [*selection*.transition](https://github.com/d3/d3-transition#selection_transition) method now takes an optional *transition* instance which can be used to synchronize a new transition with an existing transition. This method inherits timing from the closest ancestor for each selected element, and thus works even when the referenced *transition* has variable timing such as a staggered delay. This method replaces the deeply magical behavior of *transition*.each in 3.x; in 4.0, [*transition*.each](https://github.com/d3/d3-transition#transition_each) is now identical to [*selection*.each](https://github.com/d3/d3-selection#selection_each). Use the new [*transition*.on](https://github.com/d3/d3-transition#transition_on) method to listen to transition events.
Mike Bostock's avatar
Mike Bostock committed
1211

Mike Bostock's avatar
Mike Bostock committed
1212
change *transition*.transition semantics in regards to *transition*.delay.
Mike Bostock's avatar
Mike Bostock committed
1213

Mike Bostock's avatar
Mike Bostock committed
1214
changed *transition*.ease to always take an easing function, not a name. see d3-ease.
Mike Bostock's avatar
Mike Bostock committed
1215

Mike Bostock's avatar
Mike Bostock committed
1216
transitions are now frozen in the background! see d3-timer. note also d3.timeout, d3.interval.
Mike Bostock's avatar
Mike Bostock committed
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227

functions passed to transition methods take the same standard arguments as selections.
*transition*.attrTween gets standard arguments (not current attribute value).
*transition*.styleTween gets standard arguments (not current style value).
can call *transition*.{tween,attrTween,styleTween} in getter mode.

optimize transitions to re-use tweens and interpolators to improve performance!
uses optimized interpolator rather than d3.interpolate.

fix *transition*.remove if multiple transition names are in use.

Mike Bostock's avatar
Mike Bostock committed
1228
1229
1230
1231
new d3.active for chaining transitions / modifying in-progress transitions.

strict state machine to enforce when transitions can be modified; more robust.
enforces *t* = 1 on end, regardless of easing.
Mike Bostock's avatar
Mike Bostock committed
1232

Mike Bostock's avatar
Mike Bostock committed
1233
1234
1235
1236
for rewriting resuable components that support transitions:
new *transition*.selection.
new d3.interrupt.
A new [*transition*.merge](https://github.com/d3/d3-transition#transition_merge) method.
Mike Bostock's avatar
Mike Bostock committed
1237

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

Mike Bostock's avatar
Mike Bostock committed
1240
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
1241

Mike Bostock's avatar
Mike Bostock committed
1242
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
1243
1244

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
1245

Mike Bostock's avatar
Mike Bostock committed
1246
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
1247

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

Mike Bostock's avatar
Mike Bostock committed
1250
1251
1252
1253
1254
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
1255

Mike Bostock's avatar
Mike Bostock committed
1256
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).