D3 on AngularJS: Create Dynamic Visualizations with AngularJS (2014)
SVG basics
The first section of this chapter provides an introduction to SVG, a powerful open web standard for creating vector graphics in the browser. In the second half of this chapter, we’ll highlight the D3 helper functions that make working with SVG fun and manageable.
Scalable Vector Graphics
Although D3 can easily help us create and draw div elements, our visualizations generally require much more horsepower. We’ll use Scalable Vector Graphics (or SVG for short) to give us a much more expressive interface for drawing in the DOM.
SVG is, like HTML, is an XML-based markup language created specifically for creating vector-based two-dimensional graphics that has support for interactivity and animation.
Traditional graphics systems, or raster graphics, rely on manipulating pixels which often ends up being what’s called a destructive progress. This means once we commit to modifying the pixel information in a particular way, it’s very hard and often impossible to alter or undo those changes.
With vector graphics, instead of simply recording all the pixels in the image, just the necessary shapes and colors are recorded and recounted just before the graphic is shown on the screen. This last step, of taking the geometry and converting it to pixels on the screen happens transparently and automatically for us.
This process has the benefit of being easily scalable, as well as taking up much less space to store. It allows for us to create SVG images from any standard text editor, we can search, script them, and scale them indefinitely.
Vector graphics do have some disadvantages compared to raster graphics. For example, it’s much more convenient to store photos are raster graphics since most photos are not composed of simple geometric shapes. On the other hand, most data visualizations are composed of simple geometric shapes, so vector graphics makes them a perfect fit for use with D3.
Almost every D3 data visualization we’ll come across was likely created using SVG. The fact that we’re storing geometric information and not pixel data directly also means it’s very easy for us to go about making changes to the SVG graphics we create later.
Possibly the most convenient part about SVG is that we can use it directly inside of our HTML. It will feel like we are working with any other DOM element but the result will be a graphic.
Getting started
To get us started, lets take a look at the following ‘Hello World’ style SVG example:
1 <!DOCTYPE HTML>
2 <html>
3 <body>
4 <svg>
5 <circle cx="223" cy="83" r="54"/>
6 <circle cx="83" cy="83" r="54"/>
7 <circle cx="152" cy="125" r="16"/>
8 </svg>
9 </body>
10 </html>
Panda eyes
|
Live version: http://jsbin.com/ahOZAtEj/1/edit |
In order to actually place any SVG elements in our DOM, we’ll need to put them inside a parent <svg> element.
A new SVG element is easy to make, like so:
1 <svg height="200" width="200"></svg>
The <svg> element above is simply a DOM element, just like a <div> element. Just like any other HTML element, it will take as much room as it possibly can take unless we specify the dimensions.
This element won’t look like anything on the page quite yet because we haven’t placed anything inside of it.
|
SVG edges Note that when we are using an SVG element positioned beyond the border of its parent <svg> element, it will be clipped. To be sure that our elements don’t get cut off, we’ll either have to ensure the <svg> element is large enough or by making sure our inner SVG elements never exceed the border of their root <svg> element. |
There are a number of SVG elements that we can use to draw visual elements inside of our <svg> element on the DOM as well as we have the opportunity to build our own. These include simple shapes, such as circles, ellipses, lines, rectangles, and rounded rectangles.
We can draw text with many different fonts or paths that can be straight, curves filled in, outlined and more. We have the full color spectrum available for us to use to create gradients, patterns, visual effects on images, compositing, and alpha effects.
SVG also allows us to define animation for different elements.
Furthermore, many popular illustration programs export graphics to SVG, so it’s possible to draw paths using an external tool that we can draw the graphics from on the web.
Differences between SVG and HTML
Even though SVG feels like HTML, it differs in a few, not-so-obvious ways. Simply because a property or style works in HTML doesn’t mean it will work for SVG elements.
For example, width and height properties make no sense for a circle. The only three things that describe the geometry of a circle are precisely the three we mentioned, its x and y position from its center (cx and cy), and its radius (r). Notice also that these are properties and not styles. Wecannot effect position of SVG elements by using CSS styles like we can with HTML elements.
|
Common Gotcha: Just because a property or style works in HTML doesn’t mean it will work for SVG. Common pitfalls involve using attributes or styles such as width height, position, left, top, right, bottom, or float on SVG elements witch don’t support them. |
We will look at a few SVG types now so as to highlight a few of the most commonly used SVG types.
SVG coordinates
Computer-based graphics have traditionally set their coordinate system starting from the top left corner as defined as the base 0, 0 coordinate system. Larger y values move the coordinate downward, while increasing x values move it right. The SVG coordinate system is no different.
Coordinate system
When we place an element inside of our root <svg> element, we’ll need to respect the the location based on these coordinates.
SVG circle
The first SVG element we just introduced is the <circle> which, unsurprisingly creates a circle. Notice how we set the properties cx and cy corresponding to the offset of the circle from the center along the x and y axis and the r, the radius of the circle.
|
These are not HTML properties we’re using. They are properties specific to circles and not other SVG shapes (like rectangles) or other HTML elements. |
1 <circle cx="50" cy="50" r="30">
2 </circle>
Circle
This sets the center of the circle to be placed at the coordinate (50, 50) with a radius of 30.
|
Live version: http://jsbin.com/OruHiZA/1/edit |
SVG ellipse
Like the circle, we can also draw an ellipse that has a different expectation of a different radius for each dimension than the circle.
1 <ellipse cx="50" cy="50" rx="40" ry="20">
2 </ellipse>
Ellipse
|
Live version: http://jsbin.com/eHugeTar/1/edit |
SVG rect
The <rect> is a straightforward SVG element that simply creates a rectangle. To specific the geometry, we’ll need to set the properties x, y, width, and height. We’ll set the x and y values to specify the coordinates of the top left corner, while we use the width and the height to specify the rectangle’s dimensions, relative to x and y.
1 <!DOCTYPE HTML>
2 <html>
3 <body>
4 <svg>
5 <rect x="100" y="15" width="150" height="150"></rect>
6 </svg>
7 </body>
8 </html>
Black Square on a White SVG, 2013
|
Live version: http://jsbin.com/etISEYuY/1/edit |
SVG lines
SVG also supports drawing simple lines. Lines require four attributes, the starting (x1 and y1) and ending (x2 and y2) coordinates of the line segment that would pass through both points.
1 <line x1="10" y1="10"
2 x2="100" y2="100"
3 stroke="blue"
4 stroke-width="100"></line>
Line
|
Live version: http://jsbin.com/onuSAbO/1/edit |
SVG path
The <path> is a deceptively cumbersome tag to work with because we have to specific the entire geometry of the path in only a single attribute named simply d.
But don’t fret! As we’ll learn later in this chapter, D3 comes with a wide collection of helper functions that make generating this d attribute from our data effortless. It’s helpful to know how to create path’s so we’ll go over the different commands that constitute the path geometry in the dattribute. Here’s a simple example we’ll dissect:
1 <!DOCTYPE HTML>
2 <html>
3 <body>
4 <svg>
5 <path d="M 100 50 L 300 50 L 200 150 z"/>
6 </svg>
7 </body>
8 </html>
insane clown triangle
The commands that are passed to the d are described using turtle graphics style commands. Think of these commands as how you would tell someone to draw a picture blindfolded, issuing commands such as lift pen off paper, put pen on paper, move down, move up and to the left, etc. the commands we pass to d are expressed in the same imperative way. The path d attribute versions are:
M for move to
### L for line to ### z which stands for close path
Lets break down the commands in the previous example in more detail:
1 M 100 50 - move to position (x=100, y=50),
2 without drawing a line
3 L 300 50 - draw a line from the previous
4 position (x=100, y=50) to
5 (x=300, y=50)
6 L 200 150 - draw a line from (x=300, y=50)
7 to (x=200, y=150)
8 z - connect the start with the end by
9 drawing a line from (x=200, y=150)
10 to (x=100, y=50)
The <path>’s d attribute can take a few other commands but we wont get into those here since the ones we just examined are the most frequently used.
With that said, we can find further information and learn about the others commands by reading MSDN’s extensive documentation on the SVG <path>. These include commands for creating smooth lines using Bezier curves.
SVG text
The <text> tag is a straightforward way of including text into our SVG but we might question it’s existence.
Why couldn’t we just use a simple <p>, <div> or <span> tag? Why do we need a separate tag to include text in our drawings?
The main reason is that we cannot (easily) include HTML into an SVG the way we can include SVG into HTML. This is also to allow SVG images to exist on their own, outside of a browser allowing SVG images to be edited in image editors like Adobe Illustrator. We can set the location of a <text> tag using its x and y attributes and set the text by editing its inner text content.
That said, the <text> element inherits from it’s CSS-specified font styles unless it’s directly set on the <text> element itself.
1 <!DOCTYPE HTML>
2 <html>
3 <body>
4 <svg>
5 <text x="100" y="100" fill="green" font-family="arial" font-size="16">
6 Ceci n'est pas une pipe.
7 </text>
8 </svg>
9 </body>
10 </html>
text element in SVG
|
Live version: http://jsbin.com/eralusAW/1/edit |
SVG group
The <g> tag is an easy way to group SVG elements. Any transformations (positioning, scaling, rotating) that are applied to the group element will also be applied to each of the child elements.
Using groups, we could, for example, create a collection of SVG elements that draw a car using circles for wheels, and rectangles for axles. If we then wanted to rotate the car, we could simply apply the transformation to the <g> element containing all the components.
SVG style
Styling SVG elements is almost exactly the same as styling HTML elements. We can still use CSS with id and class attributes to connect our CSS with our SVG elements or simply apply the style directly using the style attribute.
The only difference is that a large number of the styles differ from what we except from experience with HTML.
Take for example the HTML background-color: orange; style. The closest equivalent for an SVG element is fill: orange;. Similarly, what we expect as of border-color: blue equivalent in SVG is stroke: blue; or border-width: 10px; and stroke-width: 10; This is an important detail and a common gotcha when working with SVG coming from an HTML background.
1 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <style>
5 svg path {
6 stroke: red;
7 stroke-width: 30px;
8 fill: white;
9 }
10 svg text {
11 font-size: 30px;
12 font-family: sans-serif;
13 fill:red; /* not `color` or `font-color` */
14 }
15 </style>
16 </head>
17 <body>
18 <svg>
19 <path d="M 30 20 L 140 200 L 240 20 z"></path>
20 <text x="95" y="80">YIELD</text>
21 </svg>
22 </body>
23 </html>
|
Live version: http://jsbin.com/iXigIFe/1/edit |
It’s possible to place these styles directly on the elements themselves. Using CSS to do so is generally much easier and more recommended as it is easier to maintain and read.
|
Common gotcha: Keep in mind that for SVG elements, transformations are applied using the transform attribute, unless HTML elements, which use a transform CSS property. |
More on SVG
Transparency
SVG supports drawing with transparency, which we can do one of two ways. We can either set the opacity attribute directly on an element or we can set the rgba as a color, where the fourth argument is the transparency (also known as the alpha value).
We can set the opacity of an SVG element just like we set any other attribute:
1 d3.select('body').append('svg')
2 .attr('width', '300px')
3 .attr('height', '200px')
4 .data([1,2,3])
5 .enter().append('circle')
6 .attr('fill', 'blue')
7 .attr('opacity', '0.4');
|
Live version: http://jsbin.com/UzIvodE/2/edit |
As we previously mentioned, it’s easy to combine the two attributes of opacity and fill using the rgba() function, where we set both the color and the transparency in one go.
1 d3.select('body').append('svg')
2 .attr('width', '300px')
3 .attr('height', '200px')
4 .data([1,2,3])
5 .enter().append('circle')
6 .attr('fill', 'rgba(100, 200, 300, 0.4');
|
Live version: http://jsbin.com/UzIvodE/2/edit |
Strokes
There are more options at our disposal when it comes to the appearance of shape strokes than just stroke thickness and color. There’s also stroke-linejoin which effects the corners of line segments, stroke-linecap which effects the appearance of line ends in a similar way stroke-linejoinand also stroke-dasharray which can be used to create a dashed line effect instead of the defualt solid like.
1 <svg>
2 <line x1="20" y1="20"
3 x2="200" y2="200"
4 stroke="blue"
5 stroke-linecap="round"
6 stroke-dasharray="4,30"
7 stroke-width="20">
8 </line>
9 </svg>
|
Live version: http://jsbin.com/EBuciXuZ/1/edit |
Layering
You may run into situations where you have overlapping SVG elements were one element should be behind another instead of in front. This can happen when the order in which you add your SVG elements is not the same as their visual depth order, bottom to top. With HTML we can fix this using the z-index CSS property but that doesn’t work for SVG elements. Instead, we’ll have to remove and re-add any elements we’d like to be on the every top of their parent element. Luckly, D3 selections come with a nice helper method called sort for just this problem. We can pass it our sort function and D3 will resort our selection and update the DOM elements accordingly.
1 d3.selectAll('circles').sort(function(a, b){
2 // assuming we've added our own `zIndex` data property
3 return a.zIndex - b.zIndex;
4 });
SVG and D3
SVG can be somewhat tedious to use on it’s own but after the previous introduction, we’ll rarely, if ever, need to write any SVG directly.
Instead, we’ll use D3 to create these elements and apply style for us.
We’ll still need to know how SVG works to do master D3, but we will let the library take care of the heavy lifting.
Now that we’ve covered some of the basics of SVG, we can begin to talk more about using it in combination with D3.
From nothing to SVG
When we first start up the page, we’ll need a place to place our SVG elements. As stated above, we can only place our elements inside of an <svg> tag. Sometimes it’s more convenient (especially when we integrate with using directives) to not place this directly on the page.
We can use d3 to make our svg, like so:
1 var svg = d3.select("body")
2 .append("svg");
With the svg variable, we can now reference the <svg> element and interact with our D3 stage at any time. It’s possible to use the same methods on the <svg> element that we’ll use on the D3 elements to set attributes on it.
For instance, let’s set a height and a width:
1 d3.select('body').append('svg')
2 .attr('width', 300)
3 .attr('height', 200);
Generators
One of the nicest parts of D3, is it’s focus on making SVG element creation manageable through D3’s generators.
Generators play the part of both objects and functions. Generators are functions, like any other function that has additional methods to allow us to change it’s behavior. Just like any other D3 class, most generator methods return themselves so we can chain methods on top of them.
Once we’ve configured our generators for our needs, we’ll use them to generate the necessary SVG commands to create our shape.
Let’s look at a very simple example, the line generator:
The line generator takes any data that we pass it and generators the necessary SVG <path> d attribute commands. In order to use the path generator, we need to tell it a little about the format of our data. We do this by defining accessor functions for the x and y coordinates of the line across our data. This essentially says “hey line generator, when you create a line, use this for the x and this for the y of each data point.”
If our data was a much of points where a single point was an array of the form [x, y] and the array of points looked like this:
1 var data = [ [x1, y1], [x2, y2], [x3, y3], etc... ];
Our line generator would look like this:
1 var line = d3.svg.line()
2 .x(function(d) { return d[0]; })
3 .y(function(d) { return d[1]; });
Lets say our data instead was an array of coordinate objects of the form { x: x1, y: y1 } and the array of points looked like this:
1 var data = [ { x: x1, y: y1 }, { x: x2, y: y2 }, etc... ];
Then our line generator x and y accessors would look like this:
1 var line = d3.svg.line()
2 .x(function(d) { return d.x; })
3 .y(function(d) { return d.y; })
Here’s a complete line generator example
1 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
5 <style>
6 body{ margin: 0; }
7 path { stroke: black; stroke-width: 2px; fill: none;}
8 </style>
9 </head>
10 <body>
11 <script>
12 var lineGenerator = d3.svg.line()
13 .x(function(d) { return d[0]; })
14 .y(function(d) { return d[1]; });
15 // the line data
16 var lineData = [[154, 14], [35, 172], [251, 127], [31, 58], [157, 205],
17 [154, 14]];
18 // create `<svg>` and inner `<path>` element
19 d3.select('body').append('svg')
20 // use the generator and line data to create the `d` attribute for our path.
21 .append('path').datum(lineData).attr('d', lineGenerator);
22 </script>
23 </body>
24 </html>
With our generator, we can also set an interpolation mode that tells D3 how to render the lines between each point.
There are quite a few interpolation modes available to us.
Interpolation modes for d3.svg.line()
And don’t forget, generators can be used more than once, for multiple elements so if our data changes but still has the same general format, we can just re-apply the generator.
d3.svg.arc
We can also produce an arc or a circle using the d3.svg.arc() generator. The four parameters that describe an arc are its inner and outer radii, as well as the start and end angles (where an angle of zero points up and -Ï€, left.)
If we wanted our arc generator to always produce the same arc, we could fix each parameter to a constant value by calling all of the arc generator accessors by passing each a single number value. Our arc is also created at (0,0) so we’ll also translate it left and down by 200 pixels to we can see the entire arc.
1 var arc = d3.svg.arc()
2 .innerRadius(100).outerRadius(150)
3 .startAngle(-Math.PI / 2).endAngle(Math.PI / 2)
4
5 d3.select('body').append('svg')
6 .append('path').attr('d', arc).attr('transform', 'translate(200, 200)')
|
Live version: http://jsbin.com/uPEfeMaj/3/edit |
In addition, the accessors can be passed functions, instead of number values, which will be called for each element of the selectors data. For every data item in the selector, D3 will call our accessor and use its result to set that parameter for the current arc being generated. Let’s create a rainbow to show this off.
1 <!DOCTYPE HTML>
2 <html>
3 <body>
4 <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
5 <script>
6
7 var rainbow = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
8 var arc = d3.svg.arc()
9 .innerRadius(30)
10 // the outer radius of the rainbow is set from the index in the rainbow array
11 .outerRadius(function(d, i){ return (rainbow.length - i) * 20 + 30})
12 .startAngle(-Math.PI / 2).endAngle(Math.PI / 2);
13
14 d3.select('body').append('svg')
15 .selectAll('path').data(rainbow).enter().append('path')
16 .attr({
17 d: arc,
18 transform: 'translate(200, 200)',
19 fill: function(d){ return d }
20 })
21 </script>
22 </body>
23 </html>
|
Live version: http://jsbin.com/AbUGOZiX/1/edit |
Here’s an example of a donut chart that uses d3.layout.pie that handles converting our data to a format we can pass directly to the pie generator. Say we had the following data that we wanted to represent as a pie chart.
1 var data = [21, 32, 35, 64, 83];
We could convert that to the necessary array of start and end angles to be passed to your arc generator by calling the pie() method on the pie layout.
1 var pie = d3.layout.pie();
2 var arcData = pie(data);
Then, we’ll create an arc generator with fixed inner and outer radius values.
1 var arc = d3.svg.arc().innerRadius(100).outerRadius(200);
We don’t need to specify the startAngle and endAngle accessors because those, by default, access a property by the same name on their datum element so there’s no need to add this snippet.
1 // default `startAngle` accessor
2 arc.startAngle(function(d){
3 return d.startAngle;
4 });
5 // default `endAngle` accessor
6 arc.endAngle(function(d){
7 return d.endAngle;
8 });
Now, the last step is to bind our arcData to newly created path elements in our selector.
1 var path = svg.append('path').data(arcData)
2 .enter().append('path').attr('d', pie);
We’ll need to translate all the paths a bit so they’re not all drawn at (0,0) in the upper left of the screen. Then, after adding a some color using a color scale (which well see more of in a later chapter), the result should look like the following:
|
Live version: http://jsbin.com/axICUjaH/1/edit |
d3.svg.area
The area generator makes it easy to create line plots where the area bellow the plot line is filled in. We need to give the generator’s accessors either functions or number values for y0, y1 and x. The y* accessors tell the generator how lower or how high the area shape should extend. x should be the successive x values along the plot just like with d3.svg.line().
1 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
5 <style>
6 path { stroke: white; stroke-width: 2; fill: steelblue;}
7 .plot{ fill: none; stroke: #aec7e8; stroke-width: 2;}
8 circle{ fill: steelblue; stroke: white;}
9 </style>
10 </head>
11 <body>
12 <script>
13
14 var svg = d3.select('body').append('svg')
15 // construct and configure the are generator
16 var area = d3.svg.area()
17 .y0(100) // set the lower y bound of the area shape
18 .y1(function(d){ return d.y })
19 .x(function(d, i){ return d.x })
20
21 // generator some random data
22 var data = d3.range(100).map(function(){ return Math.random() * 30 + 0 })
23 .map(function(d, i){ return { x: i * 10, y: d }})
24
25 // draw the area shape under the line of the plot
26 svg.append('path').datum(data).attr('d', area)
27
28 // give the area shape a border along its top edge
29 var line = d3.svg.line()
30 .x(function(d){ return d.x})
31 .y(function(d){ return d.y })
32 svg.append('path').datum(data).attr('d', line).attr('class', 'plot')
33
34 // the circles at all the points
35 svg.selectAll('circle').data(data).enter().append('circle')
36 .attr('cx', function(d){ return d.x })
37 .attr('cy', function(d){ return d.y })
38 .attr('r', 3)
39
40 </script>
41 </body>
42 </html>
d3.svg.chord
The svg chord generator helps in creating connected arc segments which is the essential component in chord diagrams. Every other component in a chord diagram can be created using other svg generators. Two arc segments make up one arc connection. The first arc segment is called thesource, the second, the target. Each arc segment is described by a radius, a startAngle and an endAngle. Conveniently, d3.layout.chord() can be used to take relational information in the form of a matrix and produce the necessary default chord layout that d3.svg.chord expects. For example, here’s an arbitrary relational data set. Every cell describes the relationship among of two items (in our example, the items A B C and D). Maybe the relationship could be likness. “How much Alex likes Betty.” and since Betty might like Alex more than Alex likes Betty, the connections have different magnitudes depending on their direction.
1 // each cell value represents a node->node relationship (column->row)
2 // A B C D
3 var matrix = [
4 [ 0 /* A -> A */, 1.3 /* B -> A */, 2 /* C -> A */, 1 /* D -> A */],
5 [ 1.9 /* A -> B */, 0 /* B -> B */, 1 /* C -> B */, 2.1 /* D -> B */],
6 [ 2 /* A -> C */, 2 /* B -> C */, 3.2 /* C -> C */, 1.8 /* D -> C */],
7 [ 2.7 /* A -> D */, 0 /* B -> D */, 1 /* C -> D */, 0 /* D -> D */]
8 ]; // `C` really likes herself
Passing this data to d3.layout.chord().matrix(matrix).chord() gives us back data that looks like this:
1 [
2 {
3 source:{ startAngle:1.2280, endAngle:1.7707, value:1.9 },
4 target:{ startAngle:0, endAngle:0.3712, value:1.3 }
5 },
6 {
7 source:{ startAngle:0.3712, endAngle:0.9424, value:2 },
8 target:{ startAngle:2.6560, endAngle:3.2272, value: 2 }
9 },
10 // etc...
11 ]
1 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
5 <style>
6 path { stroke: white; stroke-width: 2; fill: steelblue;}
7 .plot{ fill: none; stroke: #aec7e8; stroke-width: 2;}
8 circle{ fill: steelblue; stroke: white;}
9 </style>
10 </head>
11 <body>
12 <script>
13 var width = window.innerWidth;
14 var height = window.innerHeight;
15
16 var svg = d3.select('body').append('svg')
17 var matrix = [
18 // each cell value represents a single row-to-column relationship
19 [ 0 /* A -> A */, 1.3 /* A -> B */, 2 /* A -> C */, 1 /* A -> D */],
20 [ 1.9 /* B -> A */, 0 /* B -> B */, 1 /* B -> C */, 2.1 /* B -> D */],
21 [ 2 /* C -> A */, 2 /* C -> B */, 3.2 /* C -> C */, 1.8 /* C -> D */],
22 [ 2.7 /* D -> A */, 0 /* D -> B */, 1 /* D -> C */, 0 /* D -> D */]
23 ];
24
25 var chord = d3.layout.chord().matrix(matrix);
26 var innerRadius = Math.min(width, height) * .41;
27 var outerRadius = innerRadius * 1.1;
28
29
30 var fill = d3.scale.ordinal()
31 .domain(d3.range(4))
32 .range(['#FFA400', '#C50080', '#ABF000', '#1049A9']);
33
34 svg = svg.append('g')
35 .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
36
37 svg.append('g').selectAll('path').data(chord.chords)
38 .enter().append('path')
39 .attr('d', d3.svg.chord().radius(innerRadius))
40 .style('fill', function(d) { return fill(d.target.index); })
41 .style('opacity', 0.5);
42
43 </script>
44 </body>
45 </html>
d3.svg.symbol
The symbol generator creates a new symbol generating function for creating symbols. The default symbol is a circle with a size (area in pixels) of 64. This is the behavior you’re most likely to want but if you’d like to specify the dimensions of say, a square, you’ll have to compute the area given your desired dimensions and symbol.
1 var symbol = d3.svg.symbol().type('square').size(100)
2 var svg = d3.select('body').append('svg')
3 svg.append('path').attr({d: symbol}).attr('transform', 'translate(100,100)')
d3.svg.diagonal
The diagonal generator takes node pairs and produces the necessary path that would connect the two elements of the pair using a curved path. The default accessors assume each pair has the following form:
1 { source: { x: 54, y: 12 }, target: { x: 83, y: 62 } }
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <style>
5 circle { fill: orange; stroke: #333; }
6 path { fill: none; stroke: #ccc; }
7 </style>
8 </head>
9 <body>
10 <script src="http://d3js.org/d3.v3.min.js"></script>
11 <script>
12
13 var svg = d3.select('body').append('svg');
14 var diagonal = d3.svg.diagonal();
15 var source = { x: 500, y: 50 };
16 var targets = [
17 { x: 100, y: 150 },
18 { x: 300, y: 150 },
19 { x: 500, y: 150 },
20 { x: 700, y: 150 },
21 { x: 900, y: 150 }
22 ];
23 // create the link pairs
24 var links = targets.map(function(target){
25 return { source: source, target: target };
26 });
27
28 // use the diagonal generator to take our links and create the the curved paths
29 // to connect our nodes
30 var link = svg.selectAll('path').data(links).enter().append('path')
31 .attr('d', diagonal);
32
33 // add all the nodes!
34 var nodes = targets.concat(source)
35 svg.selectAll('circle').data(nodes).enter().append('circle')
36 .attr({
37 r: 20,
38 cx: function(d){ return d.x; },
39 cy: function(d){ return d.y; }
40 });
41
42 </script>
43 </body>
44 </html>
d3.svg.line.radial
The radial generator takes a data array of radius and angle pairs and produces the necessary SVG path that would connect them in series, starting with the first. The default accessors assume each pair has the following form, where the angle is measured in radians.
1 [43, Math.PI * 0.5]
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <style>
5 body{ margin: 0; }
6 circle { fill: orange; stroke: #333; }
7 path { fill: none; stroke: #333; stroke-width: 4; }
8 </style>
9 </head>
10 <body>
11 <script src="http://d3js.org/d3.v3.min.js"></script>
12 <script>
13
14 var svg = d3.select('body').append('svg');
15 // our radial line generator
16 var lineRadial = d3.svg.line.radial();
17
18 var n = 1000, max_r = 250, rotations = 10;
19 var data = d3.range(n).map(function(d){
20 var t = d / (n - 1);
21 return [ t * max_r, t * Math.PI * rotations * 2 ];
22 });
23
24 var link = svg.append('path').datum(data).attr('d', lineRadial)
25 .attr('transform', 'translate(300,300)');
26
27 </script>
28 </body>
29 </html>