Wednesday, 5 February 2014

Elements, Attributes and Styles in d3.js: A primer

The following post is a portion of the D3 Tips and Tricks book which is free to download. To use this post in context, consider it with the others in the blog or just download the the book as a pdf / epub or mobi .
----------------------------------------------------------

This post  is intended to provide an overview of some of the simpler things that d3.js can do, but in a way that may help some understand a little more about how images / objects can be added to a web page and how they can be manipulated.
Loosely speaking we will look at how objects (elements (like circles, rectangles, lines and even text) can be declared and added to a page, how their attributes in relation to the page (position, size, shape, actions) can be changed and how their style (colour, width, transparency) can be applied.
As we go through the explanation of different changes that can be applied to different elements there will be a small amount of repetition where there is cross-over with related drawing features. Please be patient :-). The aim is to have each section as complete in its own right as practical.

The Framework

To be able to demonstrate how these three related aspects of drawing objects works we will have to use a small, simple script to draw them in your web browser.
We will just take a moment to explain the script that draws a circle.
Here’s the contents of the file in it’s entirety. I have imaginatively called it circle.html.
<!DOCTYPE html>
<meta charset="utf-8">

<body>

<!-- load the d3.js library --> 
<script type="text/javascript" src="d3/d3.v3.js"></script>

<script>
 
var holder = d3.select("body") // select the 'body' element
      .append("svg")           // append an SVG element to the body
      .attr("width", 449)      // make the SVG element 449 pixels wide
      .attr("height", 249);    // make the SVG element 249 pixels high

// draw a circle
holder.append("circle")        // attach a circle
    .attr("cx", 200)           // position the x-center
    .attr("cy", 100)           // position the y-center
    .attr("r", 50);            // set the radius

</script>

</body>
Please feel free to jump ahead slightly if you understand how a HTML file with JavaScript goes together :-).
The HTML part of the file can be thought of as a wrapper for the JavaScript that will draw our circle. These are the HTML parts here…
<!DOCTYPE html>
<meta charset="utf-8">

<body>

<!-- load the d3.js library --> 
<script type="text/javascript" src="d3/d3.v3.js"></script>

<script>
 
</script>

</body>
This portion of the file is built using HTML ‘tags’. These will set up the environment for the Javascript.
The tags tell the web browser what sort of language is being used and the type of characters used to write the code…
<!DOCTYPE html>
<meta charset="utf-8">
Areas of the code are labelled.
Like the body…
<body>

In this area we can put the stuff that will be 
displayed on our web page.

</body>
And the place where we put the JavaScript…
<script>

Our d3.js code will go here.

</script>
We even load an external file that contains JavaScript that will help run our code.
<!-- load the d3.js library --> 
<script type="text/javascript" src="d3/d3.v3.js"></script>
Yes, that’s the line that loads d3.js. Once it’s loaded we can use the instructions that it makes available to make other JavaScript code (in this case ours) work.
Then we have the JavaScript code that allows us to use the functions made possible by d3.js.
var holder = d3.select("body") // select the 'body' element
      .append("svg")           // append an SVG element to the body
      .attr("width", 449)      // make the SVG element 449 pixels wide
      .attr("height", 249);    // make the SVG element 249 pixels high

// draw a circle
holder.append("circle")        // attach a circle
    .attr("cx", 200)           // position the x-center
    .attr("cy", 100)           // position the y-center
    .attr("r", 50);            // set the radius
I’ve broken the code into two separate portions to provide some clarity to their function. We could make it one block, but that wouldn’t necessarily make it easier to understand.
Firstly we add a ‘holder’ for our graphics on the web page. I’ve named it holder but we could just as easily named it anything we wanted.
var holder = d3.select("body") // select the 'body' element
      .append("svg")           // append an SVG element to the body
      .attr("width", 449)      // make the SVG element 449 pixels wide
      .attr("height", 249);    // make the SVG element 249 pixels high
The first thing we do when declaring our holder is to select the body element of our web page (Remember those<body> tags in the HTML part earlier?).
Then we append a Scalable Vector Graphic (SVG) object to the body and we make it 449 pixels wide and 249 pixels high.
The width and height are ‘attributes’ of the SVG object. That is to say they describe a property of the object.
Believe it or not, I have made the container size unusual (not nice round numbers like 450 x 250) for a good reason. Later I will introduce a grid to our diagram so we can see where everything is laid out and this size makes the grid look better.
The second block of our JavaScript finally draws our circle.
holder.append("circle")        // attach a circle
    .attr("cx", 200)           // position the x-center
    .attr("cy", 100)           // position the y-center
    .attr("r", 50);            // set the radius
The first line appends a new element (a circle) to our SVG ‘holder’.
If you like, you can think of having the holder declaration in front of the .append("circle") as being a nice short-hand way of writing the code. We could have had a much longer line that selected the body, appended the svg element and then appended our circle in one line, but it’s actually a far better scheme for building multiple objects to break the sequences up which will allow us to manipulate groupings of objects in future code.
The second and third lines declare the attribute of our circle that specify where the centre of the circle is. In this case it’s at the x/y position 200/100 (cx/cy).
The last line adds the radius attribute r. Here it is set to 50 pixels.
The three attributes cxcy and r are all required when drawing a circle. There are other attributes we can put in there (and when we look at some of the upcoming elements, you should get a feel for them), but these are the minimum.
The purpose of describing this block of code that draws a circle isn’t to show you how to draw a circle. This has only been a way of showing you how the code in the following sections is laid out and how it works. The elements we are going to generate can be drawn with exactly the same file but with just the section that adds the circle altered.
For example if you were to change this block of code;
holder.append("circle")        // attach a circle
    .attr("cx", 200)           // position the x-center
    .attr("cy", 100)           // position the y-center
    .attr("r", 50);            // set the radius
For this block of code;
holder.append("rect")          // attach a circle
    .attr("x", 150)            // x position of the top-left corner
    .attr("y", 50)             // y position of the top-left corner
    .attr("width", 100)        // set the rectangle width
    .attr("height", 100);      // set the rectangle height
Instead of drawing a circle we would be drawing a rectangle.
So this is what our circle will look like;

Circle
Because it will help a great deal to have a common frame of reference, I’m going to display the elements on a grid that looks a little like this;

Circle with Grid
The grid won’t form part of the code that gets explained, but I will take the time out to describe how it’s generated in another section, because it’s quite cool in its own way :-).
With the grid in place it’s far easier to see that the centre of our circle is indeed at the coordinates x = 200, y = 100 and that the radius is 50.
The circle is still somewhat plain, but bear with me because as we start to explore what we can do with styles and attributes we can add some variation to our elements.

Fancier Circle
With that explanation behind us, the next post will begin our odyssey into the world of d3 elements.


The description above (and heaps of other stuff) is in the D3 Tips and Tricks book that can be downloaded for free (or donate if you really want to :-)).

No comments:

Post a Comment