Walkthrough and solutions. This article will walk you through freecodecamp.org data visualization challenges.
-D3.js, or D3, stands for Data Driven Documents. D3 is a JavaScript library to create dynamic and interactive data visualizations in the browser. It’s built to work with common web standards, namely HTML, CSS, and Scalable Vector Graphics (SVG).
D3 takes input data and maps it into a visual representation of that data. It supports many different data formats. D3 lets you bind (or attach) the data to the Document Object Model (DOM). You use HTML or SVG elements with D3’s built-in methods to transform the data into a visualization.
D3 gives you a lot of control over the presentation of data. This section covers the basic functionality and how to create visualizations with the D3 library. — by FreeCodeCamp
You can find the data visualization challenges here.
Let’s start!
You can also watch the video where I talk and code the first few d3.js challenges
D3 has several methods that let you add and change elements in your document.
The select() method selects one element from the document. It takes an argument for the name of the element you want and returns an HTML node for the first element in the document that matches the name.
You can use the selection with other methods. The “d3” part of the example is a reference to the D3 object, which is how you access D3 methods.
Two other useful methods are append() and text().
The append() method takes an argument for the element you want to add to the document. It appends an HTML node to a selected item, and returns a handle to that node.
The text() method either sets the text of the selected node, or gets the current text. To set the value, you pass a string as an argument inside the parentheses of the method.
D3 allows you to chain several methods together with periods to perform a number of actions in a row.
The solution →
d3.select(“body”)
.append(“h1”)
.text(“Learning D3”);
Select a Group of Elements with D3
D3 also has the selectAll() method to select a group of elements. It returns an array of HTML nodes for all the items in the document that match the input string. Like the select() method, selectAll() supports method chaining, and you can use it with other methods.
The solution →
d3.selectAll(“li”)
.append(“h1”)
.text(“list item”);
The D3 library focuses on a data-driven approach. When you have a set of data, you can apply D3 methods to display it on the page. Data comes in many formats, but this challenge uses a simple array of numbers.
The first step is to make D3 aware of the data. The data() method is used on a selection of DOM elements to attach the data to those elements. The data set is passed as an argument to the method.
A common workflow pattern is to create a new element in the document for each piece of data in the set. D3 has the enter() method for this purpose.
When enter() is combined with the data() method, it looks at the selected elements from the page and compares them to the number of data items in the set. If there are fewer elements than data items, it creates the missing elements.
The solution →
d3.select(“body”).selectAll(“h2”)
.data(dataset)
.enter()
.append(“h2”)
.text(“New Title”);
The D3 text() method can take a string or a callback function as an argument:
selection.text((d) => d)
In the example above, the parameter d refers to a single entry in the dataset that a selection is bound to.
The solution →
.append(“h2”)
.text((d) => (d + “ USD”))
You can also watch the video where I talk and code the next 4 of d3.js challenges.
Add Inline Styling to Elements
D3 lets you add inline CSS styles on dynamic elements with the style() method. The style() method takes a comma-separated key-value pair as an argument.
The solution → .style(“font-family”, ”verdana”);
D3 is about visualization and presentation of data. It’s likely you’ll want to change the styling of elements based on the data. You can use a callback function in the style() method to change the styling for different elements.
The solution →
.style(“color”, (d) => {
if (d<20)
return “red”
else
return “green”
})
Using a lot of inline styles on HTML elements gets hard to manage, even for smaller apps. It’s easier to add a class to elements and style that class one time using CSS rules. D3 has the attr() method to add any HTML attribute to an element, including a class name.
The attr() method works the same way that style() does. It takes comma-separated values, and can use a callback function.
The solution → .attr(“class”, “bar”);
Update the Height of an Element Dynamically
Here is how to create a simple bar chart. There are two steps to this:
1) Create a div for each data point in the array
2) Give each div a dynamic height, using a callback function in the style() method that sets height equal to the data value
Recall the format to set a style using a callback function: selection.style(“cssProperty”, (d) => d)
The solution →
.style(“height”, (d) => {
return d + “px”;
})
You can also watch the video where I talk and code the next 3 of d3.js challenges.
Change the Presentation of a Bar Chart
The solution →
line 5: margin: 2px;
line 22: .style(“height”, (d) => (10 * d + “px”))
SVG stands for Scalable Vector Graphics.
Here “scalable” means that, if you zoom in or out on an object, it would not appear pixelated. It scales with the display system, whether it’s on a small mobile screen or a large TV monitor.
SVG is used to make common geometric shapes. Since D3 maps data into a visual representation, it uses SVG to create the shapes for the visualization. SVG shapes for a web page must go within an HTML svg tag.
CSS can be scalable when styles use relative units (such as vh, vw, or percentages), but using SVG is more flexible to build data visualizations.
The solution →
.append(‘svg’)
.attr(“width”, w)
.attr(“height”, h)
There are a number of supported shapes in SVG, such as rectangles and circles. They are used to display data. For example, a rectangle (<rect>) SVG shape could create a bar in a bar chart. When you place a shape into the svg area, you can specify where it goes with x and y coordinates. The origin point of (0, 0) is in the upper-left corner. Positive values for x push the shape to the right, and positive values for y push the shape down from the origin point.
To place a shape in the middle of the 500 (width) x 100 (height) svg from last challenge, the x coordinate would be 250 and the y coordinate would be 50. An SVG rect has four attributes. There are the x and y coordinates for where it is placed in the svg area. It also has a height and width to specify the size.
The solution →
append(“rect”)
.attr(“x”, 0)
.attr(“y”, 0)
.attr(“width”, 25)
.attr(“height”, 100)
You can also watch the video where I talk and code the next 4 of d3.js challenges.
Create a Bar for Each Data Point in the Set
The solution →
.data(dataset)
.enter()
.append(“rect”)
Dynamically Set the Coordinates for Each Bar
The placement of a rectangle is handled by the x and y attributes. They tell D3 where to start drawing the shape in the svg area. The last challenge set them each to 0, so every bar was placed in the upper-left corner.
For a bar chart, all of the bars should sit on the same vertical level, which means the y value stays the same (at 0) for all bars. The x value, however, needs to change as you add new bars. Remember that larger x values push items farther to the right. As you go through the array elements in dataset, the x value should increase.
The attr() method in D3 accepts a callback function to dynamically set that attribute. The callback function takes two arguments, one for the data point itself (usually d) and one for the index of the data point in the array.
It’s important to note that you do NOT need to write a for loop or use forEach() to iterate over the items in the data set. Recall that the data() method parses the data set, and any method that’s chained after data() is run once for each item in the data set.
The solution → return i * 30;
Dynamically Change the Height of Each Bar
The height of each bar can be set to the value of the data point in the array, similar to how the x value was set dynamically.
The solution → return d * 3;
In SVG, the origin point for the coordinates is in the upper-left corner. An x coordinate of 0 places a shape on the left edge of the SVG area. A y coordinate of 0 places a shape on the top edge of the SVG area. Higher x values push the rectangle to the right. Higher y values push the rectangle down.
To make the bars right-side-up, you need to change the way the y coordinate is calculated. It needs to account for both the height of the bar and the total height of the SVG area.
The solution → return h-(3 * d);
You can also watch the video where I talk and code the next 5 of d3.js challenges.
Change the Color of an SVG Element
SVG has a way to change the color of the bars.
In SVG, a rect shape is colored with the fill attribute. It supports hex codes, color names, and rgb values, as well as more complex options like gradients and transparency.
The solution → .attr(“fill”, “navy”)
D3 lets you label a graph element, such as a bar, using the SVG text element. Like the rect element, a text element needs to have x and y attributes, to place it on the SVG canvas. It also needs to access the data to display those values. D3 gives you a high level of control over how you label your bars.
The solution →
.append(“text”)
.attr(“x”, (d, i ) => i * 30)
.attr(“y”, (d, i) => (h — 3* d)-3)
.text((d) => d)
D3 methods can add styles to the bar labels. The fill attribute sets the color of the text for a text node. The style() method sets CSS rules for other styles, such as “font-family” or “font-size”.
The solution →
.attr(“font-size”, 25)
.attr(“fill”, “red”)
Add a Hover Effect to a D3 Element
It’s possible to add effects that highlight a bar when the user hovers over it with the mouse. So far, the styling for the rectangles is applied with the built-in D3 and SVG methods, but you can use CSS as well.
You set the CSS class on the SVG elements with the attr() method. Then the :hover pseudo-class for your new class holds the style rules for any hover effects.
The solution → .attr(“class”, “bar”)
A tooltip shows more information about an item on a page when the user hovers over that item. There are several ways to add a tooltip to a visualization, this challenge uses the SVG title element.
title pairs with the text() method to dynamically add data to the bars.
The solution →
.append(“title”)
.text((d) => d)
You can also watch the video where I talk and code the next 4 of d3.js challenges.
Create a Scatterplot with SVG Circles
A scatter plot is another type of visualization. It usually uses circles to map data points, which have two values each. These values tie to the x and y axes, and are used to position the circle in the visualization.
SVG has a circle tag to create the circle shape. It works a lot like the rect elements you used for the bar chart.
The solution →
.data(dataset)
.enter()
.append(“circle”)
Add Attributes to the Circle Elements
A circle in SVG has three main attributes. The cx and cy attributes are the coordinates. They tell D3 where to position the center of the shape on the SVG canvas. The radius (r attribute) gives the size of the circle.
Just like the rect y coordinate, the cy attribute for a circle is measured from the top of the SVG canvas, not from the bottom.
All three attributes can use a callback function to set their values dynamically. Remember that all methods chained after data(dataset) run once per item in dataset. The d parameter in the callback function refers to the current item in dataset, which is an array for each point. You use bracket notation, like d[0], to access the values in that array.
The solution →
.attr(“cx”, (d) => d[0])
.attr(“cy”, (d) => h-d[1])
.attr(“r”, 5)
Add Labels to Scatter Plot Circles
The text nodes need x and y attributes to position it on the SVG canvas. In this challenge, the y value (which determines height) can use the same value that the circle uses for its cy attribute. The x value can be slightly larger than the cx value of the circle, so the label is visible. This will push the label to the right of the plotted point.
The solution →
.attr(“x”, (d, i) => d[0] + 5)
.attr(“y”, (d, i) => h-d[1])
.text((d) => (d[0] + “, “ + d[1]))
In D3, there are scales to help plot data. Scales are functions that tell the program how to map a set of raw data points onto the pixels of the SVG canvas. It’s unlikely you would plot raw data as-is. Before plotting it, you set the scale for your entire data set, so that the x and y values fit your canvas width and height.
D3 has several scale types. For a linear scale (usually used with quantitative data), there is the D3 method scaleLinear():
const scale = d3.scaleLinear()
By default, a scale uses the identity relationship. The value of the input is the same as the value of the output. A separate challenge covers how to change this.
The solution →
line 5 and 6:
const scale = d3.scaleLinear(); // Create the scale here
const output = scale(50); // Call the scale with an argument here
You can also watch the video where I talk and code the next 3 of d3.js challenges.
Set a Domain and a Range on a Scale
By default, scales use the identity relationship — the input value maps to the output value. But scales can be much more flexible and interesting. The domain() and range() methods set these values for the scale. Both methods take an array of at least two elements as an argument.
The solution →
scale.domain([250, 500]);
scale.range([10, 150]);
Use the d3.max and d3.min Functions to Find Minimum and Maximum Values in a Dataset
Often when you set the domain, you’ll want to use the minimum and maximum values within the data set. Trying to find these values manually, especially in a large data set, may cause errors.
D3 has two methods — min() and max() to return this information. Fortunately, both the min() and max() methods take a callback function.
The solution →
line 5 and 6:
d3.max(positionData, (d) => d[2])
const output = d3.max(positionData, (d) => d[2]); // Change this line
The solution →
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h — padding, padding]);
You can also watch the video where I talk and code the last d3.js challenges.
Use a Pre-Defined Scale to Place Elements
You set the coordinate attribute values for an SVG shape with the scaling function. This includes x and y attributes for rect or text elements, or cx and cy for circles. Scales set shape coordinate attributes to place the data points onto the SVG canvas. You don’t need to apply scales when you display the actual data value, for example, in the text() method for a tooltip or label.
The solution →
from line 37:
.attr(‘cx’, d => xScale(d[0]))
.attr(‘cy’, d => yScale(d[1]))
.attr(‘r’, 5)
from line 51:
.attr(“x”, (d) => xScale(d[0] + 10))
.attr(‘y’, (d) => yScale(d[1]));
D3 has two methods axisLeft() and axisBottom() to render the y and x axes, respectively. (Axes is the plural form of axis). Here’s an example to create the x-axis based on the xScale in the previous challenges:
const xAxis = d3.axisBottom(xScale);
Apply a transform attribute to position the axis on the SVG canvas in the right place. Otherwise, the line would render along the border of SVG canvas and wouldn’t be visible.
SVG supports different types of transforms, but positioning an axis needs translate. When it’s applied to the g element, it moves the whole group over and down by the given amounts.
The y-axis works is the same way, except the translate argument is in the form (x, 0). Because translate is a string in the attr() method above, you can use concatenation to include variable values for its arguments.
The solution →
line 51: const yAxis = d3.axisLeft(yScale);
line 59:
svg.append(“g”)
.attr(“transform”, “translate(0, “ + (h — padding) + “)”)
.call(yAxis);
--
Are you still here?! Well, if you are congratulations! You just finished the data visualization challenges by freecodecamp!
Disclaimer: Data visualization definitions are by freecodecamp.org