On Github Yonet / GDI-d3-Workshop
Slides : bit.ly/gdi-d3-slides
Aysegul Yonet / @AysegulYonet
Lot's of examples
<circle cx="250" cy="100" r="30" fill="#25B0B0"> </circle>
<rect x="200" y="50" width="100" height="100" rx="10" ry="0" fill="#25B0B0"> </rect>Interesting fact: if a properly specified value is provided for rx but not for ry (or the opposite), then the browser will consider the missing value equal to the defined one.
<line x1="10" y1="10" x2="100" y2="100" stroke="blue" stroke-width="100"> </line>
<path d=" M50,100 L131,66 L259,115 L339,50 L400,98 M350,150 L100,150" fill="none" stroke="#25B0B0"> </path>
<svg> <text x="100" y="100" fill="red" font-family="arial" font-size="16"> Look at me, I am a text. </text> </svg>Unless you set the style of the SVG text, it inherits font-styles from CSS.
<g transform="translate(100, 100)"> <circle cx="20" cy="10" r="30" fill="#25B0B0"> </circle> <circle cx="100" cy="10" r="30" fill="#25B0B0"> </circle> </g>Any transformations (positioning, scaling, rotating) that are applied to the group element will also be applied to each of the child elements.
<svg width="100%" height="100%"> <defs> <g id="Port"> <circle style="fill:inherit" r="10"></circle> </g> </defs> <text y="15">black</text> <use x="50" y="10" href="#Port"></use> <text y="35">red</text> <use x="50" y="30" href="#Port" class="classA"></use> <text y="55">blue</text> <use x="50" y="50" href="#Port" style="fill:blue"></use> </svg>The use element takes nodes from within the SVG document, and duplicates them somewhere else. The effect is the same as if the nodes were deeply cloned into a non-exposed DOM, and then pasted where the use element is, much like cloned template elements in HTML5. Since the cloned nodes are not exposed, care must be taken when using CSS to style a use element and its hidden descendants. CSS attributes are not guaranteed to be inherited by the hidden, cloned DOM unless you explicitly request it using CSS inheritance.
var paragraphs = $("div p");
var paragraphs = d3.select("div").selectAll("p");jsFiddle D3 difference: child nodes might not actually exist. Selectors in D3 are declared the same way as CSS rules. An important difference is that a D3 selector object only contains the elements that matched the selection rule when the selection was first created. The selection can be based on tag, class, identifier, attribute, or place in the hierarchy. This includes getting and setting attributes, display texts, and styles. Elements may also be added and removed. This process of modifying, creating and removing HTML elements can be made dependent on data, which is the basic concept of D3.js.
Bind array of data to child nodes
d3.selectAll("p") .data([3, 7, 21, 31, 35, 42])
d3.select("body").selectAll("p") .data([3, 7, 21, 31, 35, 42]) .enter().append("p");When data is bound to a selection, each element in the data array is paired with the corresponding node in the selection. If there are fewer nodes than data, the extra data elements form the enter selection, which you can instantiate by appending to the enter selection. D3 methods returns the selection they act upon, you can apply multiple operations to the same selection. IMPORTANT!There is a gotcha with method chaining, however: while most operations return the same selection, some methods return a new one! For example, selection.append returns a new selection containing the new elements. This conveniently allows you to chain operations into the new elements.
var bars = d3.select('svg').selectAll('rect').data(someData); //if we have more data, add new rectangles for those data items bars.enter().append('rect') //if we have less data points, remove the rectangles that no longer have a data pairing. bars.exit().remove();Using D3’s exit and remove, you can get rid of outgoing nodes that are no longer needed.
if you forget about the enter and exit selections, you will automatically select only the elements for which there exists corresponding data.
// Update… var p = d3.select("body").selectAll("p") .data([3, 7, 21, 31, 35, 42]); // Enter… p.enter().append("p") // Exit… p.exit().remove();By handling these three cases separately, you specify precisely which operations run on which nodes.
d3.select("body").selectAll("p") .data([3, 7, 21, 31, 35, 42]) .enter().append("p") .exit().remove();while most operations return the same selection, some methods return a new one! For example, selection.append returns a new selection containing the new elements. This conveniently allows you to chain operations into the new elements. Since method chaining can only be used to descend into the document hierarchy, use var to keep references to selections and go back up.
Exercise: bit.ly/enter-exit-exercise
If you get stuck...Solution
You can operate over the nodes in a declarative way using selector methods.
You can use data values or index in a callback to define any property.
d3.select("div").selectAll("p").style("color", function(data, i) { return i % 2 ? "red" : "blue"; });
d3.selectAll("circle") .attr("r", "0"); .transition() .duration(750) .delay(function(d, i) { return i * 10; }) .attr("r", function(d) { return Math.sqrt(d); });
Exercise 0: Look at the example and create a transition to change the size of the circles:bit.ly/d3-transitions
Exercise 1: bit.ly/d3exercise1
In case you get stuck... Solution for Exercise 1
Scales and Domains
Axis
Loading external data
Scales transform a number in a certain interval (called the domain) into a number in another interval (called the range).
var x = d3.scale.linear() .domain([0, d3.max(data)])// your data minimum and maximum .range([0, 420]);//the pixels to map to d3.select(".chart") .selectAll("div") .data([3, 7, 21, 31, 35, 42]) .enter().append("div") .style("width", function(d) { return x(d) + "px"; })JSFiddle
Ordinal Scale have a discrete domain, such as a set of names or categories.
var x = d3.scale.ordinal() .domain(["A", "B", "C", "D", "E", "F"]) .rangeRoundBands([0, width], .1);
d3.scale.category10() - Constructs a new ordinal scale with a range of ten categorical colors:
Solution: Bar Charts with Scale
d3.svg.axis creates a new axis generator.
var xAxis = d3.svg.axis() .scale(x) .orient('bottom') .tickValues(data);JSFiddle
d3.time.format - creates a new local time formatter for a given specifier.
d3.time.format("%Y-%m-%d");JSFiddle
d3.time.scale - constructs a linear time scale.
var xScale = d3.time.scale() .domain([2009-07-13T00:02, 2009-07-13T23:48]) .rangeRound([0, width]); //rangeRound does the same thing as range but rounds the values to integers or begining of dates.JSFiddle
d3.time.intervals - a time interval in local time.
Most commonly used functions