UNPKG

d3

Version:

A small, free JavaScript library for manipulating documents based on data.

291 lines (245 loc) 39.1 kB
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>d3.js</title> <script type="text/javascript" src="d3.js?1.12.0"></script> <style type="text/css"> @import url("style.css?1.10.0"); @import url("syntax.css?1.6.0"); </style> </head> <body> <div class="body"> <div class="content"> <div class="topbar"> <b><a href=".">Overview</a></b> <a href="ex/">Examples</a> <a href="api/">Documentation</a> <a href="http://github.com/mbostock/d3/archives/master">Download</a> </div> <div class="sidebar"> <h1>d3.js</h1> </div> <h1 id='datadriven_documents'>Data-Driven Documents</h1> <p><strong>D3.js</strong> is a small, <a href='https://github.com/mbostock/d3/raw/master/LICENSE'>free</a> JavaScript library for manipulating documents based on data.</p> <div class='gallery'> <a href='ex/calendar.html' title='Calendar View'><img src='calendar.png' /></a><a href='ex/chord.html' title='Chord Diagram'><img src='chord.png' /></a><a href='ex/choropleth.html' title='Choropleth Map'><img src='choropleth.png' /></a><a href='ex/force.html' title='Force-Directed Graph'><img src='force.png' /></a><a href='ex/splom.html' title='Scatterplot Matrix'><img src='splom.png' /></a><a href='ex/stack.html' title='Stacked Bars'><img src='stack.png' /></a><a href='ex/stream.html' title='Streamgraph'><img src='stream.png' /></a><a href='ex/voronoi.html' title='Voronoi Diagram'><img src='voronoi.png' /></a> </div><div class='sidebar'> <ul> <li><a href='#selections'>Selections</a></li> <li><a href='#dynamic_properties'>Dynamic Properties</a></li> <li><a href='#enter_and_exit'>Enter and Exit</a></li> <li><a href='#transformation_not_representation'>Transformation, not Representation</a></li> <li><a href='#transitions'>Transitions</a></li> <li><a href='#subselections'>Subselections</a></li> <li><a href='#data_keys'>Data Keys</a></li> <li><a href='#modules'>Modules</a></li> </ul> </div> <p>D3 allows you to bind arbitrary data to a Document Object Model (DOM), and then apply data-driven transformations to the document. As a trivial example, you can use D3 to generate a basic HTML table from an array of numbers. Or, use the same data to create an interactive SVG bar chart with smooth transitions and interaction.</p> <p>D3 is not a traditional visualization framework. Rather than provide a monolithic system with all the features anyone may ever need, D3 solves only the crux of the problem: efficient manipulation of documents based on data. This gives D3 extraordinary flexibility, exposing the full capabilities of underlying technologies such as <a href='http://www.w3.org/Style/CSS/current-work'>CSS3</a>, <a href='http://www.w3.org/TR/html5/'>HTML5</a> and <a href='http://www.w3.org/TR/SVG/'>SVG</a>. It avoids learning a new intermediate proprietary representation. With minimal overhead, D3 is extremely fast, supporting large datasets and dynamic behaviors for interaction and animation. And, for those common needs, D3&#8217;s functional style allows code reuse through a diverse collection of optional modules.</p> <h3 id='selections'>Selections</h3> <p>Modifying documents using the native W3C <a href='http://www.w3.org/DOM/DOMTR'>DOM API</a> is indubitably tedious; not only are the method names verbose, but the imperative approach requires manual iteration and bookkeeping of temporary state. For example, to change the text color of paragraph elements:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='kd'>var</span> <span class='nx'>paragraphs</span> <span class='o'>=</span> <span class='nb'>document</span><span class='p'>.</span><span class='nx'>getElementsByTagName</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>);</span> <span class='lineno'>2</span> <span class='k'>for</span> <span class='p'>(</span><span class='kd'>var</span> <span class='nx'>i</span> <span class='o'>=</span> <span class='mi'>0</span><span class='p'>;</span> <span class='nx'>i</span> <span class='o'>&lt;</span> <span class='nx'>paragraphs</span><span class='p'>.</span><span class='nx'>length</span><span class='p'>;</span> <span class='nx'>i</span><span class='o'>++</span><span class='p'>)</span> <span class='p'>{</span> <span class='lineno'>3</span> <span class='kd'>var</span> <span class='nx'>paragraph</span> <span class='o'>=</span> <span class='nx'>paragraphs</span><span class='p'>.</span><span class='nx'>item</span><span class='p'>(</span><span class='nx'>i</span><span class='p'>);</span> <span class='lineno'>4</span> <span class='nx'>paragraph</span><span class='p'>.</span><span class='nx'>style</span><span class='p'>.</span><span class='nx'>setProperty</span><span class='p'>(</span><span class='s2'>&quot;color&quot;</span><span class='p'>,</span> <span class='s2'>&quot;white&quot;</span><span class='p'>,</span> <span class='kc'>null</span><span class='p'>);</span> <span class='lineno'>5</span> <span class='p'>}</span> </code></pre> </div> <p>Instead of manipulating individual nodes, D3 employs a declarative approach, operating on arbitrary sets of nodes called <em>selections</em>. For example, you can rewrite the above loop in 40 characters rather than 190:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;color&quot;</span><span class='p'>,</span> <span class='s2'>&quot;white&quot;</span><span class='p'>);</span> </code></pre> </div> <p>Of course, a selection may trivially consist of only a single node:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>select</span><span class='p'>(</span><span class='s2'>&quot;body&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;background-color&quot;</span><span class='p'>,</span> <span class='s2'>&quot;black&quot;</span><span class='p'>);</span> </code></pre> </div> <p>The selector format is defined by the W3C <a href='http://www.w3.org/TR/selectors-api/'>Selectors API</a>, supported natively by modern browsers. Backwards-compatibility for older browsers can be provided by <a href='http://sizzlejs.com/'>Sizzle</a>. The above examples select nodes by tag name (&#8221;p&#8221; and &#8220;body&#8221;, respectively). Elements may be selected using a variety of predicates, including containment, attribute values, and associated class or ID. And in the future, D3 could be extended to support additional selector formats, such as <a href='http://www.w3.org/TR/xpath/'>XPath</a>.</p> <p>D3 provides standard facilities for mutating nodes: setting attributes or styles; registering event listeners; adding, removing or sorting nodes; and changing HTML or text content. These suffice for the vast majority of needs. However, if the underlying DOM API is strictly needed, the nodes in a selection can be accessed directly, as each D3 selection is simply an array of nodes.</p> <h3 id='dynamic_properties'>Dynamic Properties</h3> <p>Readers familiar with <a href='http://jquery.com/'>jQuery</a> or <a href='http://www.prototypejs.org/'>Prototype</a> should immediately recognize similarities with D3. However, styles, attributes, and other properties can be specified as <em>functions of data</em> in D3, not just simple constants. Although their appearance is simple, these functions can be surprisingly powerful; the <code>d3.geo.path</code> function, for example, projects <a href='http://geojson.org/'>geographic coordinates</a> into SVG <a href='http://www.w3.org/TR/SVG/paths.html#PathData'>path data</a>. D3 provides many built-in reusable functions and function factories, such as graphical primitives for area, line and pie charts.</p> <p>How might you use dynamic properties? To start with a simple functional example, color paragraphs by picking random colors from the rainbow:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;color&quot;</span><span class='p'>,</span> <span class='kd'>function</span><span class='p'>()</span> <span class='p'>{</span> <span class='lineno'>3</span> <span class='k'>return</span> <span class='s2'>&quot;hsl(&quot;</span> <span class='o'>+</span> <span class='nb'>Math</span><span class='p'>.</span><span class='nx'>random</span><span class='p'>()</span> <span class='o'>*</span> <span class='mi'>360</span> <span class='o'>+</span> <span class='s2'>&quot;,100%,50%)&quot;</span><span class='p'>;</span> <span class='lineno'>4</span> <span class='p'>});</span> </code></pre> </div> <p>Or use the node index <code>i</code>, provided as the second argument, to alternate shades of gray for even and odd nodes:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;color&quot;</span><span class='p'>,</span> <span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>,</span> <span class='nx'>i</span><span class='p'>)</span> <span class='p'>{</span> <span class='lineno'>3</span> <span class='k'>return</span> <span class='nx'>i</span> <span class='o'>%</span> <span class='mi'>2</span> <span class='o'>?</span> <span class='s2'>&quot;#fff&quot;</span> <span class='o'>:</span> <span class='s2'>&quot;#eee&quot;</span><span class='p'>;</span> <span class='lineno'>4</span> <span class='p'>});</span> </code></pre> </div> <p>D3 also allows you to bind data to a selection; this data is available when computing properties. The data is specified as an array of arbitrary values (whatever you want), and each value to passed as the first argument (<code>d</code>) to property functions. The first element in the data array is passed to the first node in the selection, the second element to the second node, and so on. For example, if you bind an array of numbers to paragraph elements, you can use these numbers to compute dynamic font sizes:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>data</span><span class='p'>([</span><span class='mi'>4</span><span class='p'>,</span> <span class='mi'>8</span><span class='p'>,</span> <span class='mi'>15</span><span class='p'>,</span> <span class='mi'>16</span><span class='p'>,</span> <span class='mi'>23</span><span class='p'>,</span> <span class='mi'>42</span><span class='p'>])</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;font-size&quot;</span><span class='p'>,</span> <span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nx'>d</span> <span class='o'>+</span> <span class='s2'>&quot;px&quot;</span><span class='p'>;</span> <span class='p'>});</span> </code></pre> </div> <p>Once the data has been bound to the document, you can omit the <code>data</code> operator, and D3 will retrieve the previously-bound data per node. This allows you to recompute properties without explicitly respecifying the associated data.</p> <h3 id='enter_and_exit'>Enter and Exit</h3> <p>D3 can easily manipulate existing nodes, but what if the nodes don&#8217;t exist yet? Similarly, what if there are more nodes in the document than elements in your data array, and you want to remove the surplus? Using the <em>enter</em> and <em>exit</em> selections, you can add new nodes to match your data, and remove nodes that are no longer needed.</p> <p>When data is bound to a selection of nodes, 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 using the <code>enter</code> operator. This operator takes the name of the node to append to the document, such as &#8220;p&#8221; for paragraph elements:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>select</span><span class='p'>(</span><span class='s2'>&quot;body&quot;</span><span class='p'>).</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>data</span><span class='p'>([</span><span class='mi'>4</span><span class='p'>,</span> <span class='mi'>8</span><span class='p'>,</span> <span class='mi'>15</span><span class='p'>,</span> <span class='mi'>16</span><span class='p'>,</span> <span class='mi'>23</span><span class='p'>,</span> <span class='mi'>42</span><span class='p'>])</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>enter</span><span class='p'>().</span><span class='nx'>append</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'>4</span> <span class='p'>.</span><span class='nx'>text</span><span class='p'>(</span><span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='s2'>&quot;I&#39;m number &quot;</span> <span class='o'>+</span> <span class='nx'>d</span> <span class='o'>+</span> <span class='s2'>&quot;!&quot;</span><span class='p'>;</span> <span class='p'>});</span> </code></pre> </div> <p>A common pattern is to break the initial selection into three parts: the updating nodes to modify, the entering nodes to add, and the exiting nodes to remove.</p> <div class='highlight'><pre><code class='js'><span class='lineno'> 1</span> <span class='c1'>// Update…</span> <span class='lineno'> 2</span> <span class='kd'>var</span> <span class='nx'>p</span> <span class='o'>=</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>select</span><span class='p'>(</span><span class='s2'>&quot;body&quot;</span><span class='p'>).</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'> 3</span> <span class='p'>.</span><span class='nx'>data</span><span class='p'>([</span><span class='mi'>4</span><span class='p'>,</span> <span class='mi'>8</span><span class='p'>,</span> <span class='mi'>15</span><span class='p'>,</span> <span class='mi'>16</span><span class='p'>,</span> <span class='mi'>23</span><span class='p'>,</span> <span class='mi'>42</span><span class='p'>])</span> <span class='lineno'> 4</span> <span class='p'>.</span><span class='nx'>text</span><span class='p'>(</span><span class='nb'>String</span><span class='p'>);</span> <span class='lineno'> 5</span> <span class='lineno'> 6</span> <span class='c1'>// Enter…</span> <span class='lineno'> 7</span> <span class='nx'>p</span><span class='p'>.</span><span class='nx'>enter</span><span class='p'>().</span><span class='nx'>append</span><span class='p'>(</span><span class='s2'>&quot;p&quot;</span><span class='p'>)</span> <span class='lineno'> 8</span> <span class='p'>.</span><span class='nx'>text</span><span class='p'>(</span><span class='nb'>String</span><span class='p'>);</span> <span class='lineno'> 9</span> <span class='lineno'>10</span> <span class='c1'>// Exit…</span> <span class='lineno'>11</span> <span class='nx'>p</span><span class='p'>.</span><span class='nx'>exit</span><span class='p'>().</span><span class='nx'>remove</span><span class='p'>();</span> </code></pre> </div> <p>By handling these three cases separately, you can perform only the necessary modifications on each set of nodes. This is particularly useful when specifying transitions. For example, with a bar chart you might initialize entering bars using the old scale, and then transition entering bars to the new scale along with the updating and exiting bars. If you want to share dynamic properties across enter and update, you can reselect nodes after instantiating the enter selection, or use the <code>call</code> (mix-in) operator.</p> <p>Note that the updating nodes are actually the default selection—the result of the <code>data</code> operator. Thus, if you forget about the enter and exit selections, you will automatically select only the elements for which there exists corresponding data.</p> <p>To reiterate, D3 lets you transform <em>existing</em> documents (node hierarchies) based on data. This generalization includes creating new documents, where the starting selection is the empty node. D3 allows you to change an existing document in response to user interaction, animation over time, or even asynchronous notification from a third-party. A hybrid approach is even possible, where the document is initially rendered on the server, and updated on the client via D3.</p> <!-- By breaking the selection into three pieces—enter, update and exit—the user can define the minimal set of operations that need to apply to each subselection. Very often this includes different transitions for each subselection. Standard practice for chart transitions is to initialize entering nodes using the old layout, and to transition exiting nodes to the new layout. This allows entering and exiting nodes to transition consistently with the updating nodes. Often, the set of the nodes matching the selector are empty, as the nodes have not yet been created! By binding this empty selection to the data, you can create a *virtual* selection, with null nodes for each element in the dataset that does not yet exist in the document. The `enter` operator then creates the nodes, appending them to the document and materializing the selection. (Enter, exit and update selections are discussed further in the section on data binding.) For example, to add a tooltip to the images: <div class="highlight"><pre><code class="js"><span class="lineno">1</span> <span class="nx">d3</span><span class="p">.</span><span class="nx">selectAll</span><span class="p">(</span><span class="s2">&quot;div img&quot;</span><span class="p">)</span> <span class="lineno">2</span> <span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">&quot;title&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">d</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">d</span><span class="p">.</span><span class="nx">description</span><span class="p">;</span> <span class="p">});</span> </code></pre> </div> Here the selector "div img" is interpreted as `img` elements that are descendants of `div` elements… --> <h3 id='transformation_not_representation'>Transformation, not Representation</h3> <p>D3 does not provide a new graphical representation—unlike <a href='http://processing.org/'>Processing</a>, <a href='http://raphaeljs.com/'>Raphaël</a>, or <a href='http://vis.stanford.edu/protovis/'>Protovis</a>, there is no new vocabulary of marks to learn. Instead, you build directly on standards such as CSS3, HTML5 and SVG. This approach offers numerous advantages. You have full access to the underlying browser&#8217;s functionality; for example, you can create elements using D3, and then style them with external stylesheets. You can use advanced filters such as dashed strokes and composite filter effects. If browser makers introduce new features to CSS tomorrow, you&#8217;ll be able to use them immediately rather than waiting for a toolkit update. And, if you decide in the future to use a toolkit other than D3, you can take your enhanced knowledge of open standards with you!</p> <p>Consider the wheel. In Processing, you create a circle using the <code>ellipse</code> operator, which takes four arguments: the <em>x</em> and <em>y</em> of the ellipse center, and the <em>width</em> and <em>height</em>. Raphaël provides an <code>ellipse</code> operator with the same arguments, and a <code>circle</code> operator that takes three arguments using <em>radius</em>. Protovis defines <code>pv.Dot</code> and <code>pv.Wedge</code> mark types. D3, in contast, does not reinvent the wheel, instead using the standard <code>svg:circle</code> element:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>svg</span><span class='p'>.</span><span class='nx'>append</span><span class='p'>(</span><span class='s2'>&quot;svg:circle&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>attr</span><span class='p'>(</span><span class='s2'>&quot;cx&quot;</span><span class='p'>,</span> <span class='mi'>50</span><span class='p'>)</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>attr</span><span class='p'>(</span><span class='s2'>&quot;cy&quot;</span><span class='p'>,</span> <span class='mi'>40</span><span class='p'>)</span> <span class='lineno'>4</span> <span class='p'>.</span><span class='nx'>attr</span><span class='p'>(</span><span class='s2'>&quot;r&quot;</span><span class='p'>,</span> <span class='mi'>10</span><span class='p'>);</span> </code></pre> </div> <p>Because D3 does not specify a particular representation of circle, you can define alternate forms that may offer better performance or compatibility, such as pure HTML:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>body</span><span class='p'>.</span><span class='nx'>append</span><span class='p'>(</span><span class='s2'>&quot;div&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;position&quot;</span><span class='p'>,</span> <span class='s2'>&quot;absolute&quot;</span><span class='p'>)</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;left&quot;</span><span class='p'>,</span> <span class='s2'>&quot;40px&quot;</span><span class='p'>)</span> <span class='lineno'>4</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;top&quot;</span><span class='p'>,</span> <span class='s2'>&quot;30px&quot;</span><span class='p'>)</span> <span class='lineno'>5</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;width&quot;</span><span class='p'>,</span> <span class='s2'>&quot;20px&quot;</span><span class='p'>)</span> <span class='lineno'>6</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;height&quot;</span><span class='p'>,</span> <span class='s2'>&quot;20px&quot;</span><span class='p'>)</span> <span class='lineno'>7</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;border-radius&quot;</span><span class='p'>,</span> <span class='s2'>&quot;10px&quot;</span><span class='p'>)</span> <span class='lineno'>8</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;background-color&quot;</span><span class='p'>,</span> <span class='s2'>&quot;#000&quot;</span><span class='p'>);</span> </code></pre> </div> <p>D3 is easy to debug using the browser&#8217;s built-in inspector: the nodes that you manipulate are exactly those that can be inspected natively by the browser. Furthermore, operations are applied immediately (within the scope of operators such as <code>style</code>), and the selection object is an array of nodes.</p> <h3 id='transitions'>Transitions</h3> <p>Given D3&#8217;s focus on manipulation—not just a one-time mapping of data to a static representation—it naturally includes support for smooth transitions. These are gradual interpolation of styles or attributes over time. Various easing functions are provided to vary tweening, such as &#8220;elastic&#8221;, &#8220;cubic-in-out&#8221; and &#8220;linear&#8221;. D3 knows how to interpolate basic types, such as numbers and numbers embedded within strings (font sizes, path data, <em>etc.</em>). You can provide your own interpolator to extend transitions to more complex properties, such as a backing data structure.</p> <p>Transitions are trivially created from selections via the <code>transition</code> operator. To fade the background of the page to black, say:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>select</span><span class='p'>(</span><span class='s2'>&quot;body&quot;</span><span class='p'>).</span><span class='nx'>transition</span><span class='p'>()</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>style</span><span class='p'>(</span><span class='s2'>&quot;background-color&quot;</span><span class='p'>,</span> <span class='s2'>&quot;black&quot;</span><span class='p'>);</span> </code></pre> </div> <p>You can use CSS3 transitions, too! D3 does not replace the browser&#8217;s toolbox, but instead exposes it in a way that is easier to use. A more complex resizing of circles in a symbol map can still be expressed succinctly:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;circle&quot;</span><span class='p'>).</span><span class='nx'>transition</span><span class='p'>()</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>duration</span><span class='p'>(</span><span class='mi'>750</span><span class='p'>)</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>delay</span><span class='p'>(</span><span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>,</span> <span class='nx'>i</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nx'>i</span> <span class='o'>*</span> <span class='mi'>10</span><span class='p'>;</span> <span class='p'>})</span> <span class='lineno'>4</span> <span class='p'>.</span><span class='nx'>attr</span><span class='p'>(</span><span class='s2'>&quot;r&quot;</span><span class='p'>,</span> <span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nb'>Math</span><span class='p'>.</span><span class='nx'>sqrt</span><span class='p'>(</span><span class='nx'>d</span> <span class='o'>*</span> <span class='nx'>scale</span><span class='p'>);</span> <span class='p'>});</span> </code></pre> </div> <p>The transition&#8217;s duration and delay parameters can be customized, and as with other properties, specified as functions of data. This is particularly convenient for running a staggered delay by index (<code>i</code>), allowing the viewer to follow individual elements across the transition more easily.</p> <p>By dirtying only the attributes that actually change during the transition, D3 eliminates any overhead, allowing greater graphical complexity and higher frame rates. Transitions dispatch an event on end that allows sequencing of complex multi-stage transitions.</p> <h3 id='subselections'>Subselections</h3> <p>Most documents have some hierarchical structure. For example, what if you wanted to first select all lists, and then select all their list items? By calling <code>selectAll</code> on an existing selection, you generate a subselection for each node:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;ul&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;li&quot;</span><span class='p'>)</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>text</span><span class='p'>(</span><span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>,</span> <span class='nx'>i</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='s2'>&quot;I&#39;m number &quot;</span> <span class='o'>+</span> <span class='nx'>i</span> <span class='o'>+</span> <span class='s2'>&quot;!&quot;</span><span class='p'>;</span> <span class='p'>});</span> </code></pre> </div> <p>The result of the first <code>selectAll</code> contains all <code>ul</code> elements, while the second contains all <code>li</code> elements that are within <code>ul</code> elements. This results in a simple tree structure that mirrors the document:</p> <p><img src='subselectAll.png' alt='subselect' /></p> <p>The second selection is <em>grouped</em> according to the first selection: the index (<code>i</code>) for the list items (<code>li</code> elements) corresponds to their index <em>within</em> the list, rather than across all lists. By grouping elements, D3 allows you to maintain the hierarchical structure as you recursively descend into the document.</p> <p>For example, if your associated data is hierarchical—say a list of multiple choice questions, each with a set of possible responses—you can map the list of questions to the first <code>ul</code> selection, and then each set of responses to the groups in the second <code>li</code> selection. The <code>data</code> property is evaluated for each group of the subselection:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;ul&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>data</span><span class='p'>(</span><span class='nx'>questions</span><span class='p'>)</span> <span class='c1'>// an array of questions</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;li&quot;</span><span class='p'>)</span> <span class='lineno'>4</span> <span class='p'>.</span><span class='nx'>data</span><span class='p'>(</span><span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nx'>d</span><span class='p'>.</span><span class='nx'>responses</span><span class='p'>;</span> <span class='p'>})</span> <span class='c1'>// a nested array of responses</span> <span class='lineno'>5</span> <span class='p'>.</span><span class='nx'>text</span><span class='p'>(</span><span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nx'>d</span><span class='p'>.</span><span class='nx'>text</span><span class='p'>;</span> <span class='p'>});</span> <span class='c1'>// the text of the response</span> </code></pre> </div> <p>Thus, the <code>data</code> property can <em>also</em> be defined as a function, taking as an argument the data associated with the parent node. By combining subselection with the <code>enter</code> and <code>exit</code> operators, you can use D3 to construct and update complex hierarchical documents with a minimum amount of code.</p> <!-- Whereas `selectAll` groups the subselection by the parent node (the list element in the above example), the `select` operator maintains the original grouping. Thus, if we replace the second `selectAll` with a `select`, we will instead obtain a flat selection of the first list items within each list: ![subselect](subselect.png) Subselections are obtained by calling `select` or `selectAll` on an existing selection. (Conceptually, the `d3` global is a singleton selection of the root `document`.) When `select` is used, the specified selector is queried on each of the nodes in the existing selection. The returned selection has the same number of nodes as the original selection. For example, to select the first bold (`b`) element within all paragraph (`p`) elements: <div class="highlight"><pre><code class="js"><span class="lineno">1</span> <span class="nx">d3</span><span class="p">.</span><span class="nx">selectAll</span><span class="p">(</span><span class="s2">&quot;p&quot;</span><span class="p">)</span> <span class="lineno">2</span> <span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s2">&quot;b&quot;</span><span class="p">);</span> </code></pre> </div> With `selectAll`, the returned selection contains *all* matching nodes, for *each* node in the original selection, so grouped. Thus, in the photo-sharing example above, the index (`i`) for the image elements is of the array of photos, whereas the corresponding index for the parent div elements is of the array of albums. --> <h3 id='data_keys'>Data Keys</h3> <p>With static documents, it often suffices to map data elements to nodes by index. However, if your data changes you may need to rebind new data to existing nodes. In this case you provide a key function to the <code>data</code> operator; data is rebound to nodes by matching string keys on the old and new data. For example:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;ul&quot;</span><span class='p'>)</span> <span class='lineno'>2</span> <span class='p'>.</span><span class='nx'>data</span><span class='p'>(</span><span class='nx'>data</span><span class='p'>,</span> <span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nx'>d</span><span class='p'>.</span><span class='nx'>id</span><span class='p'>;</span> <span class='p'>});</span> </code></pre> </div> <p>The key function also determines the enter and exit selections: the new data for which there is no corresponding key in the old data become the enter selection, and the old data for which there is no corresponding key in the new data become the exit selection. The remaining data become the default update selection.</p> <p>To continue the previous example of a multiple-choice test, here is the skeleton code to update the state of the document to match the array of questions:</p> <div class='highlight'><pre><code class='js'><span class='lineno'>1</span> <span class='c1'>// Update…</span> <span class='lineno'>2</span> <span class='kd'>var</span> <span class='nx'>ul</span> <span class='o'>=</span> <span class='nx'>d3</span><span class='p'>.</span><span class='nx'>selectAll</span><span class='p'>(</span><span class='s2'>&quot;ul&quot;</span><span class='p'>)</span> <span class='lineno'>3</span> <span class='p'>.</span><span class='nx'>data</span><span class='p'>(</span><span class='nx'>data</span><span class='p'>,</span> <span class='kd'>function</span><span class='p'>(</span><span class='nx'>d</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nx'>d</span><span class='p'>.</span><span class='nx'>id</span><span class='p'>;</span> <span class='p'>});</span> <span class='lineno'>4</span> <span class='lineno'>5</span> <span class='c1'>// Enter…</span> <span class='lineno'>6</span> <span class='nx'>ul</span><span class='p'>.</span><span class='nx'>enter</span><span class='p'>().</span><span class='nx'>append</span><span class='p'>(</span><span class='s2'>&quot;ul&quot;</span><span class='p'>);</span> <span class='lineno'>7</span> <span class='lineno'>8</span> <span class='c1'>// Exit…</span> <span class='lineno'>9</span> <span class='nx'>ul</span><span class='p'>.</span><span class='nx'>exit</span><span class='p'>().</span><span class='nx'>remove</span><span class='p'>();</span> </code></pre> </div> <p>For more on data keys, see <a href='tutorial/bar-2.html'>part 2</a> of the bar chart tutorial.</p> <h3 id='modules'>Modules</h3> <p>D3 is highly extensible, with optional modules available as needed, without bloating the core library. The only required feature of D3 is the selection implementation, along with transitions. For convenience, the default <code>d3.js</code> file also includes standard SVG shape generators and utilities, such as scales and data transformations.</p> <p>Several additional modules are available that are not included in the default build. The <code>geo</code> module adds support for geographic data, such as translating GeoJSON into SVG path data. The Albers equal-area projection is included in this module, as it is well-suited to choropleth maps. The <code>geom</code> module includes several computational geometry utilities, such as algorithms for Voronoi diagrams and convex hulls. The <code>csv</code> module supports reading and writing comma-separated values, a common alternative to <a href='http://www.json.org/'>JSON</a>. Lastly, the <code>layout</code> module includes various reusable visualization layouts, such as force-directed graphs, treemaps, and chord diagrams.</p> </div> <div class="foot">Copyright &copy; 2011 <a href="http://bost.ocks.org/mike">Mike Bostock</a></div> </div> </div> <a href="http://github.com/mbostock/d3"><img style="position:absolute;top:0;right:0;border:0;" width="149" height="149" src="forkme.png" alt="Fork me on GitHub" /></a> </body> </html>