Seyram A. Butame

You see the Black Skin Blue Eyed Boys/ They ain't gonna fight no wars.

D3js Tutorial Notes -- d3Vienno

Below are my very rough notes from a Youtube Tutorial on D3

My notes below are based on tutorials offered by d3Vienno on Youtube. Who about 10 years ago created a series of about 15 vids on using D3. Some of the material is out of date, given the changes and improvements in the various iterations of D3 (at the time they made the video, D3 was on version 03, and we are not at version 07). However much of the explanations and rationale given for the way the language is written is pretty sound. Access the videos below.

src –> This indicates a source attribute

d3.select() function in D3.js is used to select the first element that matches the specified selector string.

d3.select("element")

You can select any element

In JavaScript the characters before the period represent an object. And this object is reference a collection of data. Therefore d3 is an object, which was called into our work with importing the library.

Therefore d3.select() means we are using the d3 object and the select function from object (which is one of the

For example the below can be read as

d3.select(“body”).append(“p”).text(“High, what’s up?”);

Using the d3 object, select the “body” element (i.e., where items are located within a webpage). To that element, append a paragraph (via the p element), then insert the text.

Of course this is not what the d3 object is designed for. You can do what is stated in the above using HTML.

Hi, what's up?

Adding Stylistic Elements

There is a .style(). This function affects the css property of the element in question. It takes two arguments, the property and the value.

d3.select("body")
	.append("p")
	.style("color", "red")
	.text("Hi, what's up");

The above will change the color of any text added to the p element to red (Defined by the arguments of property (i.e., color) and value (i.e., red).

Another way to change the stylistic quality is via the attribute. The .attr() function. Attributes can also affect what we would think of as style, but it also affects things like placement.

Using Scalable Vector Graphics (svg)

To create visualizations you employ svg elements. They are a way to create two dimensional graphics on our webpage, by employing vector notions (i.e., a combination of numbers).

Via the svg element, we can create some basic shapes. A circle, rectangle and a square.

Start by creating a container or a canvas for the svg element.

Give it some properties using the .attr() function.

	d3.select("body")
		.append("svg")
		.attr("width", 500)
		.attr("height", 500);

When styling svg elements we use the .attr approach to define properties as opposed to the more generalized .style() function.

The above code thus creates a container or canvas for our svg element that is 500px wide and 500px high/tall.

Assigning Code Snippets to Variables

We can then assign the above container, which we designed to have specific elements, to a variable var. All the code defining the element constitutes a snippet.


	var canvas = d3.select("body")
						.append("svg")
						.attr("width", 500)
						.attr("height", 500);

Hence our variable name is canvas which contains the snippet for the code we defined above.

Creating a shapes on the canvas


	var circle = canvas.append("circle")
					.attr("cx", 250)
					.attr("cy", 250)
					.attr("r", 50)
					.attr("fill", "#69a3b2")
					.attr("stroke", "black");

	var rect = canvas.append ("rect")
					.attr("width", 100)
					.attr("height", 50);
			

All svgs start in the top left corner of the pane. So if you don’t specify a location, then it will be in the top left corner until otherwise stated. As you can see, because we didn’t specify a location on the canvas, the circle gets placed in the top right corner.

The above appends a “circle” element to our canvas. We give it the following attributes

“cx” – Center horizontal “cy” – Center vertical “fill” – property that defines color “stroke” – property that defines the outer limits of the shape

Visualizing Data

First we keep our svg canvas defined with a width of 500 and a height of 500.

Then we define a simple array as follows

var dataArray = [20, 40, 50];

An array is a simple way of conveying data (similar to a data-frame). In the above, imagine that the three values 20, 40, and 50 represent three variables.

It is possible to visualize the data in different ways. A bar chart Or three circles for each

But lets create a simple bar chart. Where each data point would represent a bar. A bar chart is essentially a modified set of rectangles.

selectAll – Similar to the select function, but it selects all the elements that we specify.

The first step canvas.selectAll("rect") returns an empty selection. We can then bind this empty selection to our data. Then specify where the data comes from using the .data() function. Then we use the enter() function. This returns place holders for which there are no corresponding DOM elements on the page. For example, if we assume that there were already rectangles on the canvas, the enter() binds the data to the place holders for parts of the canvas without existing rectangles.

Then introducing the rect() appends a rectangle or a bar for each data element. Then you use the attr() to establish the size of the bars. Typically when creating a rectangle, we hard code the using .attr("width", 500), for example. However we replace the hard coded value with a function that is dependent on the values in the data.

.attr("width", function(d){ return d;}) So rather than hardcoding the bars we create the following function. Which essentially reads, for every d (i.e., data point), return the value of d. Where-in d also becomes the value argument in the attr() function.

However the process is not over. As it stands the code will produce three rectangles superimposed over each other. We can separate them and also arrange them. .attr("y", function(d, i){ return i * 100}); This portion of the code separates the bars on the vertical axis again using the function. It reads for every d, there is an i or index value which represents the position of each data point relative to the next. For example, our array [20, 40, 50] has three values, 20 is first followed by 40 with 50 being in the third position. Consequently the function then returns a value of i *100, which means multiply the value of the position by a 100. Hence vertical positioning of the rectangles becomes such that the first rectangle is shown at 100px, the second at 200px and the third at 300px. `

Note – Look up how functions operate in JavaScript.

Using Scales

Scales can behave as both objects and functions where working JavaScript.

We treat them as functions but at the same time we can make modifications to their basic functionality.

If we add what another value to our data array var dataArray = [20, 40, 50, 60];, we are left with the below. Remember that we set out canvas to 500px by 500px. And because we defined the width of the bars using a function that multiplied the value of a perspective bar by 10 (i.e., 2010=200 and 4010=400 etc), to make the differences in the bars more visible. A bar that is 600px wide would be cut off by the parameters of our canvas or the container.

Applying a scale will transform the range of values into a new range so the fit into the bounds of the canvas we have created. Such that the largest data point will have the largest bar on to the smallest. You can eyeball this when you have a small dataset like we do in this case but our goal it to automate things.

Get into the habit of creating variables that define the canvas or container separately. This way one can then read the variable into the attribute

	var width = 500;
	var height = 500;

	var canvas = d3.select("body")
						.append("svg")
						.attr("width", width)
						.attr("height", height);

Defining Scales

	            var widthScale = d3.scaleLinear();

The linear scale is perhaps the most common of the type of scale. Which means the values in the calculated range are the result of a linear function applied to the domain values. The domain represents the values in the uploaded data. So have to let the scale know the domain that applies.

In the domain you list the minimum value and then the maximum value.

	.domain([0, 60])

Then you define what the resulting range should be. Here what we argue is that the range represented on the canvas should be such that, the minimum value can be zero, but the maximum value can never be exceeded. Which in this case is set the bounds of our container.


	.range([0, width])

So what happens is that a the linear function will recalculate the values in the domain to ensure that they fit into the within the bounds of the range we set.

So when we go to create our bars. When it comes to the attribute that defines the bars, we insert our variable denoting the widthScale, which determines the width of the bars

	.attr("width", function(d){ return widthScale(d);})

So in this case, for every d (i.e., data point), return the value determined by the widthScale variable.

So now when we push the html.

Use Scales to Define Color

We can also use scales when it comes to color. For example we want to apply colors to the bars based on their value. Such that there will be a gradient of colors along the bar.

One way to define the colors of the bars is to use an .attr("fill", "#89cdd3"). Thus we would get whatever color is shown by the HEX.

But with d3.ScaleLinear you can show a range of colors


	var color = d3.scaleLinear()
                        .domain([0, 60])
                        .range(["red", "blue"])

In the above, we define the domain based on the min and max in our array (or the dataset), as we did with the scale. Then in the range, we provide the color that is to represent the min value, and the color that is supposed to represent the maximum value.

Then in .attr() you apply the anonymous function to return the color variable you defined.

	.attr("fill", function(d){ return color(d);})

Reads, for every d (i.e., data-point), return a value determined by the color variable based on d

So what ends up happening is that the smaller value (i.e., bar representing the smaller value) is shown as red. And the bar representing the largest value is shown as blue. All the other bars that show up between are given some combination of red and blue, thus showing a gradation.

Groups and Axes

We can group svg elements together so we can transform them as whole. We can also add axes to our charts to display values. In the charts we have created so far, we can see that the bars are different.

To group svg elements we an add the following via the append() function.


	.append("g");


What will then happen is that when placed in our definition of the canvas, anything added to the canvas (e.g., bars representing the data) including the canvas itself are grouped together. In HTML this is shown by having the contents of the svg element being enclosed within a g tag (i.e., )

This then allows us to apply transformations to all the bars.

For example, we can use the attr() property to transform the figure.


.attr("transform", "translate(50, 50)");

The above figure will move the entire figure to the right by 50px and down the page by 50px.

Adding Axes

First we need to create a variable that denotes the axes, and then supply in the values using the scale method.


		var xaxis = d3.axisBottom()
                   .scale(widthScale);

The axisBottom() creates the x axis (conversely axisLeft() creates the y axis) to be able to read the axis in the standard manner.

Then the below, placed in the definition of the canvas, ensures that the axis as defined are placed on the chart at the relevant spot.


	.call(xaxis);

Using the group element, we can properly place the axis.


	  canvas.append("g")
                .attr("transform", "translate(0, 400)")
                .call(xaxis);



With the above, we group the elements whtin the canvas. We then transform (i.e., move) the grouped elements down by 400 pixels. And then to this we call the axis using the .call() function.

Change Ticks on Axis

You can use the ticks attribute. There is a default number when you apply the .axixBottom(). However if you apply .ticks(), and specify the number within, you will be able to change the ticks on the axis.

The Relationship DOM Elements and Data Elements

  • DOM elements < data elements –> This creates the (enter) selection, which contains placeholders for each data element that does not have a corresponding DOM element.
  • DOM elements > data elements –> This creates the (exit) selection, which contains placeholders for each DOM elements that does not have corresponding data elements.
  • DOM elements = data elements – > This creates the (update) selection.

Transitions in D3

Transitions are similar to animation. You change the property of an object and apply it smoothly over time. Hence the property does not change instantaneously but gradually giving the effect of animation.

For example if I have a circle appended to my canvas and wish to move it across the canvas by a bit I can use the following:

	circle.transition()
                .attr("cx", 150);
            

You can then change the pace of the transition using the .duration() operates in milliseconds (1500 milliseconds is .

	circle.transition()
				.duration(1500)
				.attr("cx", 150);
            

Adding a .delay(2000), will change when the transition starts. Making it start 2 seconds before.

Loading Data

Typically hardcoding your data into HTML, like I have been doing above is uncommon. Typically, we fetch or load external files. D3 allows for a number of data types including JSON (i.e., JavaScript Object Notation) and csv (i.e., comma separated vars).f

This is where it is important for you to be running some kind of server. Because most browsers won’t recognize some of the commands locally.

	d3.json("mydata.json", function(data){
	
	var canvas = d3.select("body")
			.append("svg")
			.attr("width", 500)
			.attr("height", 500)

	canvas.selectAll("rect")
			.data(data)
			.enter()
				.append("rect")
				.attr("width", function(d) { return d.age * 10; })
				.attr("height", 48)
				.attr("y", function(d,i) { return i *50})
				.attr("fill", "blue");
	})

The function beings with the file path. The we apply a call back function. All code that depends on the data being available is stored within the function. And w store the data in a variable (i.e., the object called “data”)

We can add text to each bar using the append