diff --git a/PIE.md b/PIE.md index 89dcf46..e27f00f 100644 --- a/PIE.md +++ b/PIE.md @@ -1,7 +1,22 @@ # Creating a Pie Chart +## Introduction + +In this section we'll be using animations to make our graphs move. This can give your visualizations a more polished and professional feel. By the end of this section, you'll be able to: + +1. Create an ordinal scale +1. Create a color scale +1. Add paths for each pie segment +1. Generate an arc creating function +1. Format the data for the arc +1. Adjust the position of the pie +1. Make a donut graph +1. Remove parts of the pie + ## Set Up +As always, we'll need an `index.html` file: + ```html @@ -21,6 +36,28 @@ ## Set Config Vars +At the bottom of the `
` tag, we're referencing an `app.js` file. Let's create that file, and add the following to it: + +```javascript +var WIDTH = 360; +var HEIGHT = 360; +var radius = Math.min(WIDTH, HEIGHT) / 2; + +var dataset = [ + { label: 'Bob', count: 10 }, + { label: 'Sally', count: 20 }, + { label: 'Matt', count: 30 }, + { label: 'Jane', count: 40 } +]; +console.log(dataset); +``` + +To be sure it's working and linked up properly, we've added the `console.log(dataset)` at the bottom. Let's open up `index.html` and view the developer console to make sure everything is hooked up the way it should be: + + + +Once we're sure, it's working, remove the `console.log(dataset);`: + ```javascript var WIDTH = 360; var HEIGHT = 360; @@ -36,7 +73,9 @@ var dataset = [ ## Create an Ordinal Scale -An ordinal scale maps discrete values (can't be interpolated) to discrete values. +An ordinal scale maps a discrete value to some other value. A discrete value is something can't be divided. In the past, we've used values like numbers that can be divided up and interpolated. Interpolated just means that for any two numbers, we can find other numbers in between them. For instance, given 10 and 5, we can find values between them (e.g. 6, 8.2, 7, 9.9, etc). Now we want to map values that can't be interpolated, the `label` properties in our dataset (`Bob`, `Sally`, `Matt`, `Jane`). What values lie between `Bob` and `Sally`? How about between `Bob` and `Matt`? There are none. These are just strings, not numerical values that can be divided up and interpolated. + +What we want to do, is map these discrete values to other values. Here's an example of how to do this with an ordinal scale: ```javascript var mapper = d3.scaleOrdinal(); @@ -48,25 +87,37 @@ console.log(mapper('Sally')); console.log(mapper('Zagthor')); ``` -You cannot invert ordinal scales: +The previous code should produce the following: + + + +**NOTE** When working with ordinal scales, you'll need to list all values for both domain and range. Even if one set is numerical (in the previous case, the range), you'll still need to list each value. If we had just listed the min/max for the range, omitting `63`, D3 would have no idea what value to map `Sally` to. After all, how close is `Sally` to `Bob` as a value? How close is `Sally` to `Zagthor` as a value? There's no way to calculate that distance, since they're all strings of text, not numbers. + +One thing that's surprising, is that you can't invert ordinal scales: ```javascript console.log(mapper.invert(45)); ``` + + +D3 can only go in one direction: from domain to range. + ## Create the color scale to map labels to colors -D3 comes with lots of pre-made color schemes: +Now we want to map the `label` properties of our data set to colors, instead of random numbers like in the previous section. We can come up with our own color scheme, or choose one of D3's set of colors: - https://github.com/d3/d3-scale/blob/master/README.md#category-scales - https://github.com/d3/d3-scale-chromatic#categorical -They're just arrays: +If we want to, we can see that these color schemes are just arrays: ```javascript console.log(d3.schemeCategory10) ``` + + Consequently, we can use them when setting a range: ```javascript @@ -74,7 +125,7 @@ var colorScale = d3.scaleOrdinal(); colorScale.range(d3.schemeCategory10); ``` -We can generate an array of labels for the domain using JavaScript's map function: +We can generate an array of labels for the domain using JavaScript's native map function: ```javascript colorScale.domain(dataset.map(function(element){ @@ -82,9 +133,30 @@ colorScale.domain(dataset.map(function(element){ })); ``` +Here's our code so far: + +```javascript +var WIDTH = 360; +var HEIGHT = 360; +var radius = Math.min(WIDTH, HEIGHT) / 2; + +var dataset = [ + { label: 'Bob', count: 10 }, + { label: 'Sally', count: 20 }, + { label: 'Matt', count: 30 }, + { label: 'Jane', count: 40 } +]; + +var colorScale = d3.scaleOrdinal(); +colorScale.range(d3.schemeCategory10); +colorScale.domain(dataset.map(function(element){ + return element.label; +})); +``` + ## Set up the svg -Standard: +This is pretty standard: ```javascript d3.select('svg') @@ -94,6 +166,8 @@ d3.select('svg') ## Add paths for each pie segment +Let's add `path` elements for each element in our dataset: + ```javascript var path = d3.select('g').selectAll('path') .data(dataset) @@ -104,9 +178,13 @@ var path = d3.select('g').selectAll('path') }); ``` +If we examine our elements in the developer tools, we'll see the paths were added, and each path has a fill value, as determined by `colorScale(d.label)`, which is mapping the label of each data object to a color: + + + ## Generate an arc creating function -Next we want to do something like this: +The paths have fill colors, but no shape. If you'll recall, `