Book Image

Data Visualization with D3 and AngularJS

By : Erik Hanchett, Christoph Körner
Book Image

Data Visualization with D3 and AngularJS

By: Erik Hanchett, Christoph Körner

Overview of this book

Table of Contents (16 chapters)
Data Visualization with D3 and AngularJS
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

A brief overview of visualization tools for the Web


Now, let me explain why we are using D3.js and not any other similar visualization library to manipulate vector graphics.

When I started with web development in 2004, vector graphics and interactive applications were mostly embedded as Flash objects into web pages. The main reason for this was the lack of web standards for vector graphics or good and powerful JavaScript libraries for image manipulation. It was difficult to create interactive visualizations that integrate into the underlying page because functionalities (such as layouts and fonts) defined in CSS and user interactions written in JavaScript were not available in embedded objects. Thus, these visualization objects often felt like a strange add-on to the underlying application, where fonts, size, and colors were not completely matching with the application. A typical code example for an embedded visualization looks like this:

<html>
  ...
  <body>
  <object id="vis" width="50" height="30">
    <param name="movie" value="vis.swf">
    <embed src="vis.swf" type="application/x-shockwave-flash">
  </object>
  </body>
</html>

We can see in the preceding example that the compiled and embedded vis.swf Flash object is completely isolated from the scope of the host application. In addition to the web browser, we would also need a plugin that can interpret the Flash binary object. While the application and the embedded visualization have the same task—displaying data on a web page—they are not sharing common styles or a common scope for user interactions.

Java and Flash

One of the first consistent toolsets for interactive data visualization for the Web was the Java library Prefuse, which was published by Jeffrey Heer in 2007, who, at this time, is a member at the Berkley Visualization Lab. Prefuse provided rich tools for data modeling and interactive graphics. The visualization could be embedded as Java applets into a web page, but this required the Java runtime environment to be installed on every browser that wants to display the visualization.

Later in 2008, Heer released the first version of Flare, a port of the Prefuse library to ActionScript, which could compile the visualization to a more common Flash object. A simple application that shows three circles with different x coordinates in an image with the size of 50 x 30 pixel looks like this with Flare:

[SWF(width="50", height="30")]
public class Vis extends Sprite
{
  public function Vis()
  {
    // Define the dataset
    var data:Array = [15, 25, 35];
    for each (var d:int in data) {
      var sprite:Sprite = new Sprite();
      // Draw and color the circles
      sprite.graphics.beginFill(0xff0000, 1.0);
      sprite.graphics.drawCircle(0, 0, 5);
      this.addChild(sprite);
      // Set the coordinates of the circle
      sprite.x = d;
      sprite.y = 15;
    }
  }
}

Looking at the preceding code, we can see that in each loop, we create a drawing container (sprite) and a circle element. We also color it and with sprite.x = d, we set the x coordinate of the sprite container to the current value d of the data array. Don't worry if this code looks quite complicated to you because this is exactly the reason why I am showing it. It's complicated and not intuitive to create containers, add elements, and move containers to the position where we want to display the circle. Furthermore, to run this example in the browser, we have a very similar problem as before with Prefuse: each browser needs the Flash runtime installed. The resulting image generated by the previous code will look like the following figure:

Image of three circles

Raphaël (JavaScript – SVG/VML)

By 2008, most of the major browsers provided native support for SVG and signified the certain end of Flash in the upcoming years. However, Internet Explorer implemented a different markup language for vector graphics than SVG; it used the similar, but different Vector Markup Language (VML).

In 2009, Dmitry Baranovskiy announced the first release of Raphaël, a JavaScript library that aims to simplify the manipulation of vector graphics by providing a JavaScript API for SVG with a compatibility layer for VML for Internet Explorer. The representation of graphics inside the DOM not only enabled the use of JavaScript event handlers for user interactions on elements of the image, but it also enabled the use of CSS to style these elements. This was a huge step towards open web standards, accessibility, and acceptance of SVG. An example of drawing the same three circles looks like this:

<script type="text/javascript">
  // Define the dataset
  var data = [15, 25, 35];
  // Draw the canvas
  var paper = Raphael(0, 0, 50, 30);
  // Draw and color the circles
  for (var i = 0; i < 3; i ++) {
    var circle = paper.circle(data[i], 15, 5);
    circle.attr('fill', 'red');
  }
</script>

Again, we generate a circle with the x coordinate of the data array each time we loop over the array. In a modern browser, the preceding code produces an SVG image that looks exactly like the previous example, but additionally outputs directly to the DOM of the HTML page. It adds three circle elements with different x coordinates of the center point to the DOM tree inside the SVG node. The generated SVG code embedded in the web page will look like this:

<html>
  ...
  <body>
    <svg width="50" height="30">
      <circle cx="15" cy="15" r="5" style="fill:red;">
      <circle cx="25" cy="15" r="5" style="fill:red;">
      <circle cx="35" cy="15" r="5" style="fill:red;">
    </svg>
  </body>
</html>

Protovis (JavaScript – SVG)

In the same year at Stanford, Michael Bostock and Jeffrey Heer published the visualization library Protovis for SVG manipulation in JavaScript. Its new data-driven approach allowed the developers to declare the representation of data, rather than looping and drawing multiple elements explicitly. The following code uses Protovis to generate the exact same SVG graphic of the three circles shown in the previous figure:

<script type="text/javascript">
  // Define the dataset
  var data = [15, 25, 35];
  // Define the canvas
  var vis = new pv.Panel()
    .width(50)
    .height(30);
  // Define the circles and their color
  vis.add(pv.Dot)
    .data(data)
    .left(function(d) { return d; })
    .bottom(15)
    .radius(5)
    .fillStyle('red');
  // Draw the canvas and the circles
  vis.render();
</script>

The main difference in the previous example is that the explicit loop over the data array in Raphaël is replaced by the a implicit data() function in Protovis, where the x coordinate of each circle is called as a function that returns the current element of the data array.

D3.js (JavaScript – HTML/SVG)

In 2011, when SVG was finally supported in all major browsers and Internet Explorer, the same authors of Protovis—Michael Bostock and further members of the Stanford Visualization Group—published D3.js, a more generalized version of Protovis with built-in support for animations. The goal was not to restrict the library anymore on just the SVG object, but to access the complete DOM tree and use all of its features and underlying standards. Therefore, all updates and extensions for HTML and CSS (for example, new attributes, and so on) are immediately available in D3.js. To support dynamic visualizations, D3.js also introduced the concepts of data joins, which let the developer add, update, and remove elements depending on data that was added, updated, or removed from a Selection (this will be discussed in more detail in the next chapter).

The same graphic as previously generated with Raphael and Protovis can be created with D3.js as follows:

<script type="text/javascript">
  // Define the dataset
  var data = [15, 25, 35];
  // Draw the canvas
  var vis = d3.select('body')
    .append('svg')
    .attr('width', 50)
    .attr('height', 30);
  // Draw and color the circles
  vis.selectAll('circle')
    .data(data)
    .enter().append('circle')
    .attr('cx', function(d) { return d; })
    .attr('cy', 15)
    .attr('r', 5)
    .style('fill', 'red');
</script>

We remark that D3.js implements more general methods, for example, attr('r') that uses the underlying SVG attribute r for the radius explicitly instead of the radius() function, which is an abstraction of the SVG attribute r in Protovis.

The selectAll().data().enter() construct in this static example looks more complicated than the simple data() function of Protovis, but it implements data joins to create new elements for new data in the Selection. Therefore, it will be very useful to update dynamic graphics in the following chapters of this book.

Note

D3.js forces developers to use the underlying standards HTML, CSS, and SVG instead of providing an abstraction of these attributes.

Canvas API (JavaScript – Canvas)

Since the introduction of HTML5, we can also use the Canvas element and its JavaScript API to draw the exact same circles as in the previous examples. The performance of Canvas is much better than SVG when drawing large amount of objects/elements. However, the content of the Canvas will be drawn as a pixel graphic and no element will be appended to the DOM or the Canvas node, which is a huge drawback.

Three.js (JavaScript – WebGL)

With WebGL that was introduced in 2011, we can also draw the example of the three circles using the Three.js JavaScript library. WebGL has access to hardware acceleration of the operating system and is mainly used for 3D graphics. The resulting image is a pixel graphic. However, it's worth mentioning that it's not available in all modern browsers.