class: center, middle, inverse # D3 V4 - What's new? Play along: [D3 v3 playground](http://jsbin.com/degoxo/1/edit?html,js,console,output) | [D3 v4 playground](http://jsbin.com/yoruka/1/edit?html,js,console,output) Slides: [iros.github.io/d3-v4-whats-new/](http://iros.github.io/d3-v4-whats-new/#1) [![bocoup](stylesheets/images/bocoup.png)](http://bocoup.com/datavis)
Irene Ros
@ireneros
irene@bocoup.com
--- # Modularity #### D3 v3 was one large library. You had to include all of it, even if you didn't need all of it. -- #### D3 v4 is actually a set of small modules. You can choose to use one or more as you need them. https://github.com/d3/ ![modules](https://i.gyazo.com/d4661085579da7bbbf82e47ca62022db.png) --- # Modularity For example: `https://github.com/d3/d3-scale` Can be installed via npm: `npm install d3-scale` -- Note that each module has it's own dependencies. When installing them via npm, they will be pulled down for you, but if you were to include them manually, you need to make sure those are included as well. For example: ```html ``` Most likely you will use some sort of build system to package your JS. Mike Bostock has suggested using [Rollup](http://rollupjs.org/) an example of which you can find [here](http://bl.ocks.org/mbostock/bb09af4c39c79cffcde4). --- # Modularity You can still use the entire v4 build by including it using your favorite method: ```html ``` --- # Namespacing D3 v3's API was logically namespaced. For example: * `d3.scale.linear` * `d3.scale.ordinal` * `d3.time.format` * `d3.svg.axis` -- In D3 v4, all modules share a flat namespace `d3.*` as a result of adopting ES6 modules. * `d3.scale.linear` is now `d3.scaleLinear` * `d3.layout.treemap` is now `d3.treemap` -- This does mean you can't just swap in D3 v4 and expect it to work. --- # Method accessors Many utility methods now take an accessor method that has a consistent signature: `function(d, i, data) {...}` For example: ```javascript var settlersData = [ {name: "Wood", count: 2}, {name: "Ore", count: 3}, {name: "Sheep", count: 4}, {name: "Wheat", count: 1} ]; d3.min(settlersData, function(d, i, data) { return d.count; }); ``` Previously some methods were not consistent about this (for example, `d3.quantile`). --- # Canvas Rendering In v3, d3's few actual rendering methods only rendered to SVG. Starting v4, many of the rendering helpers now have a new `context` method that lets you pass in a Canvas context to render to. For example: ```javascript var line = d3.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.value); }); ``` -- To render SVG: ```javascript path.datum(data).attr("d", line); ``` -- To render to Canvas: ```javascript line.context(context)(data); ``` You can see more examples in the shapes module: [d3-shape](https://github.com/d3/d3-shape/blob/master/README.md). --- # Selections * Selections no longer subclass Array by extending its prototype. They are now plain objects. -- * There is a new method called `.nodes` to retrieve all nodes within a selection as an array. -- * Selections are immutable (parents and elements never change, though their attributes do.) For example. `selection.sort` will return a new selection. --- # Selections * `selection.append` now inserts elements in the order of the data bound, instead of at the end: For example, in v3: ``` javascript d3.select("body").selectAll("span").data([1, 3, 5], String).enter().append("span").text(String); d3.select("body").selectAll("span").data([1, 2, 3, 4, 5], String).enter().append("span").text(String); // 13524 ``` In v4: ``` javascript d3.select("body").selectAll("span").data([1, 3, 5], String).enter().append("span").text(String); d3.select("body").selectAll("span").data([1, 2, 3, 4, 5], String).enter().append("span").text(String); // 12345 ``` -- * New lifecycle event (ish)! `merge`. --- [example](http://jsbin.com/cipebe/4/edit?html,js,console,output) In v3: ```javascript var circleBinding = svg.selectAll("circle").data(data); circleBinding.style("fill", "blue"); // UPDATE circleBinding.exit().remove(); // EXIT circleBinding.enter().append("circle") // ENTER; modifies UPDATE! .style("fill", "green"); circleBinding // ENTER + UPDATE .style("stroke", "black"); ``` -- In v4: ```javascript var circleBinding = svg.selectAll("circle").data(data); circleBinding.style("fill", "blue"); // UPDATE circleBinding.exit().remove(); // EXIT circleBinding.enter().append("circle") // ENTER .style("fill", "green") .merge(circleBinding) // ENTER + UPDATE .style("stroke", "black"); ``` --- # Selections ([d3-selection](https://github.com/d3/d3-selection/blob/master/README.md)) * To move a selection to the front of its siblings call `selection.raise`. To move it backwards, call `selection.lower` -- * You can dispatch events on selections using `selection.dispatch` -- * The `selection.call` method no longer sets `this` to be the selection. It is now passed as the first argument to the callback. In v3: ```javascript d3.selectAll("div.states") .call(function() { this.style('color', 'red'); }) ``` In V4: ```javascript d3.selectAll("div.states") .call(function(statesSelection) { statesSelection.style('color', 'red'); }) ``` --- # Multi-Selections ([d3-selection-multi](https://github.com/d3/d3-selection-multi)) In d3 v3, you could easily set multiple style or attribute properties like this: ```javascript d3.select("h4").style({ color: "red", background: "yellow" }); ``` -- In v4, you can no longer do that. Even this does not work: ```javascript d3.select("h4").style({ color: "red" }); ``` Instead, you have to set the key and value explicitly: ```javascript d3.select("h4").style("color", "red"); ``` --- # Multi-Selections ([d3-selection-multi](https://github.com/d3/d3-selection-multi)) Multi-selections allows you to set multiple properties with one call, but it is *not included by default* with the standard build. You have to include it yourself: ```html ``` This will let you: ```javascript var div = d3.selectAll("div") .attrs({ "title": "Hello, world!", "name" : "greeter" }) .styles({ "color": "red", "background" : "green" }); ``` Note that it's `styles` and `attrs`, not `style` and `attr` as before. --- # Transitions ([d3-transition](https://github.com/d3/d3-transition/blob/master/README.md)) You can create transitions and then share them across selections ```javascript var t = d3.transition() .duration(750) .ease(d3.easeLinear); d3.selectAll(".apple").transition(t) .style("fill", "red"); d3.selectAll(".orange").transition(t) .style("fill", "orange"); ``` --- # Transitions ([d3-transition](https://github.com/d3/d3-transition/blob/master/README.md)) Delays are now relative to previous transition, not the first transition ```javascrit d3.selectAll(".apple") .transition() // First fade to green. .style("fill", "green") .transition() // Then red. .style("fill", "red") .transition() // Wait one second. Then brown, and remove. .delay(1000) .style("fill", "brown") .remove(); ``` -- * `selection.interrupt` stops active transitions and cancels all scheduled transitions on the selection. -- * All transition callbacks recieve the standard arguments `(d, i, nodes)` - which impacts in particular the `attrTween` and `styleTween` functions which took a tween function or style value as the third argument. --- * `d3.active` lets you select a transition that is currently active on a given node. [Example](http://bl.ocks.org/mbostock/70d5541b547cc222aa02) ```javascript var whiteblue = d3.interpolateRgb("#eee", "steelblue"), blueorange = d3.interpolateRgb("steelblue", "orange"), orangewhite = d3.interpolateRgb("orange", "#eee"); d3.select("body").selectAll("div") .data(d3.range(n)) .enter().append("div") .transition() .delay(function(d, i) { return i + Math.random() * n / 4; }) .ease(d3.easeLinear) .on("start", function repeat() { d3.active(this) .styleTween("background-color", function() { return whiteblue; }) .transition() .delay(1000) .styleTween("background-color", function() { return blueorange; }) .transition() .delay(1000) .styleTween("background-color", function() { return orangewhite; }) .transition() .delay(n) .on("start", repeat); }); ``` --- # Scales ([d3-scale](https://github.com/d3/d3-scale/blob/master/README.md)) * Lots of renaming: * `d3.scale.linear` → `d3.scaleLinear` * `d3.scale.sqrt` → `d3.scaleSqrt` * `d3.scale.pow` → `d3.scalePow` -- * Scales now generate ticks in the same order as the domain (useful if you have a descending scale) -- * You can specify what to do when a scale recieves a value that is outside the domain using `.unknown`: ```javascript var x = d3.scaleOrdinal() .domain([0, 1]) .range(["red", "blue"]) .unknown(undefined); x(0) // "red" x(2); // undefined ``` --- # Scales ([d3-scale](https://github.com/d3/d3-scale/blob/master/README.md)) * Categorical color scales have changed. They have been renamed: `d3.scale.category10` → `d3.schemeCategory10` and they are no longer actual scales but just array of numbers: In v3: ```javascript var color = d3.scale.category10(); ``` In V4: ```javascript var color = d3.scaleOrdinal(d3.schemeCategory10); ``` -- * New sequential scales - instead of outputting to a range, they use an interpolator. Most useful for sequential color schemes. Lots of new interplators inspired by matplotlib's perceptually motivated colormaps. ```javascript z = d3.scaleSequential(d3.interpolateViridis); ``` ![interpolateViridis](https://i.gyazo.com/b531e023ced883ee075df093336aae01.png) --- # Histograms ([d3-array](https://github.com/d3/d3-array/blob/master/README.md)) ### `d3.histogram` In v4: ```javascript var values = [ { val : 1 }, { val : 1 }, { val : 4 }, { val : 5 }, { val : 23 }, { val : 1 }, { val : 4 } ]; var hist = d3.histogram() .thresholds(3) .value(function(d) { return d.val; }); ``` --- # Histograms ([d3-array](https://github.com/d3/d3-array/blob/master/README.md)) ### `d3.histogram` * `d3.layouts.histogram` is now `d3.histogram` -- * The `bins` method was renamed to `thresholds` -- * `dx` which specified the bin width is gone, there are now `x0` and `x1` which specify the start and end range of a bin. `x0` will equal the `x1` of the previous bin. -- The binning is also now different. In v3 the values we have for `x` and `dx` are: `[1, 7.33333] [8.33333333, 7.33333], [15.666666666666666, 7.33333]` In V4 the bins are: `[1, 10] [10, 20] [20, 23]` --- # Axes ([d3-axis](https://github.com/d3/d3-axis/blob/master/README.md)) In v3, you had to style the axes or it would look like this: ![v3 axes](https://raw.githubusercontent.com/d3/d3/master/img/axis-v3.png) ```css .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .axis text { font: 10px sans-serif; } ``` ```javascript d3.select(".axis") .call(d3.svg.axis() .scale(x) .orient("bottom")); ``` --- # Axes ([d3-axis](https://github.com/d3/d3-axis/blob/master/README.md)) In v4, styling is taken care of: ```javascript var x = d3.scaleLinear() .domain([1,10]) .range([1,300]); var axis = d3.axisTop(x); d3.select("body").append("svg") .attr("class", "axis") .attr("width", 310) .attr("height", 30) .append("g") .attr("transform", "translate(0,20)") .call(axis); ``` Results in: ![v4 axes](https://i.gyazo.com/95a8056bc4643c05a8f4e651cab14840.png) The default styles have been changed to offset the axis by 0.5px which fixes a crisp-edges rendering issue on safari where the axis would be drawn 2px thick. --- # Axes ([d3-axis](https://github.com/d3/d3-axis/blob/master/README.md)) * Note that instead of setting the axis orientation we now use * `axisLeft` * `axisRight` * `axisTop` * `axisBottom` -- `axis.tickArguments([20, "s"])` - shorthand for calling `axis.ticks(20)` and `axis.tickFormat(d3.format("s"))`. --- # Collections ([d3-collections](https://github.com/d3/d3-collection/blob/master/README.md)) Aggregates all functions having to do with data structures * Objects * Maps * Sets * Nests --- # Collections ([d3-collections](https://github.com/d3/d3-collection/blob/master/README.md)) ### d3.set * Renamed: `set.forEach` to `set.each` * Now accepts an accessor function ```javascript var values = [ { val : 1 }, { val : 1 }, { val : 4 }, { val : 5 }, { val : 23 }, { val : 1 }, { val : 4 } ]; var x = d3.set(values, function(d) { return d.val; }); // [1,4,5,23] ``` --- # Collections ([d3-collections](https://github.com/d3/d3-collection/blob/master/README.md)) ### d3.map * Renamed: `map.forEach` → `map.each`. * Argument order changed for each callback to `(value, key, map)`: ```javascript var values = [ { val : 1, name: "One"}, { val : 1, name: "One" }, { val : 4, name: "Four" }, { val : 5, name: "Five" }, { val : 23, name: "TwentyThree" }, { val : 1, name: "One" } ]; var x = d3.map(values, function(d) { return d.name; }); x.each(function(val, key, map) { console.log(val); }); // { val : 1, name: "One"}, { val : 4, name: "Four" }, { val : 5, name: "Five" },... ``` In V3, the order was `(key, value)`. So if you would get: `["One", "Four", "Five", "TwentyThree"]` if you forget to reverse your callback variables... --- # Collections ([d3-collections](https://github.com/d3/d3-collection/blob/master/README.md)) ### Both d3.set and d3.map * Return the collection, when you call `.add` to add a new element, instead of the added value. * Have new `.clear` methods to clear the collections. --- # Arrays ([d3-array](https://github.com/d3/d3-array/blob/master/README.md)) ### `d3.scan(arr, fn)` D3 v3's `d3.min` and `d3.max` would return the min or max element appropriately, but you couldn't easily find out the original position of that element. In v4, `d3.scan` does just that using a comparator function. ```javascript var settlersData = [ {name: "Wood", count: 2}, {name: "Ore", count: 3}, {name: "Sheep", count: 4}, {name: "Wheat", count: 1} ]; var idx = d3.scan(settlersData, function(a, b) { return a.count - b.count; }); // 3 settlersData[idx]; // {name: "Wheat", count: 1} ``` --- # Arrays ([d3-array](https://github.com/d3/d3-array/blob/master/README.md)) ### `d3.ticks(start, end, count)` A new method that will generate an array of `count+1` items equally spaced between `start` and `end`. ```javascript var ticks = d3.ticks(0, 10, 5); // [0, 2, 4, 6, 8, 10] ``` Note that this method has nothing to do with axes. ### `d3.tickStep(start, end, count)` Will give you the space between values that you would obtain from `d3.ticks`: ```javascript d3.tickStep(0,10,5); // 2 ``` --- # Arrays ([d3-array](https://github.com/d3/d3-array/blob/master/README.md)) ###`d3.range(start, end, increment)` Floating point math is fun: `0.2 * 3 = 0.6000000000000001` In D3 v3, `d3.range` tried to handle this: ```javascript d3.range(0, 1, 0.2) // [0, 0.2, 0.4, 0.6, 0.8] ``` D3 v4's `d3.range` no longer does that: ```javascript d3.range(0, 1, 0.2) // [0, 0.2, 0.4, 0.6000000000000001, 0.8] ``` This only matters if you are dealing with floating point numbers and you can always use `d3.format` to present them more consistently. --- # Colors ([d3-color](https://github.com/d3/d3-color/blob/master/README.md)) * All colors now have an opacity method exposed: `.opacity` which takes a value from 0 to 1. -- * You can also pass an optional opacity argument to `d3.rgb`, `d3.hsl`, `d3.lab`, `d3.hcl` or `d3.cubehelix`. -- * You can now parse CSS color specifiers with `d3.color`: ```javascript var red = d3.color("hsl(0, 80%, 50%)"); // {h: 0, l: 0.5, s: 0.8, opacity: 1} ``` -- * The `toString` method will now return an `rgb` or `rgba` string in the form of `rgb(12,13,42)`. -- * There is no more `.hsl` method on a color instance. To convert a color to hsl call the `d3.hsl` helper method: ```javascript d3.hsl(red) // Color instance: {h: 0, s: 0.8, l: 0.5, opacity: 1} ``` -- * New method called `color.displayable()` will return false if the color is [out of gamut](https://en.wikipedia.org/wiki/Gamut). --- # Easing ([d3-ease](https://github.com/d3/d3-ease/blob/master/README.md)) In v3, you used easing function string names to specify the ones you wanted like "linear" or "cubic-in-out". In V4, we use methods instead: Instead of: ```javascript var e = d3.ease("elastic-out-in", 1.2); ``` Use: ```javascript var e = d3.easeElastic.amplitude(1.2); ``` [Visual reference](https://github.com/d3/d3-ease/blob/master/README.md) for the functions [Animated version](http://bl.ocks.org/mbostock/248bac3b8e354a9103c4) --- # Dispatching ([d3-dispatch](https://github.com/d3/d3-dispatch/blob/master/README.md)) * Instead of exposing individual methods for each event type, you just use `call` to fire off an event (note these are different from the `selection.call`). In V3: ```javascript dispatcher.foo.call(that, "Hello, Foo!"); ``` In V4: ```javascript dispatcher.call("foo", that, "Hello, Foo!"); ``` -- * The `on` method accepts multiple event names, separated by a space: ```javascript dispatcher.on("foo bar", function(message) { console.log(message); }); ``` --- # Brushing ([d3-brush](https://github.com/d3/d3-brush/blob/master/README.md)) * `d3.svg.brush` is now `d3.brush` -- * There are now 3 classes for brushing along the x, y or both dimensions: `d3.brushX`, `d3.brushY` or `d3.brush`. -- * Brush is no longer depending on scales - they define a selection in screen coordinates and you can invert it using a scale of choice. -- * You can restrict a brushing area to a `brush.extent`, otherwise it defaults to the full SVG element. -- * A brush doesn't store the active selection - it is now stored on the element to which the brush was applied. You can access it either via: * a brush event - retrieve element by calling `event.selection`. * Call `d3.brushSelection` on any given element. -- * You can move the brush by calling `brush.move` -- * There are now default styling applied, so you don't have to add them manually. --- # Brushing ([d3-brush](https://github.com/d3/d3-brush/blob/master/README.md)) ### `d3.brush` ```javascript var brush = d3.brush() .on("start brush", brushed) .on("end", brushended); function brushed() { var s = d3.event.selection; //... } function brushended() { if (!d3.event.selection) { //... } } svg.append("g") .attr("class", "brush") .call(brush) .call(brush.move, [[307, 167], [611, 539]]); ``` Example: http://bl.ocks.org/mbostock/0d20834e3d5a46138752f86b9b79727e --- # Dragging ([d3-drag](https://github.com/d3/d3-drag/blob/master/README.md)) * `d3.behavior.drag` → `d3.drag` * There's a new method called `subject` which lets you define an accessor to return what is being dragged. This is useful when using canvas, since there are no DOM nodes representing the content. The result of this accessor function call will be available on a drag event under d3.event.subject. Example: http://bl.ocks.org/mbostock/444757cc9f0fde320a5f469cd36860f4 -- * There is now an `on` method to bind to start, end and drag events: ```javascript canvas.call(d3.drag() .subject(dragsubject) .on("start", dragstarted) .on("drag", dragged) .on("end", dragended) .on("start.render drag.render end.render", render)); ``` -- * There are also `d3.dragEnable` and `d3.dragDisable` methods to control dragging support at a higher level. --- # Force layout ([d3-force](https://github.com/d3/d3-force/blob/master/README.md)) * Renamed: `d3.layout.force` → `d3.forceSimulation`. -- * The force algorithm changed to track node velocity (`node.vx` and `node.vy`) and position (`node.x` and `node.y`, not just position (formally `node.px` and `node.py`). -- * Initial node position is now [deterministic](https://raw.githubusercontent.com/d3/d3-force/master/img/phyllotaxis.png) -- * If you need to find the closest node to a pointer, you no longer have to use a Voronoi SVG overlay, you can call `simulation.find`. -- * Old v3 version of [Les Miserables](http://bl.ocks.org/timelyportfolio/5049980). In v4: [Les Miserables](https://bl.ocks.org/mbostock/4062045) with [dragging](http://bl.ocks.org/mbostock/ad70335eeef6d167bc36fd3c04378048) ``` javascript var simulation = d3.forceSimulation() .force("link", d3.forceLink().id(function(d) { return d.id; })) .force("charge", d3.forceManyBody()) .force("center", d3.forceCenter(width / 2, height / 2)); simulation .nodes(graph.nodes) .on("tick", ticked); simulation.force("link") .links(graph.links); ``` --- # Hierarchies ([d3-hierarchy](https://github.com/d3/d3-hierarchy/blob/master/README.md)) * Lots of renaming: * `d3.layout.cluster` → `d3.cluster` * `d3.layout.hierarchy` → `d3.hierarchy` * New useful method `d3.stratify` to convert flat arrays of objects into the hierarchical structures required by hierarchical layouts: ```json [ {"name": "Eve", "parent": ""}, {"name": "Cain", "parent": "Eve"}, {"name": "Seth", "parent": "Eve"}, {"name": "Enos", "parent": "Seth"} ] ``` --- To convert to a hierarchy: ```javascript var root = d3.stratify() .id(function(d) { return d.name; }) .parentId(function(d) { return d.parent; }) (table); ``` ![image](https://raw.githubusercontent.com/d3/d3-hierarchy/master/img/stratify.png) --- # Hierarchies ([d3-hierarchy](https://github.com/d3/d3-hierarchy/blob/master/README.md)) * All hierarchical layouts now expect a hierarchy object. So if you already have json in the right form you first have to call `var struct = d3.hierarchy(myJsonObj)` to convert it and then pass it to your layout. -- * There are new methods for aggregating special nodes like: * `nodes.leaves` to get just leaf nodes * `nodes.descendents` * `nodes.anscestors` * To get the links in the form of {source, target} call `nodes.links` (which you used to obtain from your layouts.) --- # Queue ([d3-queue](https://github.com/d3/d3-queue/blob/master/README.md)) * A queue evaluates zero or more deferred asynchronous tasks with configurable concurrency * Used to be a separate library, now included in the default bundle as `d3.queue`. ```javascript d3.queue() .defer(d3.json, 'states.json') .defer(d3.json, 'cities.json') .await(function(error, states, cities) { // make map }); // or: d3.queue() .defer(d3.json, 'states.json') .defer(d3.json, 'cities.json') .awaitAll(function(error, results) { // results is an array of the returned objects. }); ``` --- # Delimiter-Separated Values ([d3-dsv](https://github.com/d3/d3-dsv/blob/master/README.md)) * Lots of renaming: * `d3.csv.parse` → `d3.csvParse` * `d3.csv.parseRows` → `d3.csvParseRows` -- * The original `d3.csv` and `d3.tsv` for loading files have not been renamed. -- * There is no more `d3.dsv` for custom formatters, you can now use `d3.dsvFormat("|")` to define a new formatter and parser. -- * The parse method now exposes column names: ```javascript d3.csv("cars.csv", function(error, data) { if (error) throw error; console.log(data.columns); // ["Year", "Make", "Model", "Length"] }); ``` --- # Polygons ([d3-polygon](https://github.com/d3/d3-polygon/blob/master/README.md)) * `d3.geom.polygon` is gone and there is no `d3.polygon`. * Now using `d3.polygonHull(points)` which returns the convex hull of the specified points. The returned hull is represented as an array containing a
subset
of the input points arranged in counterclockwise order. -- Some helper methods to call with the results of polygonHull: * `d3.polygonArea` - area of polygon * `d3.polygonCentroid` - center point of polygon * `d3.polygonContains` - checks if a point is inside of a polygon. * `d3.polygonLength` - returns the length of the perimiter. Example [here](http://bl.ocks.org/mbostock/6f14f7b7f267a85f7cdc) --- # Quadtree ([d3-quadtree](https://github.com/d3/d3-quadtree/blob/master/README.md)) A quadtree recursively partitions two-dimensional space into squares, dividing each square into four equally-sized squares. http://bl.ocks.org/mbostock/9078690 * `d3.geom.quadtree` → `d3.quadtree` * Quadtree is no longer a generator. Instead of defining a quadtree function that you pass your data to, you add your data to the quadtree you're generating using the `add` or `addAll` methods: In v3: ```javascript var quadtree = d3.geom.quadtree() .extent([[0, 0], [width, height]]); quadtree(data); ``` In V4: ```javascript var quadtree = d3.quadtree() .extent([[0, 0], [width, height]]) .addAll(data); ``` --- # Quadtree ([d3-quadtree](https://github.com/d3/d3-quadtree/blob/master/README.md)) * Previously the quadtree generator returned the root node, now you can get it by calling `quadtree.root`. -- * The `leaf` boolean flag on nodes is gone, now you can use `node.length` to determine if the node has children instead. -- * `quadtree.find` now takes an optional radius (in screen px) that its search will be restricted to - useful when your quadtree has a lot of points. -- * Implementation no longer recursive and much faster. --- # Other small but notable * Written in strict mode -- * `d3-geo` introduces `fitSize`, the [greatest thing since sliced bread](http://bl.ocks.org/mbostock/19ffece0a45434b0eef3cc4f973d1e3d) -- * The default build is anonymous (aka no global `d3` object is exported if AMD or CommonJS is detected.) -- * Uses only ASCII variable names and ASCII string literals. No more requirement to be explicit about UTF-8. -- * `d3.format` now has text formatting: `d3.format(">10c")("foo"); // " foo"` -- * You can set a default locale based on country for some of your number parsing with `d3.formatDefaultLocale` [link](https://npmcdn.com/d3-format@1.0.1/locale/) -- * New random number generators for exponential and uniform distributions. -- * `d3.xhr` is now `d3.request`, which also supports basic auth by calling `.user` and `.password` methods. --- # Not covered: * Chord diagrams ([d3-chord](https://github.com/d3/d3-chord/blob/master/README.md)) [changes](https://github.com/d3/d3/blob/master/CHANGES.md#chords-d3-chord) * Number formatting ([d3-format](https://github.com/d3/d3-format/blob/master/README.md)) [changes](https://github.com/d3/d3/blob/master/CHANGES.md#number-formats-d3-format) * Geography ([d3-geo](https://github.com/d3/d3-geo/blob/master/README.md)) [changes](https://github.com/d3/d3/blob/master/CHANGES.md#geographies-d3-geo) * Hierarchical layouts ([d3-hierarchy](https://github.com/d3/d3-hierarchy)) such as treemaps, circle packing etc. [changes](https://github.com/d3/d3/blob/master/CHANGES.md#hierarchies-d3-hierarchy) * Interpolators ([d3-interpolate](https://github.com/d3/d3-interpolate/blob/master/README.md)) - interpolation methods [changes](https://github.com/d3/d3/blob/master/CHANGES.md#interpolators-d3-interpolate) * Time formats ([d3-time-format](https://github.com/d3/d3/blob/master/CHANGES.md#time-formats-d3-time-format)) [changes](https://github.com/d3/d3/blob/master/CHANGES.md#time-formats-d3-time-format) * Timers ([d3-timer](https://github.com/d3/d3-timer/blob/master/README.md)) [changes](https://github.com/d3/d3/blob/master/CHANGES.md#timers-d3-timer) * Voronoi diagrams ([d3-voronoi](https://github.com/d3/d3-voronoi/blob/master/README.md)) [changes](https://github.com/d3/d3/blob/master/CHANGES.md#voronoi-diagrams-d3-voronoi) * Zooming ([d3-zoom](https://github.com/d3/d3-zoom/blob/master/README.md)) [changes](https://github.com/d3/d3/blob/master/CHANGES.md#zooming-d3-zoom) --- class: center, middle, inverse # Thanks!
Irene Ros
@ireneros
irene@bocoup.com