D3: Binding Data

Introduction

In my previous article, Meet D3: Data Driven Documents, I discussed my experience learning D3, in particular, discovering what D3 is not: it is not, strictly speaking, a SVG library. You will not find a function in the library to draw a circle or rectangle. Instead, you use its powerful selections interface to manipulate the DOM.

For example, assuming the DOM contains this element:

<svg id="mychart"></svg>

If we want to add a green circle with radius 10px at point (100,100), there is no draw-a-circle function in D3. Instead we do this:

d3.select('#mychart')
.append('circle')
.attr('cx', 100)
.attr('cy', 100)
.attr('r', 10)
.attr('fill', 'green');

After the above, the DOM will look like this:

<svg id="mychart">
<circle cx="100" cy="100" r="10" fill="green"></circle>
</svg>

What I found confusing (and countless questions on the internets suggest I was not alone) was all the functions in the D3 library under the d3.svg namespace. What do you mean d3.svg.line doesn’t draw a line? It isn’t until you fully grok D3’s powerful data binding paradigm that those functions begin to make sense.

Data Binding

You will read in many D3 tutorials that selections and data joins are the heart and soul of D3. A quick review: selection.data() takes up to two arguments:

selection.data([values[, key]])

With arguments, the specified values are bound to the selection and stored as a property on the node(s), data. With no arguments, data() returns the previously bound data to the selection (data).

The first argument, values, is an array of elements to be bound to the selection. It can also be a function that returns a computed array. The second, optional, argument is a key function to match elements in the array with previously bound data to the same selection. It takes the form:

key([d[,i]])

The key function returns a string that uniquely defines one element in the data.

The key function is called in two phases. In the first, it is called across all previously bound data in the selection, building an internal, temporary mapping, key-to-node. The second pass calls the key function for each item in values, the passed in array, attempting to match items against the key-to-node mapping:

  • nodes in key-to-node found by keys generated from values are current nodes and added to the update selection.
  • nodes not found in key-to-node by keys generated from values are new and added to the enter selection.
  • items remaining in key-to-node, not in values, are old items and added to the exit selection.

For each call to the key function, the first argument, d, is a datum in the data (either the previously bound array of data, or the passed in array, depending on the phase), and i is the index into the array. The this context is different for each phase: in the first phase this points to the current node, in the second phase, the values array.

If key is not specified, the default is to match by index: the first item in the array is bound to the first element in the selection, and so on. In this case, either one or both of the enter and exit selections will be empty: if there are more items in values than previously bound, the enter selection will have the extra nodes from values and the exit selection will be empty; if there are fewer items in values than previously bound, the exit selection will have the extraneous nodes and the enter selection will be empty; if there are exactly the same number of items, both will be empty.

The return value of data() is the update selection. Two functions attached to the update selection return the enter selection and exit selection, .enter() and .exit(), respectively.

Further detail about data joins can be found here.

The Update Pattern

There is a very common pattern of usage with update selections you will see across D3 code. Let’s say we have an array of data describing widgets which we plan to visualize as circles, [w1, w2, w3, …], where each object in the array has the following properties:

{
model: // a unique string we can use as an ID
info: // textual information about the widget

// and visualization information, for our circle
x: // x value of center
y: // y value of center
r: // radius
c: // fill color
}

Let’s say these circles will be displayed inside a specific group:

widget_group = d3.select('#widget-display');

We select all circles with class widget and bind an array, widget_data:

widgets = widget_group.selectAll('circle.widget')
.data(widget_data, function(d) {return d.model;});

Note the use of the key function returning the model of each widget. At this point, widgets is an update selection, containing those widgets that had previously been bound. Assuming there are new items in widget_data, not previously bound, then the enter selection is non-empty. We use the enter selection to add the new items:

widgets.enter()
.append('circle')
.classed('widget', true);

The above will add a new circle, assigning it the specified class, for each datum in widget_data not previously bound. In addition, when using the append() function on an enter selection, the node is also added back into the update selection! This means we only need to do the minimal work necessary to add elements with the enter selection, leaving attribute manipulation to the update selection:

widgets
.attr(...)
.attr(...)
.attr(...);

Then, typically, we’ll use the exit selection to remove old nodes:

widgets.exit().remove();

So, the pattern will look something like this:

// acquire update selection
update = some_group.selectAll(*selector*);
// use enter selection to add elements
update.enter()
.append(*element*);
// operate on the update selection (which includes elements appended to the enter selection)
update.attr().attr().attr();
// remove elements found in the exit selection
update.exit().remove()

Mike Bostock, the author of D3, has a wonderful series of demos on the update pattern, each demo of the series building on the previous, creating visualizations that illustrate the update pattern in action.

Referencing Bound Data

As discussed, with D3 you manipulate visualization attributes by manipulating elements in the DOM. If we want to change all circles to green, we change the SVG fill attribute:

d3.selectAll('circle')
.attr('fill', 'green');

All the functions that manipulate content on a D3 selection can take static values (as shown above by using the string 'green'), but more powerfully, the values can be specified as functions of the form:

fn(d, i)

where d is the datum bound to the current node within the selection we are acting on, i is the index of d into the bound array of data, and the this context is the current node. For example, continuing with our array of widgets, we can manipulate attributes via functions that give access to our bound data:

widgets
.attr('cx', function(d) {return d.x;})
.attr('cy', function(d) {return d.y;})
.attr('r', function(d) {return d.r;})
.attr('fill', function(d) {return d.c;})
.attr('stroke', '#666')
.attr('stroke-width', 2);

Hopefully you can begin to see the data-driven-ness of D3.

d3.svg.line

So, if you were like me, you were at first confused by functions in the d3.svg namespace. I thought, "Oh, look, I can use d3.svg.line to draw my line!" Close, but not exactly.

Before exploring this function further, you need to have an understanding of SVG’s PATH element, in particular, its d attribute. Briefly, PATH describes a path to be drawn and the data for the path, along with the description of the shape of the path, is given by the d attribute. For example, to draw a straight line from (10,10) to (100,100):

<path d="M10,10L100,100" stroke="black"/>

Huh? The d attribute is a mini-language. The above says, "Move to 10,10, next, draw a line to 100,100." It’s a simple language, yet becomes quickly non-trivial to manage. (For details about PATH, see W3C’s reference documentation.)

For example, here’s a PATH element that draws a sine wave (the image at the top of this article):

<path d="M0,250L1,250.8726203218642L2,251.74497483512505L3,252.61679781214718L4,253.4878236872063L5,254.35778713738287L6,255.22642316338266L7,256.0934671702574L8,256.9586550480033L9,257.82172325201157L10,258.68240888334645L11,259.5404497688272L12,260.39558454088797L13,261.24755271719323L14,262.0960947799834L15,262.94095225512604L16,263.78186779085L17,264.61858523613677L18,265.4508497187474L19,266.2784077228578L20,267.1010071662834L21,267.91839747726505L22,268.7303296707956L23,269.5365564244637L24,270.33683215379L25,271.13091308703497L26,271.91855733945386L27,272.69952498697734L28,273.47357813929455L29,274.2404810123169L30,275L31,275.75190374550266L32,276.49596321166024L33,277.23195175075136L34,277.95964517353735L35,278.6788218175523L36,279.38926261462365L37,280.0907511576024L38,280.78307376628294L39,281.4660195524919L40,282.139380484327L41,282.8029514495253L42,283.4565303179429L43,284.0999180031249L44,284.73291852294983L45,285.35533905932743L46,285.9669900169325L47,286.56768508095854L48,287.1572412738697L49,287.7354790111386L50,288.3022221559489L51,288.85729807284855L52,289.4005376803361L53,289.9317755023646L54,290.45084971874735L55,290.9576022144496L56,291.45187862775214L57,291.93352839727123L58,292.4024048078213L59,292.85836503510563L60,293.3012701892219L61,293.73098535696977L62,294.14737964294636L63,294.5503262094184L64,294.93970231495837L65,295.3153893518325L66,295.67727288213007L67,296.025242672622L68,296.3591927283394L69,296.6790213248601L70,296.9846310392954L71,297.27592877996585L72,297.5528258147577L73,297.81523779815177L74,298.063084796916L75,298.29629131445347L76,298.51478631379985L77,298.71850323926174L78,298.90738003669026L79,299.0813591723832L80,299.2403876506104L81,299.38441702975695L82,299.5134034370785L83,299.62730758206607L84,299.72609476841365L85,299.8097349045873L86,299.87820251299127L87,299.9314767377287L88,299.9695413509548L89,299.99238475781954L90,300L91,299.99238475781954L92,299.9695413509548L93,299.9314767377287L94,299.87820251299127L95,299.8097349045873L96,299.72609476841365L97,299.6273075820661L98,299.5134034370785L99,299.38441702975695L100,299.2403876506104L101,299.0813591723832L102,298.90738003669026L103,298.71850323926174L104,298.51478631379985L105,298.29629131445347L106,298.063084796916L107,297.81523779815177L108,297.5528258147577L109,297.27592877996585L110,296.98463103929544L111,296.6790213248601L112,296.3591927283394L113,296.025242672622L114,295.67727288213007L115,295.3153893518325L116,294.93970231495837L117,294.5503262094184L118,294.14737964294636L119,293.73098535696977L120,293.3012701892219L121,292.85836503510563L122,292.4024048078213L123,291.93352839727123L124,291.45187862775214L125,290.9576022144496L126,290.45084971874735L127,289.9317755023646L128,289.4005376803361L129,288.85729807284855L130,288.3022221559489L131,287.7354790111386L132,287.1572412738697L133,286.56768508095854L134,285.9669900169325L135,285.35533905932743L136,284.73291852294983L137,284.09991800312497L138,283.4565303179429L139,282.8029514495253L140,282.139380484327L141,281.4660195524919L142,280.78307376628294L143,280.0907511576024L144,279.38926261462365L145,278.6788218175523L146,277.95964517353735L147,277.23195175075136L148,276.49596321166024L149,275.7519037455027L150,275L151,274.2404810123169L152,273.4735781392945L153,272.69952498697734L154,271.91855733945386L155,271.13091308703497L156,270.33683215379L157,269.5365564244637L158,268.7303296707956L159,267.91839747726505L160,267.10100716628347L161,266.2784077228578L162,265.4508497187474L163,264.61858523613677L164,263.78186779085L165,262.94095225512604L166,262.0960947799834L167,261.24755271719323L168,260.39558454088797L169,259.5404497688273L170,258.68240888334645L171,257.82172325201157L172,256.9586550480033L173,256.0934671702574L174,255.22642316338266L175,254.35778713738287L176,253.4878236872063L177,252.61679781214718L178,251.74497483512505L179,250.8726203218642L180,250L181,249.12737967813584L182,248.25502516487495L183,247.38320218785282L184,246.5121763127937L185,245.6422128626171L186,244.77357683661734L187,243.90653282974264L188,243.04134495199673L189,242.17827674798843L190,241.3175911166535L191,240.45955023117276L192,239.604415459112L193,238.75244728280674L194,237.9039052200166L195,237.05904774487396L196,236.21813220915004L197,235.38141476386318L198,234.54915028125262L199,233.72159227714215L200,232.89899283371656L201,232.08160252273495L202,231.2696703292044L203,230.46344357553633L204,229.66316784621L205,228.86908691296503L206,228.08144266054612L207,227.30047501302266L208,226.52642186070543L209,225.75951898768315L210,225L211,224.2480962544973L212,223.50403678833976L213,222.7680482492486L214,222.04035482646267L215,221.3211781824477L216,220.61073738537635L217,219.90924884239757L218,219.2169262337171L219,218.5339804475081L220,217.86061951567302L221,217.19704855047468L222,216.5434696820571L223,215.90008199687512L224,215.26708147705014L225,214.64466094067262L226,214.03300998306744L227,213.4323149190415L228,212.84275872613028L229,212.2645209888614L230,211.6977778440511L231,211.14270192715145L232,210.59946231966393L233,210.06822449763538L234,209.54915028125262L235,209.0423977855504L236,208.5481213722479L237,208.0664716027288L238,207.59759519217874L239,207.14163496489437L240,206.69872981077808L241,206.2690146430302L242,205.85262035705364L243,205.4496737905816L244,205.06029768504166L245,204.6846106481675L246,204.32272711786996L247,203.97475732737797L248,203.6408072716606L249,203.32097867513994L250,203.01536896070454L251,202.72407122003418L252,202.44717418524232L253,202.18476220184823L254,201.93691520308406L255,201.7037086855466L256,201.48521368620015L257,201.28149676073824L258,201.09261996330972L259,200.91864082761683L260,200.7596123493896L261,200.6155829702431L262,200.4865965629215L263,200.37269241793388L264,200.27390523158633L265,200.19026509541274L266,200.1217974870088L267,200.0685232622713L268,200.0304586490452L269,200.00761524218044L270,200L271,200.00761524218044L272,200.0304586490452L273,200.0685232622713L274,200.1217974870088L275,200.19026509541274L276,200.27390523158633L277,200.37269241793393L278,200.4865965629215L279,200.61558297024308L280,200.7596123493896L281,200.91864082761683L282,201.09261996330972L283,201.28149676073824L284,201.48521368620015L285,201.7037086855466L286,201.93691520308406L287,202.18476220184823L288,202.44717418524232L289,202.72407122003415L290,203.0153689607046L291,203.3209786751399L292,203.6408072716606L293,203.97475732737797L294,204.32272711786996L295,204.6846106481675L296,205.06029768504166L297,205.4496737905816L298,205.85262035705364L299,206.2690146430302L300,206.69872981077808L301,207.14163496489437L302,207.5975951921787L303,208.0664716027288L304,208.54812137224792L305,209.0423977855504L306,209.54915028125262L307,210.06822449763536L308,210.59946231966393L309,211.14270192715145L310,211.6977778440511L311,212.2645209888614L312,212.84275872613026L313,213.4323149190415L314,214.03300998306744L315,214.64466094067262L316,215.26708147705014L317,215.90008199687512L318,216.5434696820571L319,217.19704855047462L320,217.86061951567302L321,218.5339804475081L322,219.2169262337171L323,219.90924884239757L324,220.61073738537635L325,221.32117818244765L326,222.04035482646267L327,222.7680482492486L328,223.50403678833976L329,224.24809625449726L330,225L331,225.75951898768315L332,226.52642186070543L333,227.30047501302266L334,228.08144266054612L335,228.86908691296503L336,229.66316784621L337,230.4634435755363L338,231.2696703292044L339,232.08160252273495L340,232.89899283371656L341,233.72159227714215L342,234.54915028125262L343,235.38141476386315L344,236.21813220915004L345,237.05904774487396L346,237.9039052200166L347,238.75244728280674L348,239.604415459112L349,240.45955023117276L350,241.3175911166535L351,242.17827674798843L352,243.04134495199673L353,243.90653282974264L354,244.77357683661734L355,245.6422128626171L356,246.5121763127937L357,247.38320218785276L358,248.25502516487495L359,249.12737967813584L360,250L361,250.8726203218642L362,251.74497483512508L363,252.61679781214718L364,253.48782368720623L365,254.35778713738287L366,255.22642316338263L367,256.0934671702574L368,256.9586550480033L369,257.8217232520115L370,258.68240888334645L371,259.5404497688273L372,260.39558454088797L373,261.24755271719323L374,262.09609477998333L375,262.940952255126L376,263.78186779085L377,264.61858523613677L378,265.4508497187474L379,266.2784077228578L380,267.10100716628347L381,267.91839747726505L382,268.7303296707956L383,269.5365564244637L384,270.33683215379L385,271.13091308703497L386,271.91855733945386L387,272.69952498697734L388,273.4735781392945L389,274.2404810123169L390,275L391,275.75190374550266L392,276.49596321166024L393,277.23195175075136L394,277.95964517353735L395,278.6788218175523L396,279.38926261462365L397,280.0907511576024L398,280.78307376628294L399,281.4660195524919L400,282.139380484327L401,282.8029514495253L402,283.4565303179429L403,284.09991800312497L404,284.73291852294983L405,285.3553390593274L406,285.9669900169325L407,286.56768508095854L408,287.1572412738697L409,287.7354790111386L410,288.3022221559489L411,288.85729807284855L412,289.4005376803361L413,289.9317755023646L414,290.45084971874735L415,290.95760221444954L416,291.45187862775214L417,291.93352839727123L418,292.40240480782126L419,292.85836503510563L420,293.30127018922195L421,293.73098535696977L422,294.14737964294636L423,294.5503262094184L424,294.93970231495837L425,295.3153893518325L426,295.67727288213007L427,296.025242672622L428,296.3591927283394L429,296.6790213248601L430,296.98463103929544L431,297.27592877996585L432,297.5528258147577L433,297.81523779815177L434,298.063084796916L435,298.29629131445347L436,298.51478631379985L437,298.71850323926174L438,298.90738003669026L439,299.0813591723832L440,299.2403876506104L441,299.3844170297569L442,299.5134034370785L443,299.6273075820661L444,299.72609476841365L445,299.8097349045873L446,299.87820251299127L447,299.9314767377287L448,299.9695413509548L449,299.99238475781954L450,300L451,299.99238475781954L452,299.9695413509548L453,299.9314767377287L454,299.87820251299127L455,299.8097349045873L456,299.72609476841365L457,299.62730758206607L458,299.5134034370785L459,299.3844170297569L460,299.2403876506104L461,299.0813591723832L462,298.90738003669026L463,298.71850323926174L464,298.5147863137998L465,298.29629131445347L466,298.063084796916L467,297.81523779815177L468,297.5528258147577L469,297.27592877996585L470,296.98463103929544L471,296.6790213248601L472,296.3591927283394L473,296.025242672622L474,295.67727288213L475,295.3153893518325L476,294.93970231495837L477,294.55032620941836L478,294.14737964294636L479,293.73098535696977L480,293.30127018922195L481,292.85836503510563L482,292.40240480782126L483,291.93352839727123L484,291.4518786277521L485,290.95760221444965L486,290.45084971874735L487,289.9317755023646L488,289.40053768033613L489,288.85729807284855L490,288.3022221559489L491,287.7354790111386L492,287.1572412738697L493,286.56768508095854L494,285.9669900169325L495,285.3553390593274L496,284.73291852294983L497,284.0999180031249L498,283.4565303179429L499,282.8029514495254L500,282.139380484327L501,281.4660195524919L502,280.78307376628294L503,280.0907511576025L504,279.38926261462365L505,278.6788218175523L506,277.9596451735374L507,277.23195175075136L508,276.49596321166024L509,275.7519037455027L510,275L511,274.2404810123169L512,273.47357813929455L513,272.69952498697734L514,271.9185573394539L515,271.13091308703497L516,270.33683215379006L517,269.5365564244637L518,268.7303296707956L519,267.91839747726505L520,267.1010071662834L521,266.2784077228578L522,265.4508497187474L523,264.61858523613677L524,263.78186779085L525,262.94095225512604L526,262.09609477998333L527,261.24755271719323L528,260.39558454088797L529,259.5404497688273L530,258.68240888334645L531,257.8217232520115L532,256.9586550480033L533,256.0934671702574L534,255.22642316338272L535,254.35778713738287L536,253.48782368720623L537,252.61679781214724L538,251.74497483512505L539,250.87262032186413L540,250L541,249.12737967813584L542,248.255025164875L543,247.38320218785282L544,246.5121763127937L545,245.6422128626171L546,244.77357683661734L547,243.90653282974267L548,243.04134495199673L549,242.17827674798843L550,241.3175911166535L551,240.45955023117276L552,239.60441545911206L553,238.7524472828068L554,237.9039052200166L555,237.05904774487402L556,236.21813220915004L557,235.38141476386315L558,234.54915028125262L559,233.72159227714215L560,232.89899283371662L561,232.08160252273495L562,231.26967032920436L563,230.46344357553633L564,229.66316784621L565,228.8690869129651L566,228.08144266054614L567,227.3004750130226L568,226.52642186070548L569,225.75951898768315L570,225.00000000000003L571,224.2480962544973L572,223.5040367883397L573,222.76804824924866L574,222.04035482646267L575,221.32117818244765L576,220.61073738537638L577,219.90924884239757L578,219.21692623371715L579,218.5339804475081L580,217.86061951567302L581,217.19704855047468L582,216.5434696820571L583,215.90008199687512L584,215.26708147705014L585,214.64466094067262L586,214.03300998306744L587,213.4323149190415L588,212.84275872613028L589,212.2645209888614L590,211.69777784405105L591,211.1427019271515L592,210.59946231966393L593,210.06822449763536L594,209.54915028125262L595,209.0423977855504L596,208.54812137224792L597,208.06647160272883L598,207.5975951921787L599,207.14163496489437L600,206.69872981077808L601,206.26901464303023L602,205.85262035705364L603,205.4496737905816L604,205.06029768504166L605,204.6846106481675L606,204.32272711786996L607,203.97475732737797L608,203.6408072716606L609,203.32097867513994L610,203.01536896070454L611,202.72407122003415L612,202.44717418524232L613,202.18476220184823L614,201.93691520308406L615,201.7037086855466L616,201.48521368620015L617,201.28149676073824L618,201.09261996330972L619,200.91864082761683L620,200.7596123493896L621,200.61558297024308L622,200.4865965629215L623,200.37269241793388L624,200.27390523158633L625,200.19026509541274L626,200.1217974870088L627,200.0685232622713L628,200.0304586490452L629,200.00761524218044L630,200L631,200.00761524218044L632,200.0304586490452L633,200.0685232622713L634,200.1217974870088L635,200.19026509541274L636,200.27390523158633L637,200.37269241793388L638,200.4865965629215L639,200.6155829702431L640,200.7596123493896L641,200.91864082761683L642,201.09261996330972L643,201.28149676073824L644,201.4852136862002L645,201.7037086855466L646,201.93691520308406L647,202.18476220184823L648,202.44717418524232L649,202.72407122003418L650,203.01536896070454L651,203.3209786751399L652,203.6408072716606L653,203.97475732737797L654,204.32272711786996L655,204.6846106481675L656,205.06029768504166L657,205.4496737905816L658,205.85262035705364L659,206.2690146430302L660,206.69872981077802L661,207.14163496489437L662,207.59759519217874L663,208.0664716027288L664,208.5481213722479L665,209.04239778555046L666,209.54915028125262L667,210.06822449763538L668,210.59946231966387L669,211.14270192715145L670,211.6977778440511L671,212.2645209888614L672,212.84275872613028L673,213.43231491904143L674,214.03300998306744L675,214.64466094067265L676,215.26708147705014L677,215.90008199687512L678,216.54346968205704L679,217.19704855047462L680,217.86061951567308L681,218.5339804475081L682,219.2169262337171L683,219.90924884239763L684,220.61073738537635L685,221.3211781824477L686,222.04035482646262L687,222.7680482492486L688,223.50403678833976L689,224.24809625449726L690,225L691,225.7595189876831L692,226.52642186070543L693,227.30047501302266L694,228.08144266054612L695,228.86908691296503L696,229.66316784620994L697,230.4634435755363L698,231.2696703292044L699,232.08160252273493L700,232.89899283371656L701,233.7215922771422L702,234.5491502812526L703,235.38141476386318L704,236.21813220914999L705,237.05904774487396L706,237.90390522001664L707,238.75244728280674L708,239.604415459112L709,240.4595502311727L710,241.31759111665346L711,242.17827674798846L712,243.04134495199668L713,243.90653282974264L714,244.77357683661728L715,245.6422128626171L716,246.51217631279377L717,247.38320218785276L718,248.25502516487495L719,249.12737967813587L720,249.99999999999994L721,250.8726203218642L722,251.744974835125L723,252.61679781214718L724,253.4878236872063L725,254.35778713738287L726,255.22642316338266L727,256.0934671702573L728,256.95865504800327L729,257.82172325201157L730,258.68240888334645L731,259.5404497688272L732,260.3955845408879L733,261.24755271719323L734,262.0960947799834L735,262.940952255126L736,263.78186779084996L737,264.6185852361368L738,265.45084971874735L739,266.2784077228578L740,267.10100716628335L741,267.91839747726505L742,268.73032967079564L743,269.5365564244637L744,270.33683215379L745,271.1309130870349L746,271.91855733945386L747,272.69952498697734L748,273.4735781392945L749,274.2404810123169L750,274.99999999999994L751,275.75190374550266L752,276.49596321166024L753,277.2319517507513L754,277.95964517353735L755,278.6788218175523L756,279.3892626146236L757,280.0907511576024L758,280.7830737662829L759,281.4660195524919L760,282.139380484327L761,282.8029514495253L762,283.4565303179429L763,284.0999180031249L764,284.73291852294983L765,285.35533905932743L766,285.96699001693247L767,286.56768508095854L768,287.1572412738698L769,287.7354790111385L770,288.3022221559489L771,288.8572980728485L772,289.4005376803361L773,289.93177550236464L774,290.45084971874735L775,290.9576022144496L776,291.4518786277521L777,291.9335283972712L778,292.4024048078213L779,292.8583650351056L780,293.3012701892219L781,293.7309853569697L782,294.14737964294636L783,294.5503262094184L784,294.93970231495837L785,295.3153893518325L786,295.67727288213007L787,296.025242672622L788,296.3591927283394L789,296.67902132486006L790,296.9846310392954L791,297.2759287799659L792,297.5528258147577L793,297.81523779815177L794,298.063084796916L795,298.2962913144534L796,298.51478631379985L797,298.71850323926174L798,298.90738003669026L799,299.0813591723832L800,299.2403876506104L801,299.38441702975695L802,299.5134034370785L803,299.62730758206607L804,299.72609476841365L805,299.8097349045873L806,299.87820251299127L807,299.9314767377287L808,299.9695413509548L809,299.99238475781954L810,300L811,299.99238475781954L812,299.9695413509548L813,299.9314767377287L814,299.87820251299127L815,299.8097349045873L816,299.72609476841365L817,299.6273075820661L818,299.5134034370785L819,299.3844170297569L820,299.2403876506104L821,299.0813591723832L822,298.90738003669026L823,298.71850323926174L824,298.5147863137998L825,298.29629131445347L826,298.063084796916L827,297.81523779815177L828,297.5528258147577L829,297.27592877996585L830,296.98463103929544L831,296.6790213248601L832,296.3591927283394L833,296.025242672622L834,295.67727288213007L835,295.3153893518325L836,294.93970231495837L837,294.55032620941836L838,294.14737964294636L839,293.73098535696977L840,293.3012701892219L841,292.85836503510563L842,292.40240480782126L843,291.93352839727123L844,291.45187862775214L845,290.95760221444954L846,290.45084971874735L847,289.9317755023646L848,289.40053768033613L849,288.85729807284855L850,288.3022221559489L851,287.7354790111386L852,287.1572412738697L853,286.56768508095854L854,285.9669900169325L855,285.3553390593274L856,284.7329185229499L857,284.09991800312497L858,283.4565303179429L859,282.8029514495254L860,282.139380484327L861,281.4660195524919L862,280.78307376628294L863,280.0907511576024L864,279.38926261462365L865,278.6788218175523L866,277.9596451735374L867,277.23195175075136L868,276.49596321166024L869,275.7519037455027L870,275L871,274.2404810123169L872,273.47357813929455L873,272.69952498697734L874,271.9185573394539L875,271.13091308703497L876,270.33683215378994L877,269.5365564244637L878,268.7303296707956L879,267.9183974772651L880,267.10100716628347L881,266.2784077228578L882,265.45084971874746L883,264.61858523613677L884,263.78186779085L885,262.94095225512604L886,262.09609477998333L887,261.24755271719323L888,260.39558454088797L889,259.5404497688273L890,258.6824088833465L891,257.8217232520115L892,256.9586550480033L893,256.0934671702574L894,255.22642316338263L895,254.35778713738293L896,253.48782368720623L897,252.61679781214724L898,251.74497483512508L899,250.8726203218642L900,250.00000000000006L901,249.12737967813584L902,248.255025164875L903,247.38320218785282L904,246.5121763127937L905,245.64221286261716L906,244.77357683661734L907,243.90653282974267L908,243.04134495199676L909,242.17827674798843L910,241.31759111665355L911,240.45955023117276L912,239.604415459112L913,238.7524472828068L914,237.9039052200166L915,237.05904774487402L916,236.21813220915004L917,235.38141476386323L918,234.5491502812526L919,233.72159227714215L920,232.89899283371662L921,232.08160252273493L922,231.2696703292044L923,230.46344357553633L924,229.6631678462101L925,228.86908691296497L926,228.08144266054614L927,227.30047501302275L928,226.52642186070543L929,225.75951898768315L930,225.00000000000003L931,224.2480962544972L932,223.5040367883397L933,222.76804824924866L934,222.04035482646276L935,221.32117818244765L936,220.61073738537638L937,219.90924884239766L938,219.21692623371706L939,218.53398044750816L940,217.86061951567308L941,217.19704855047462L942,216.5434696820571L943,215.90008199687514L944,215.26708147705008L945,214.64466094067262L946,214.03300998306747L947,213.43231491904152L948,212.84275872613026L949,212.26452098886145L950,211.69777784405113L951,211.1427019271514L952,210.59946231966393L953,210.06822449763538L954,209.5491502812526L955,209.0423977855504L956,208.54812137224792L957,208.0664716027288L958,207.5975951921787L959,207.1416349648944L960,206.69872981077813L961,206.2690146430302L962,205.85262035705364L963,205.4496737905816L964,205.0602976850416L965,204.6846106481675L966,204.32272711786996L967,203.97475732737797L968,203.6408072716606L969,203.32097867513994L970,203.0153689607046L971,202.72407122003415L972,202.44717418524232L973,202.1847622018483L974,201.93691520308406L975,201.7037086855466L976,201.4852136862002L977,201.28149676073824L978,201.09261996330972L979,200.91864082761683L980,200.7596123493896L981,200.61558297024308L982,200.4865965629215L983,200.37269241793393L984,200.27390523158633L985,200.19026509541274L986,200.1217974870088L987,200.0685232622713L988,200.0304586490452L989,200.00761524218044L990,200L991,200.00761524218044L992,200.0304586490452L993,200.0685232622713L994,200.1217974870088L995,200.19026509541274L996,200.27390523158633L997,200.37269241793393L998,200.4865965629215L999,200.61558297024308" fill="none" stroke="blue"/>

Imagine trying to generate that mini-language in your javascript code!!

That’s where d3.svg.line comes in. It is a function that returns a function that follows the pattern of the functions described above which can be used as the second argument to, e.g, selection.attr():

line = d3.svg.line();
some_path_element_selection
.attr('d', line);

Here’s a real example: imagine we have bound to an element (with .data()) an array of points that form our line, e.g:

line_data = [[10,10], [100,100], [200, 10], [300, 100]];
update = some_group.selectAll('path.myline').data([line_data]);

Note how the call to data() places line_data into a one-element array. The call to data expects an array and we have one line to join (which happens to be an array of two-element arrays).

Then, using the update pattern:

update.enter()
.append('path')
.classed('myline', true);
update.attr({d: d3.svg.line(),
fill: 'none',
stroke: 'blue'
});

The above draws this:

path


So, in the end, the functions in d3.svg do draw shapes, albeit indirectly, by creating functions that generate the difficult-to-manage path mini-language based on bound data.

Attributes of the line functions

The above showed drawing a line where x,y coordinates are given as two-element arrays and the lines are drawn as straight lines where the x and y values map directly to the SVG coordinate space. This is the default behavior of the function returned by d3.svg.line(). What if your coordinates are not given as an array, but properties on an object? What if you want a differently shaped line? Or your x and y values are in some value domain that is wildly different than your SVG coordinate space?

The output of d3.svg.line() is a function. That function has its own accessors to get/set attributes of the line it will generate. For example, if your line is an array of objects, with x and y coordinates given as properties, then:

line = d3.svg.line()
.x(function(d) {return d.x;})
.y(function(d) {return d.y;});

For each element in the line’s array, these functions will be called with d as the current element. These functions can be used not only to access data in non-default ways, but to scale x and y to your chart’s coordinate space:

xscale = d3.scale.linear()
.domain([50,250]) // the domain is the low/high values found in the data
.range([0,1000]); // the range is the low/high values output (the visual x coord range)

line = d3.svg.line()
// return the scaled x property
.x(function(d) {return xscale(d.x);})

Details of line attributes can be found in D3’s documentation.

Summary

Understanding D3’s data binding process is key to exploiting D3’s core functionality. Using the update pattern is a powerful paradigm for generating dynamic, data driven documents, especially when used in conjunction with the rich functions found in the d3.svg namespace which can manage the cumbersome d attribute of SVG’s PATH element.

Daniel Popowich

Daniel Popowich

Daniel is a Sr Software Engineer for Art & Logic.
Daniel Popowich

Latest posts by Daniel Popowich (see all)

Tags:

Creative Commons License

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.