forked from IsaKiko/D3-visualising-data
-
Notifications
You must be signed in to change notification settings - Fork 0
/
07-d3setup.html
149 lines (149 loc) · 16.5 KB
/
07-d3setup.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<title>Software Carpentry: D3 setup</title>
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap-theme.css" />
<link rel="stylesheet" type="text/css" href="css/swc.css" />
<link rel="alternate" type="application/rss+xml" title="Software Carpentry Blog" href="http://software-carpentry.org/feed.xml"/>
<meta charset="UTF-8" />
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body class="lesson">
<div class="container card">
<div class="banner">
<a href="http://software-carpentry.org" title="Software Carpentry">
<img alt="Software Carpentry banner" src="img/software-carpentry-banner.png" />
</a>
</div>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<h1 class="title">D3 setup</h1>
<h2 class="subtitle">Setting up html for our data visualisation</h2>
<div id="learning-objectives" class="objectives panel panel-warning">
<div class="panel-heading">
<h2 id="learning-objectives" class="objectives panel panel-warning"><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2>
</div>
<div class="panel-body">
<ul>
<li>Setting up an html file to contain the plot</li>
<li>Reading in data from a given <code>.json</code> file</li>
<li>Structuring the html content</li>
</ul>
</div>
</div>
<p>We’ve finally learned everything we need to know to start using D3. D3 is a JavaScript library. This means that we can use all of the JavaScript commands that we have already learned, but on top of these, there are a few new functions that will make our life easier.</p>
<p>The main purpose of D3 is to create visualisations of data online. Because it uses JavaScript, it is possible to make graphs interactive!</p>
<p>As a little refresher, we will repeat a little bit html to set up our page.</p>
<p>Create a new GitHub repository and create a gh-pages branch to which you commit. This is, where our actual page will live. Then create <code>index.html</code> in the new repository containing the following:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="dt"><!DOCTYPE </span>html<span class="dt">></span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="kw"><html></span></a>
<a class="sourceLine" id="cb1-3" data-line-number="3"> <span class="kw"><head></span></a>
<a class="sourceLine" id="cb1-4" data-line-number="4"> <span class="kw"><title></span>The Wealth <span class="er">&</span> Health of Nations<span class="kw"></title></span></a>
<a class="sourceLine" id="cb1-5" data-line-number="5"> <span class="kw"><link</span><span class="ot"> rel=</span><span class="st">"stylesheet"</span><span class="ot"> type=</span><span class="st">"text/css"</span><span class="ot"> href=</span><span class="st">"main.css"</span> <span class="kw">/></span></a>
<a class="sourceLine" id="cb1-6" data-line-number="6"> <span class="kw"></head></span></a>
<a class="sourceLine" id="cb1-7" data-line-number="7"> <span class="kw"><body></span></a>
<a class="sourceLine" id="cb1-8" data-line-number="8"></a>
<a class="sourceLine" id="cb1-9" data-line-number="9"> <span class="kw"><h1></span>The Wealth <span class="er">&</span> Health of Nations<span class="kw"></h1></span></a>
<a class="sourceLine" id="cb1-10" data-line-number="10"></a>
<a class="sourceLine" id="cb1-11" data-line-number="11"> <span class="kw"><div</span><span class="ot"> id=</span><span class="st">"chart_area"</span><span class="kw">></div></span></a>
<a class="sourceLine" id="cb1-12" data-line-number="12"></a>
<a class="sourceLine" id="cb1-13" data-line-number="13"> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"https://d3js.org/d3.v5.min.js"</span><span class="kw">></script></span></a>
<a class="sourceLine" id="cb1-14" data-line-number="14"> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"main.js"</span><span class="kw">></script></span></a>
<a class="sourceLine" id="cb1-15" data-line-number="15"> <span class="kw"></body></span></a>
<a class="sourceLine" id="cb1-16" data-line-number="16"><span class="kw"></html></span></a></code></pre></div>
<p>There are a few things in this file that look new: <code><link rel="stylesheet" type="text/css" href="main.css" /></code> is linking the local CSS file <code>main.css</code>(that can just be an empty file for now). <code><script src="main.js"></script></code> is linking the JavaScript file, the file in which all the action will happen.</p>
<p>Additionally, we now need to link d3 using <code><script src="https://d3js.org/d3.v5.min.js"></script></code>. The order matters. Since code is executed sequentially and we want to use parts of the D3 library in our own script, we have to link to d3.js first.</p>
<p>The last bit, that’s important here is an HTML element (paragraph) we create. We give it an id <code>chart_area</code>. This is the area we reserve for our pretty chart. We will use JavaScript (and D3) to fill it in.</p>
<p>Now, let’s write main.js.</p>
<p>Similar to the syntax we’ve already seen (<code>JSON.stringify</code>), D3-specific functions can be called using a <code>d3.</code>-syntax.</p>
<p>The first thing we need, is of course our data, which we can find at ‘https://raw.githubusercontent.com/MQ-software-carpentry/D3-visualising-data/gh-pages/code/nations.json’. D3 provides a handy function to read in <code>json</code>-files:</p>
<pre class="d3"><code>var dataUrl = "https://raw.githubusercontent.com/MQ-software-carpentry/D3-visualising-data/gh-pages/code/nations.json";
d3.json(dataUrl).then(function(nations) { /* ... */ });</code></pre>
<p>This line probably needs a little explanation and we’ll go through it bit by bit:</p>
<ul>
<li><code>d3.json()</code> is called the function call. In this case, we have a function that reads in a json file, parses it, and is also able to do something with the parsed data on the way.</li>
<li>The first argument <code>dataUrl</code> tells the function where to get the data we want to have parsed.</li>
<li><code>function(...){...}</code> is called the callback function. It is a so-called ‘inline’ function, which means it has no name (we’re only operating in the object space here). This also means we can’t use this function anywhere else in our code. The code we put inside the curly brackets is the code that’s run once d3.json() is called and the data is loaded.</li>
<li>D3 assigns the name <code>nations</code> to the parsed object it returns. We can only use ‘nations’ within the callback function, this means our code only knows of <code>nations</code> inside the curly brackets.</li>
<li>What seems unusual, but is actually quite common, is that this function call doesn’t return anything. It is simply executed and displayed (if we tell it to), but no value is returned.</li>
</ul>
<div id="what-else-can-i-read-in-conveniently" class="callout panel panel-info">
<div class="panel-heading">
<h2 id="what-else-can-i-read-in-conveniently" class="callout panel panel-info"><span class="glyphicon glyphicon-pushpin"></span>What else can I read in conveniently?</h2>
</div>
<div class="panel-body">
<p>D3 offers the possibility to also read in csv (comma-separated values) files directly. See <a href="https://github.com/mbostock/d3/wiki/CSV">here</a> for an example. Also available are functions to read in tab-separated values (tsv) and files with arbitrary delimiter (dsv).</p>
</div>
</div>
<p>So naturally, the next step is to think about what we want to happen between the curly brackets. For now, we want to:</p>
<ul>
<li>Link JavaScript to HTML page</li>
<li>Insert an SVG canvas</li>
<li>Create axes (x: income per capita, y: life expectancy)</li>
<li>Display data points (scatter plot)</li>
</ul>
<p>First, let’s draw a little schematic of how we want the page to be structured.</p>
<p><img src="img/chart_area.png" alt="What we want.." width="700" /></p>
<p>We already set up our HTML page to contain a chart area. That’s the space we want to fill now. We’ll have a picture frame (an SVG-element), our drawing area (a g-element), and in that drawing area, we’ll have separate elements for both axes and the area for our circles.</p>
<p>What we now want to end up with in our html document is this:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="kw"><div</span><span class="ot"> id=</span><span class="st">"chart_area"</span><span class="kw">></span> <span class="kw"><svg></span> <span class="kw"></svg></span> <span class="kw"></div></span></a></code></pre></div>
<p>But this time, we want to create these elements automatically using JavaScript only. First, we need to link the JavaScript and HTML environment so that we have writing access to the HTML. To do this, we use the <code>.select()</code>. This lets us grab an element by specifying its ID.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode js"><code class="sourceCode javascript"><a class="sourceLine" id="cb4-1" data-line-number="1"><span class="co">// Select the chart area by ID</span></a>
<a class="sourceLine" id="cb4-2" data-line-number="2"><span class="kw">var</span> chart_area <span class="op">=</span> <span class="va">d3</span>.<span class="at">select</span>(<span class="st">"#chart_area"</span>)<span class="op">;</span></a></code></pre></div>
<p>Now we’re setting up the grid by appending the chart area by the SVG picture frame.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode js"><code class="sourceCode javascript"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="kw">var</span> frame <span class="op">=</span> <span class="va">chart_area</span>.<span class="at">append</span>(<span class="st">"svg"</span>)<span class="op">;</span></a></code></pre></div>
<p>in the HTML file. We chose to append because we now have access to the SVG element without the need to seperately select it by ID.</p>
<p>We also create the canvas inside the frame:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode js"><code class="sourceCode javascript"><a class="sourceLine" id="cb6-1" data-line-number="1"><span class="co">// Create canvas inside frame.</span></a>
<a class="sourceLine" id="cb6-2" data-line-number="2"><span class="kw">var</span> canvas <span class="op">=</span> <span class="va">frame</span>.<span class="at">append</span>(<span class="st">"g"</span>)<span class="op">;</span></a></code></pre></div>
<p>Let’s set up the dimensions for our elements that we want to use:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode js"><code class="sourceCode javascript"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="co">// Set margins, width, and height.</span></a>
<a class="sourceLine" id="cb7-2" data-line-number="2"><span class="kw">var</span> margin <span class="op">=</span> <span class="op">{</span><span class="dt">top</span><span class="op">:</span> <span class="fl">19.5</span><span class="op">,</span> <span class="dt">right</span><span class="op">:</span> <span class="fl">19.5</span><span class="op">,</span> <span class="dt">bottom</span><span class="op">:</span> <span class="fl">19.5</span><span class="op">,</span> <span class="dt">left</span><span class="op">:</span> <span class="fl">39.5</span><span class="op">};</span></a>
<a class="sourceLine" id="cb7-3" data-line-number="3"><span class="kw">var</span> frame_width <span class="op">=</span> <span class="dv">960</span><span class="op">;</span></a>
<a class="sourceLine" id="cb7-4" data-line-number="4"><span class="kw">var</span> frame_height <span class="op">=</span> <span class="dv">350</span><span class="op">;</span></a>
<a class="sourceLine" id="cb7-5" data-line-number="5"><span class="kw">var</span> canvas_width <span class="op">=</span> frame_width <span class="op">-</span> <span class="va">margin</span>.<span class="at">left</span> <span class="op">-</span> <span class="va">margin</span>.<span class="at">right</span><span class="op">;</span></a>
<a class="sourceLine" id="cb7-6" data-line-number="6"><span class="kw">var</span> canvas_height <span class="op">=</span> frame_height <span class="op">-</span> <span class="va">margin</span>.<span class="at">top</span> <span class="op">-</span> <span class="va">margin</span>.<span class="at">bottom</span><span class="op">;</span></a></code></pre></div>
<p>…and apply them to the actual elements:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode js"><code class="sourceCode javascript"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="co">// Set frame attributes width and height.</span></a>
<a class="sourceLine" id="cb8-2" data-line-number="2"><span class="va">frame</span>.<span class="at">attr</span>(<span class="st">"width"</span><span class="op">,</span> frame_width)<span class="op">;</span></a>
<a class="sourceLine" id="cb8-3" data-line-number="3"><span class="va">frame</span>.<span class="at">attr</span>(<span class="st">"height"</span><span class="op">,</span> frame_height)<span class="op">;</span></a></code></pre></div>
<p>The canvas element will have to fit nicely into the frame. To make it fit, we set a transform attribute and use the translate function.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode js"><code class="sourceCode javascript"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="co">// Shift the canvas</span></a>
<a class="sourceLine" id="cb9-2" data-line-number="2"><span class="va">canvas</span>.<span class="at">attr</span>(<span class="st">"transform"</span><span class="op">,</span> <span class="st">"translate("</span> <span class="op">+</span> <span class="va">margin</span>.<span class="at">left</span> <span class="op">+</span> <span class="st">","</span> <span class="op">+</span> <span class="va">margin</span>.<span class="at">top</span> <span class="op">+</span> <span class="st">")"</span>)<span class="op">;</span></a>
<a class="sourceLine" id="cb9-3" data-line-number="3"><span class="co">// and make it slightly smaller than the svg canvas</span></a>
<a class="sourceLine" id="cb9-4" data-line-number="4"><span class="va">canvas</span>.<span class="at">attr</span>(<span class="st">"width"</span><span class="op">,</span> canvas_width)<span class="op">;</span></a>
<a class="sourceLine" id="cb9-5" data-line-number="5"><span class="va">canvas</span>.<span class="at">attr</span>(<span class="st">"height"</span><span class="op">,</span> canvas_height)<span class="op">;</span></a></code></pre></div>
<div id="adding-svgs-from-javascript-file" class="challenge panel panel-success">
<div class="panel-heading">
<h1 id="adding-svgs-from-javascript-file" class="challenge panel panel-success"><span class="glyphicon glyphicon-pencil"></span>Adding SVGs from JavaScript file</h1>
</div>
<div class="panel-body">
<ol type="1">
<li>Add a SVG circle element to the frame.</li>
<li>Once the circle reference is obtained, make the radius 40px, the border black and the colour green.</li>
</ol>
<p>HINT: You can use the <code>attr</code> method on the circle object obtained.</p>
</div>
</div>
</div>
</div>
<div class="footer">
<a class="label swc-blue-bg" href="http://software-carpentry.org">Software Carpentry</a>
<a class="label swc-blue-bg" href="https://github.com/swcarpentry/lesson-template">Source</a>
<a class="label swc-blue-bg" href="mailto:[email protected]">Contact</a>
<a class="label swc-blue-bg" href="LICENSE.html">License</a>
</div>
</div>
<!-- Javascript placed at the end of the document so the pages load faster -->
<script src="js/jquery.min.js"></script>
<script src="css/bootstrap/bootstrap-js/bootstrap.js"></script>
</body>
</html>