<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ D3 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ D3 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:21:03 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/d3/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Data Visualization with D3.js ]]>
                </title>
                <description>
                    <![CDATA[ D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. We just published a full course on the freeCodeCamp.org YouTube channel that teaches how to implement various data visua... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/data-visualizatoin-with-d3/</link>
                <guid isPermaLink="false">66b201fd297cd6de0bd54614</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 05 May 2022 17:43:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/05/dataviz.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS.</p>
<p>We just published a full course on the freeCodeCamp.org YouTube channel that teaches how to implement various data visualization techniques with D3.js.</p>
<p>Curran Kelleher teaches this course. He is one of the top D3 instructors in the world. He has a Ph.D. in Computer Science, and has taught at universities including MIT. This is the third time Curran has taught this course, and it gets better every time. </p>
<p>Curran originally taught this course in a series of live streams. Now, for the first time, you can watch the entire course in a single video. </p>
<p>In this course, the code is organized in such a way that the rendering logic (e.g. DOM manipulation) is decoupled from the data transformation logic (e.g. transform rows into objects that represent graphical marks). This approach makes it straightforward to adapt the core of the visualization technique to work with various frameworks like React, Vue, Svelte, and others.</p>
<p>Here are the sections covered in this course:</p>
<ul>
<li>SVG Fundamentals</li>
<li>Pseudo Visualizations</li>
<li>Sol LeWitt in Vanilla JS</li>
<li>Sol LeWitt in D3</li>
<li>D3 Selections</li>
<li>JavaScript Modules &amp; Build Tools</li>
<li>Productizing a Codebase</li>
<li>Scatter Plot</li>
<li>Reusable Charts</li>
<li>Dynamic Charts</li>
<li>Charts with Menus</li>
<li>Quantitative and Categorical</li>
<li>Closing the Series</li>
</ul>
<p>Watch the full course below or on <a target="_blank" href="https://www.youtube.com/watch?v=xkBheRZTkaw">the freeCodeCamp.org YouTube channel</a> (20-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/xkBheRZTkaw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ D3.js Tutorial – Data Visualization for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I'm going to walk you through how to use D3.js in a step by step and beginner-friendly way. We'll talk about what D3.js is, how it works, and we'll create some basic visualizations to add transitions, interactions, and zooming. Table... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/d3js-tutorial-data-visualization-for-beginners/</link>
                <guid isPermaLink="false">66d46150706b9fb1c166b9bd</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ D3.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Spruce Emmanuel ]]>
                </dc:creator>
                <pubDate>Wed, 24 Nov 2021 15:03:01 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/11/Group-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I'm going to walk you through how to use D3.js in a step by step and beginner-friendly way.</p>
<p>We'll talk about what D3.js is, how it works, and we'll create some basic visualizations to add transitions, interactions, and zooming.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-getting-started-with-d3js">Getting Started</a> What is D3.js? How to Set Up a D3.js Environment</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-select-elements-in-d3">Selections</a> How to Select Elements in D3 How to Modify Elements in D3</p>
</li>
<li><p><a class="post-section-overview" href="#heading-d3-is-data-driven">D3 is Data Driven</a> Data Join in D3 Data Loading in D3</p>
</li>
<li><p><a class="post-section-overview" href="#heading-scales-in-d3">Scales in D3</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-bar-chart-with-d3js">Create a bar chart with d3.js</a> Axis Component in D3 D3 Margin Convention How to Style it With CSS in D3</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-world-map-with-d3jsone-of-the-things-i-personally-love-about-d3-is-its-ability-to-handle-geographic-data-unlike-our-former-examples-which-used-json-data-format-maps-now-well-use-a-special-form-of-json-data-called-geojsonyou-can-find-the-geojson-data-we-are-going-to-use-herelike-in-our-other-examples-lets-first-select-our-svg-element-in-the-document-and-also-set-up-the-margin-conventionconst-margin-top-5-right-5-bottom-5-left-5-width-documentqueryselectorbodyclientwidth-height-500-const-svg-d3selectd3demoattrviewbox-0-0-width-height-html-next-to-generate-our-map-well-need-a-projection-to-render-spherical-coordinates-in-our-data-file-and-a-path-generator-to-convert-the-projected-coordinates-to-a-svg-path-which-is-then-rendered-on-the-screenlet-projection-d3geoequirectangularcenter0-0-d3-provides-a-lot-of-projections-i-only-used-this-one-because-i-like-it-now-that-we-have-chosen-our-projection-lets-convert-it-to-an-svg-path-d3-handles-the-conversion-for-us-when-we-use-the-d3geopath-method-this-method-takes-in-a-projection-the-one-we-defined-aboveconst-pathgenerator-d3geopathprojectionprojection-we-dont-want-to-draw-the-map-directly-on-the-svg-because-we-are-going-to-be-adding-animations-and-zooming-later-on-so-we-append-a-g-element-to-the-selected-svglet-g-svgappendg-then-well-load-our-data-for-the-mapd3jsonhttpsrawgithubusercontentcomiamspruceintro-d3maindatacountries-110mgeojson-thendata-gt-consolelogdata-if-this-doesnt-make-sense-i-suggest-you-re-read-the-data-loading-sectionlastly-lets-use-our-pathgenerator-to-generate-our-paths-gselectallpath-datadatafeatures-joinpath-attrd-pathgenerator-above-we-used-d3-data-join-to-append-a-path-for-each-country-and-then-set-the-d-attribute-to-our-pathgeneratorattrd-pathgenerator-and-in-case-that-isnt-clear-its-the-equivalent-of-writing-thisattrd-d-gt-pathgeneratord-you-can-find-the-final-code-and-live-preview-on-codepen">Create a World Map with d3.js</a> How to Use Multiple Datasets in D3.js Map with city names Event Handling with D3.js Map with Panning and Zooming Programmatic zooming Adding ToolTips</p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-who-is-this-article-for">Who is this article for?</h2>
<p>This article is aimed at developers who already have a basic knowledge of HTML, CSS, SVG and JavaScript who want to learn how to visualize data with D3.js.</p>
<p>This article is suitable for both complete beginners and those who already have some experience working with D3.js.</p>
<p>By the end of this article, you should understand how D3.js works and how to create visualizations with your data.</p>
<h2 id="heading-getting-started-with-d3js">Getting Started with D3.js</h2>
<p>D3.js is a JavaScript library for creating visualizations like charts, maps, and more on the web.</p>
<blockquote>
<p><strong>D3.js</strong> (also known as <strong>D3</strong>, short for <strong>Data-Driven Documents</strong>) is a JavaScript library for producing dynamic, interactive <a target="_blank" href="https://en.wikipedia.org/wiki/Data_visualization">data visualizations</a> in web browsers. It makes use of Scalable Vector Graphics (SVG), HTML5, and Cascading Style Sheets (CSS) standards. – Wikipedia</p>
</blockquote>
<p>Unlike many other data visualization libraries that provide ready made charts, D3 gives you lots of creative freedom as you have total control over the visualizations you create. D3 also uses web technologies like HTML, CSS, SVG and JavaScript.</p>
<p>In addition to the fact that D3 uses these familiar technologies, it has several other benefits:</p>
<ul>
<li><p>D3 is extremely fast,</p>
</li>
<li><p>It encourages code reusability</p>
</li>
<li><p>It supports large datasets and provides an easy way of loading and transforming data</p>
</li>
<li><p>It's good for creating visualizations with rich interactions</p>
</li>
</ul>
<h3 id="heading-how-to-set-up-a-d3-environment">How to Set Up a D3 Environment</h3>
<p>D3 works in all modern browsers, and at the time of writing this article, D3.js is on version 7 (v7).</p>
<p>To use the latest version of D3 you have to link to it on your web page like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://d3js.org/d3.v7.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>However for the purposes of teaching, all examples in this article are on <a target="_blank" href="https://codepen.io">Codepen</a>, so you can edit the live examples.</p>
<h2 id="heading-how-to-select-elements-in-d3">How to Select Elements in D3</h2>
<p>When you're coding in JavaScript and you need to modify elements on a page, you need to select those elements. D3.js works the same way, and provides us with two methods to select DOM elements:</p>
<ul>
<li><p><code>d3.select()</code></p>
</li>
<li><p><code>d3.selectAll()</code></p>
</li>
</ul>
<p>Both of this selector methods will take in any CSS selector and return the element that matches the specified selector. If no element matches the selector it will return an empty selection.</p>
<p>The <code>d3.select()</code> method will select the first element that matches in the DOM (from top to bottom).</p>
<pre><code class="lang-javascript">d3.select(<span class="hljs-string">"#d3_p"</span>).style(<span class="hljs-string">"color"</span>, <span class="hljs-string">"blue"</span>);

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_p"</span>&gt;</span> hello world 1<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>If there are multiple elements that match the specified selector, <a target="_blank" href="http://d3.select"><code>d3.select</code></a><code>()</code> will match the first one it finds.</p>
<pre><code class="lang-javascript">&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"d3_example"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_p-all"</span>&gt;</span> hello world 1<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_p-all"</span>&gt;</span> hello world 2<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_p-all"</span>&gt;</span> hello world 3<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_p-all"</span>&gt;</span> hello world 4<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>The <code>d3.selectAll()</code> method works very similarly to <a target="_blank" href="http://d3.select"><code>d3.select</code></a><code>()</code> – but instead it selects ALL elements that match the selector:</p>
<pre><code class="lang-javascript">d3.selectAll
(<span class="hljs-string">".d3_p"</span>).style(<span class="hljs-string">"color"</span>, <span class="hljs-string">"blue"</span>);

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_p"</span>&gt;</span> hello world 1<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_p"</span>&gt;</span> hello world 2<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_p"</span>&gt;</span> hello world 3<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_p"</span>&gt;</span> hello world 4<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<h3 id="heading-how-to-modify-elements-in-d3">How to Modify Elements in D3</h3>
<p>After you have selected your DOM elements, D3 provides the following methods to modify them:</p>
<pre><code class="lang-javascript">| Method   |      Usage      |  Example |  
|---|---|---|
| <span class="hljs-string">`.attr()`</span> |  Update selected element attribute | <span class="hljs-string">`d3.select("p").attr("name", "fred")`</span> | 
| <span class="hljs-string">`..classed()`</span> | Assigns or unassigns the specified CSS <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">names</span> <span class="hljs-title">on</span> <span class="hljs-title">the</span> <span class="hljs-title">selected</span> <span class="hljs-title">elements</span>   |   `<span class="hljs-title">d3</span>.<span class="hljs-title">select</span>("<span class="hljs-title">p</span>").<span class="hljs-title">classed</span>("<span class="hljs-title">radio</span>", <span class="hljs-title">true</span>)</span>;<span class="hljs-string">` |
| `</span>.style()<span class="hljs-string">`  | Updates the style property |    `</span>d3.select(<span class="hljs-string">"p"</span>).style(<span class="hljs-string">"color"</span>, <span class="hljs-string">"blue"</span>);<span class="hljs-string">` |
| `</span>.property()<span class="hljs-string">` | Used to set an element property |    `</span>d3.select(<span class="hljs-string">'input'</span>).property(<span class="hljs-string">'value'</span>, <span class="hljs-string">'hello world'</span>)<span class="hljs-string">` |
| `</span>.text()<span class="hljs-string">`  | Updates selected element text content |    `</span>d3.select(<span class="hljs-string">'h1'</span>).text(<span class="hljs-string">'Learning d3.js'</span>)<span class="hljs-string">` |
| `</span>.html()<span class="hljs-string">` | Sets the inner HTML to the specified value on all selected elements |    `</span>d3.select(<span class="hljs-string">'div'</span>).html(<span class="hljs-string">'h1&gt;learning d3.js&lt;/h1&gt;'</span>)<span class="hljs-string">` |
| `</span>.append()<span class="hljs-string">`  | Appends a new element as the last child of the selected element |    `</span>d3.select(<span class="hljs-string">"div"</span>).append(<span class="hljs-string">"p"</span>)<span class="hljs-string">` |
| `</span>.insert()<span class="hljs-string">`  | Works the same as the `</span>.append()<span class="hljs-string">` method, except you can specify another element to insert before |    `</span>d3.select(<span class="hljs-string">"div"</span>).insert(<span class="hljs-string">"p"</span>, <span class="hljs-string">"h1"</span>)<span class="hljs-string">` |
| `</span>.remove()<span class="hljs-string">`  | Removes selected element from the DOM  | `</span>d3.select(<span class="hljs-string">"div"</span>).remove(<span class="hljs-string">"p"</span>)<span class="hljs-string">` |</span>
</code></pre>
<p>Don't worry if all these doesn't make sense right away – we will soon be using all these methods in our examples.</p>
<p>Each of the above DOM manipulation methods takes in a constant value or a function as a parameter which gives rise to creating <strong>Dynamic Properties.</strong></p>
<p>The function takes in two properties: the first is the data which is conventionally called <code>d</code> in d3.js, and the other is the <code>index</code>.</p>
<pre><code class="lang-javascript">d3.selectAll(<span class="hljs-string">"circle"</span>).attr(<span class="hljs-string">'cx'</span>, (<span class="hljs-function">(<span class="hljs-params">d, i</span>) =&gt;</span> i * <span class="hljs-number">100</span>))

&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"d3_example"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_svg_demo1"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">g</span> <span class="hljs-attr">transform</span>=<span class="hljs-string">"translate(50, 40)"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">r</span>=<span class="hljs-string">"30"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">r</span>=<span class="hljs-string">"30"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">r</span>=<span class="hljs-string">"30"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">g</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>As you can see above, within this function we can apply any logic to manipulate the data and output.</p>
<h2 id="heading-d3-is-data-driven">D3 is Data Driven</h2>
<p>D3.js itself is data-driven, which means it gets its super powers from data. D3 supports different types of data like arrays, CSV, XML, TSV, JSON, and so on.</p>
<p>This data can come from a local file in your working directory or can be fetched from an API.</p>
<h3 id="heading-data-joins-in-d3">Data Joins in D3</h3>
<p>D3's data join lets us join the specified data to the selected element(s). To create a data join, you can use the <code>.data()</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> fruits = [<span class="hljs-string">'Apple'</span>, <span class="hljs-string">'Orange'</span>, <span class="hljs-string">'Mango'</span>]

d3.selectAll(<span class="hljs-string">".d3_fruit"</span>).data(fruits).text(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d)
</code></pre>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_fruit"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_fruit"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Let's see what's going on here and why we got only one output instead of three.</p>
<p>So far, we have:</p>
<ol>
<li><p>3 data points in our Fruits Array</p>
</li>
<li><p>1 <code>p</code> element in our selection</p>
</li>
</ol>
<p>D3 just assigns the first fruit (Apple) in our array to the only selection <code>p</code> it got and forgets about the rest.</p>
<p>A quick fix for this is to manually create the other 2 p elements and just move on with your life. But most of the time you don't actually know how many items are in your array of data that is fetched from an external API.</p>
<p>To solve this problem, the latest versions of D3 provides us with a <code>.join()</code> method. It appends, removes, and reorders elements as necessary to match the specified data. Let's try it with our previous example to see what happens:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> fruits = [<span class="hljs-string">'Apple'</span>, <span class="hljs-string">'Orange'</span>, <span class="hljs-string">'Mango'</span>]

d3.select(<span class="hljs-string">".d3_fruit"</span>)
    .selectAll(<span class="hljs-string">"p"</span>)
    .data(fruits)
    .join(<span class="hljs-string">"p"</span>) <span class="hljs-comment">// the join method</span>
        .attr(<span class="hljs-string">"class"</span>, <span class="hljs-string">"d3_fruit"</span>)
        .text(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d)
</code></pre>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_fruit"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_fruits"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Let's break this down a bit:</p>
<ol>
<li><p>Select the <code>div</code> wrapper <code>d3_fruit</code></p>
</li>
<li><p>Select all the <code>p</code> elements even when there are no <code>p</code> elements in the div - this returns an empty selection</p>
</li>
<li><p><code>.data(fruits)</code> - Binds the fruits array to the empty selection</p>
</li>
<li><p><code>.join("p")</code> - This methods creates all the <code>p</code> elements for each item in our Array</p>
</li>
<li><p><code>.attr("class", "d3_fruit")</code> - We set a class for each <code>p</code> element that was created</p>
</li>
<li><p><code>.text((d) =&gt; d)</code> - Sets the text of each created <code>p</code> based on the fruits Array</p>
</li>
</ol>
<h3 id="heading-data-loading-in-d3">Data Loading in D3</h3>
<p>We have seen what data is to D3 and how to join data to our selections. But so far we have only used our own self-created data <code>let fruits = ['Apple', 'Orange', 'Mango']</code>.</p>
<p>In a real world scenario this is not usually the case – you sometimes have to fetch data from an API or a local file.</p>
<p>D3 has some methods to load various types of files:</p>
<ul>
<li><p>d3.json</p>
</li>
<li><p>d3.csv</p>
</li>
<li><p>d3.xml</p>
</li>
<li><p>d3.tsv</p>
</li>
<li><p>d3.text</p>
</li>
</ul>
<p>When using any of these methods, the syntax is generally the same:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// async await</span>
<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> d3.csv(<span class="hljs-string">"/path/to/file.csv"</span>);
<span class="hljs-built_in">console</span>.log(data);

<span class="hljs-comment">// or</span>
d3.json(<span class="hljs-string">"/path/to/file.json"</span>).then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {  <span class="hljs-built_in">console</span>.log(data); })
</code></pre>
<p>Let's see this in action by loading data from an actual external JSON file.</p>
<p>For this example I have a JSON file that contains all the info about Nigeria and all its states:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> el = d3.select(<span class="hljs-string">"#d3_svg_demo2"</span>);

d3.json(<span class="hljs-string">"https://raw.githubusercontent.com/iamspruce/intro-d3/main/nigeria-states.json"</span>).then(<span class="hljs-function">(<span class="hljs-params">{data}</span>) =&gt;</span> {
    el
     .selectAll(<span class="hljs-string">"p"</span>)
     .data(data)
     .join(<span class="hljs-string">"p"</span>)
      .text(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d.Name)
});



<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_svg_demo2"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>    
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>    
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>    
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>    
    ... + 31 others
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Using the above method you can fetch any data in D3.</p>
<h2 id="heading-scales-in-d3">Scales in D3</h2>
<p>Thus far, you've learned how to load and use data in D3.js. Now we need to learn about <strong>Scales</strong>. <strong>T</strong>his can be the most confusing part to learn for most folks and it's also the most important concept of D3.</p>
<p>In the last example we just looked at above, we loaded JSON data from an API and for each State in Nigeria we appended the name to a <code>p</code> element. That JSON file also contains the population of each state and some other info.</p>
<p>The population of each state ranges from the lowest at <code>2 million</code> to the highest at <code>16 million</code>. To correctly represent that data on a bar chart, for example, you need to create a bar chart with a height of <code>16000000px</code>.</p>
<p>Just imagining that, you'd probably agree that it would be a very long bar chart. That's where <code>d3.scale</code> comes in.</p>
<p>The <code>d3.scale</code> function takes in data as input and returns a visual value in pixels. <code>d3.scale</code> needs to be set with a <strong>domain</strong> and a <strong>range.</strong> The domain sets a LIMIT for the data we are trying to represent visually.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> x_scale = d3.scaleLinear()
    .domain([<span class="hljs-number">10</span>, <span class="hljs-number">500</span>])
    .range([<span class="hljs-number">2000000</span>, <span class="hljs-number">16000000</span>]);
</code></pre>
<p>Let's break this down a bit:</p>
<ul>
<li><p><code>d3.scaleLinear()</code> - we tell D3 we are going to use the scaleLinear</p>
</li>
<li><p><code>.domain([10, 500])</code> - we set the domain (Limit) from 10 to 500</p>
</li>
<li><p><code>.range([2000000, 16000000])</code> - we set our minimum value to 2 million and maximum to 16 million which means we map out 2 million to <code>10px</code> and 16 million to <code>500px</code></p>
</li>
</ul>
<p>Now if we have a city with a population of about <code>8000000</code>(half of 15 million) it would map out to a pixel value of <code>250px</code>(half of 500).</p>
<p>It is important to point out that D3 has various form of <a target="_blank" href="https://github.com/d3/d3-scale">Scales</a>. The one you decide to use we be determined by the type of data you are trying to represent.</p>
<ul>
<li><p>When you're working with data that represents dates, use <a target="_blank" href="https://github.com/d3/d3-scale#scaleTime">d3.scaleTime</a></p>
</li>
<li><p>When you're creating bar charts, use <a target="_blank" href="https://github.com/d3/d3-scale#scaleBand">d3.scaleBand</a></p>
</li>
<li><p>For other scales, refer to <a target="_blank" href="https://github.com/d3/d3-scale">d3.scale</a></p>
</li>
</ul>
<h2 id="heading-how-to-create-a-bar-chart-with-d3js">How to Create a Bar Chart with D3.js</h2>
<p>Now let's apply everything we've learned to create a real world bar chart with D3.</p>
<p>For this example we are going to continue building from the example code in the data loading section of this tutorial:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> el = d3.select(<span class="hljs-string">"#d3_svg_demo2"</span>);

d3.json(<span class="hljs-string">"https://raw.githubusercontent.com/iamspruce/intro-d3/main/nigeria-states.json"</span>).then(<span class="hljs-function">(<span class="hljs-params">{data}</span>) =&gt;</span> {
    el
     .selectAll(<span class="hljs-string">"p"</span>)
     .data(data)
     .join(<span class="hljs-string">"p"</span>)
      .text(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d.Name)
});
</code></pre>
<p>First let's create the scales for our bar chart:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> width = <span class="hljs-number">960</span>, height = <span class="hljs-number">500</span>;
<span class="hljs-keyword">const</span> x_scale = d3.scaleBand().range([<span class="hljs-number">0</span>, width])
<span class="hljs-keyword">const</span> y_scale = d3.scaleLinear().range([height, <span class="hljs-number">0</span>])
</code></pre>
<p>What's going on here:</p>
<ul>
<li><p>First we defined our x scale (horizantal scale) with a minimum of 0 and maximum of our SVG width</p>
</li>
<li><p>Secondly we set our y scale (vertical scale) to range from 0 to our SVG height</p>
</li>
</ul>
<p>Next we need to select our SVG element in the document:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> svg = d3.select(<span class="hljs-string">"#d3_demo"</span>)
    .attr(<span class="hljs-string">"width"</span>, width)
    .attr(<span class="hljs-string">"height"</span>, height)
</code></pre>
<p>Here we selected our SVG element and set the height and width to our specified height and width. Next let's fetch the JSON data from our API:</p>
<pre><code class="lang-javascript">d3.json(<span class="hljs-string">"https://raw.githubusercontent.com/iamspruce/intro-d3/main/nigeria-states.json"</span>).then(<span class="hljs-function">(<span class="hljs-params">{ data }</span>) =&gt;</span> {
    data.forEach(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> (d.Population = +d.info.Population))
})
</code></pre>
<p>If this doesn't look familiar please re-read the data loading section. Because of the way our JSON data is structured I destructed <code>{ data }</code> from the API.</p>
<p>The fetched data comes in as a string but we need the Population field to be a number. So using the JavaScript <code>+</code> operator we convert each Population field to a number:</p>
<pre><code class="lang-javascript">data.forEach(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> (d.Population = +d.info.Population))
</code></pre>
<p>Next we need to set the domain of our scales – and now that we have fetched our data we can do that:</p>
<pre><code class="lang-javascript">x_scale.domain(data.map(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d.Name);
y_scale.domain([<span class="hljs-number">0</span>, d3.max(data, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d.Population)]);
</code></pre>
<p>Let's see what's going on here:</p>
<ul>
<li><p><code>x_scale.domain(</code><a target="_blank" href="http://data.map"><code>data.map</code></a><code>((d) =&gt;</code> <a target="_blank" href="http://d.Name"><code>d.Name</code></a><code>)</code> - The x scale is a band scale so we set the domain to the name of states (36 states)</p>
</li>
<li><p><code>y_scale.domain([0, d3.max(data, (d) =&gt; d.Population)])</code> - The y scale is a linear scale so we set the minimum value to 0. And rather than setting the maximum value ourselves, we let D3 do that for us by using the <code>d3.max()</code> method.</p>
</li>
</ul>
<p>NOTE: with the <code>d3.max()</code> method we loop through the provided data and always return the maximum value of the specified field (Population in our case).</p>
<p>Lastly we need to add the rectangles so we can see our bar chart:</p>
<pre><code class="lang-javascript">svg
 .selectAll(<span class="hljs-string">"rect"</span>)
 .data(data)
 .join(<span class="hljs-string">"rect"</span>)
  .attr(<span class="hljs-string">"class"</span>, <span class="hljs-string">"bar"</span>)
  .attr(<span class="hljs-string">"x"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> x_scale(d.Name))
  .attr(<span class="hljs-string">"y"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> y_scale(d.Population))
  .attr(<span class="hljs-string">"width"</span>, x_scale.bandwidth())
  .attr(<span class="hljs-string">"height"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> height - y_scale(d.Population));
</code></pre>
<p>Okay this isn't something new right? If this is still new please re-read the data join section of this tutorial. But there are some things we are seeing for the first time:</p>
<ul>
<li><p><code>.attr("x", (d) =&gt; x_scale(</code><a target="_blank" href="http://d.Name"><code>d.Name</code></a><code>))</code> - We set the x (horizontal) position of each <code>rect</code> created according to the generated scale. Same for the y (vertical position <code>.attr("y", (d) =&gt; y_scale(d.Population))</code>.</p>
</li>
<li><p><code>.attr("width", x_scale.bandwidth())</code> - here we set the width of each <code>rect</code>. Of course we can set this to any number we like, but using <code>x_scale.bandwidth()</code> D3 automatically sizes the <code>rect</code> for us to match the width of our SVG.</p>
</li>
<li><p><code>.attr("height", (d) =&gt; height - y_scale(d.Population))</code> - lastly we set the height of each <code>rect</code> to the SVG height and then subtract the height generated by the <code>y_scale(d.Population)</code>, making sure each <code>rect</code> is represented correctly.</p>
</li>
</ul>
<p>Here is the full code put together in one place:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> width = <span class="hljs-number">960</span>, height = <span class="hljs-number">500</span>;

<span class="hljs-keyword">const</span> x_scale = d3.scaleBand().range([<span class="hljs-number">0</span>, width]).padding(<span class="hljs-number">0.1</span>);
<span class="hljs-keyword">const</span> y_scale = d3.scaleLinear().range([height, <span class="hljs-number">0</span>]);

<span class="hljs-keyword">const</span> svg = d3.select(<span class="hljs-string">"#d3_demo"</span>)
    .attr(<span class="hljs-string">"width"</span>, width)
    .attr(<span class="hljs-string">"height"</span>, height);

d3.json(<span class="hljs-string">"https://raw.githubusercontent.com/iamspruce/intro-d3/main/nigeria-states.json"</span>)
    .then(<span class="hljs-function">(<span class="hljs-params">{ data }</span>) =&gt;</span> {

     data.forEach(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> (d.Population = +d.info.Population));

     <span class="hljs-comment">// Scale the Domain</span>
     x_scale.domain(data.map(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d.Name));
     y_scale.domain([<span class="hljs-number">0</span>, d3.max(data, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d.Population)]);

     <span class="hljs-comment">// add the rectangles for the bar chart</span>
     svg
      .selectAll(<span class="hljs-string">"rect"</span>)
      .data(data)
      .join(<span class="hljs-string">"rect"</span>)
      .attr(<span class="hljs-string">"class"</span>, <span class="hljs-string">"bar"</span>)
      .attr(<span class="hljs-string">"x"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> x_scale(d.Name))
      .attr(<span class="hljs-string">"y"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> y_scale(d.Population))
      .attr(<span class="hljs-string">"width"</span>, x_scale.bandwidth())
      .attr(<span class="hljs-string">"height"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> height - y_scale(d.Population));
    });
</code></pre>
<p>And here's the output:</p>
<pre><code class="lang-javascript">%[https:<span class="hljs-comment">//codepen.io/Spruce_khalifa/pen/porxVVd]</span>
</code></pre>
<p>And there you have it, a very basic D3.js bar chart. But if you showed that bar chart to a colleague or friend, they would probably ask you "what's going on here, what are we looking at?" That would lead us to another topic – the <strong>Axis</strong>.</p>
<h3 id="heading-axis-component-in-d3">Axis Component in D3</h3>
<blockquote>
<p>The axis component renders human-readable reference marks for scales. – D3 docs</p>
</blockquote>
<p>To create these human readable reference marks, the <code>d3.axis</code> makes uses the <code>d3.scale</code> function to determine the number of ticks to generate.</p>
<p>To create different orientations for our axis, D3 provides four methods:</p>
<ul>
<li><p>d3.axisTop</p>
</li>
<li><p>d3.axisBottom</p>
</li>
<li><p>d3.axisLeft</p>
</li>
<li><p>d3.axisRight</p>
</li>
</ul>
<p>Let's see an example of these:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> svg = d3.select(<span class="hljs-string">"#d3_demo8"</span>).attr(<span class="hljs-string">'width'</span>, <span class="hljs-number">200</span>).attr(<span class="hljs-string">'height'</span>, <span class="hljs-number">200</span>)
<span class="hljs-keyword">let</span> scale = d3.scaleLinear().domain([<span class="hljs-number">0</span>, <span class="hljs-number">100</span>]).range([<span class="hljs-number">0</span>, <span class="hljs-number">200</span>]);


<span class="hljs-keyword">let</span> bottom_axis = d3.axisBottom(scale);

svg.append(<span class="hljs-string">"g"</span>).call(bottom_axis);
</code></pre>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_demo"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example d3_no_pad"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_svg_demo2"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d3_example-text"</span>&gt;</span>Example output<span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_demo8"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>To make all this work, you only need to pass in your existing <code>d3.scale</code> function. Let's apply this to our previous example.</p>
<p>The first thing we need to do is to set up the D3 margin convention.</p>
<h3 id="heading-d3-margin-convention">D3 Margin Convention</h3>
<p>The margin convention is just a way of adding margins to our graphics so as to have space to add our Axis.</p>
<p>To create the margin, first create an object with a property for each of the four sides:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> margin = { <span class="hljs-attr">top</span>: <span class="hljs-number">20</span>, <span class="hljs-attr">right</span>: <span class="hljs-number">30</span>, <span class="hljs-attr">bottom</span>: <span class="hljs-number">55</span>, <span class="hljs-attr">left</span>: <span class="hljs-number">70</span> }
</code></pre>
<p>Then you need to define the width and height for our SVG. For a responsive graphic we set the width to the document body:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> width = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"body"</span>).clientWidth;
<span class="hljs-keyword">const</span> height = <span class="hljs-number">500</span>;
</code></pre>
<p>Next we need to apply this width as a view box to our SVG element:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> svg = d3.select(<span class="hljs-string">"#d3_demo"</span>).attr(<span class="hljs-string">"viewBox"</span>, [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, width, height])
</code></pre>
<p>Next we need to set the <code>x_scale</code> and <code>y_scale</code> to work with our new margins:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> x_scale = d3
    .scaleBand()
    .range([margin.left, width - margin.right])
    .padding(<span class="hljs-number">0.1</span>);

<span class="hljs-keyword">const</span> y_scale = d3.scaleLinear()
    .range([height - margin.bottom, margin.top]);
</code></pre>
<p>Next let's define our left and bottom axis – remember we only need to pass in our existing scale (the ones above):</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> x_axis = d3.axisBottom(x_scale);

<span class="hljs-keyword">let</span> y_axis = d3.axisLeft(y_scale);
</code></pre>
<p>Everything else is the same as our previous example except the last part where we add the Axis:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// append x axis</span>
svg
 .append(<span class="hljs-string">"g"</span>)
  .attr(<span class="hljs-string">"transform"</span>, <span class="hljs-string">`translate(0,<span class="hljs-subst">${height - margin.bottom}</span>)`</span>)
  .call(x_axis)
  .selectAll(<span class="hljs-string">"text"</span>) <span class="hljs-comment">// everything from this point is optional</span>
  .style(<span class="hljs-string">"text-anchor"</span>, <span class="hljs-string">"end"</span>)
  .attr(<span class="hljs-string">"dx"</span>, <span class="hljs-string">"-.8em"</span>)
  .attr(<span class="hljs-string">"dy"</span>, <span class="hljs-string">".15em"</span>)
  .attr(<span class="hljs-string">"transform"</span>, <span class="hljs-string">"rotate(-65)"</span>);

<span class="hljs-comment">// add y axis</span>
svg
 .append(<span class="hljs-string">"g"</span>)
  .attr(<span class="hljs-string">"transform"</span>, <span class="hljs-string">`translate(<span class="hljs-subst">${margin.left}</span>,0)`</span>)
  .call(y_axis);
</code></pre>
<p>You can view the <a target="_blank" href="https://codepen.io/Spruce_khalifa/pen/RwZvOPx">output and full code on Codepen</a>.</p>
<h3 id="heading-how-to-style-it-with-css-in-d3">How to Style it With CSS in D3</h3>
<p>You'll notice that our bar chart is green in color – how come? Well, we added a class of <code>bar</code> to each bar in the chart:</p>
<pre><code class="lang-javascript">.attr(<span class="hljs-string">"class"</span>, <span class="hljs-string">"bar"</span>)
</code></pre>
<p>We can use that class to style our bar chart with CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.bar</span> {
  <span class="hljs-attribute">fill</span>: green;
}
</code></pre>
<h2 id="heading-how-to-create-a-world-map-with-d3js">How to Create a World Map With D3.js</h2>
<p>One of the things I personally love about D3 is its ability to handle geographic data. Unlike our former examples, which used JSON data format maps, now we'll use a special form of JSON data called <a target="_blank" href="http://geojson.org/">GeoJSON</a>.</p>
<p>You can find the GeoJSON data we are going to use <a target="_blank" href="https://raw.githubusercontent.com/iamspruce/intro-d3/main/data/countries-110m.geojson">here</a>.</p>
<p>Like in our other examples, let's first select our SVG element in the document and also set up <strong>the margin convention:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> margin = { <span class="hljs-attr">top</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">right</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">bottom</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">left</span>: <span class="hljs-number">5</span> },
    width = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"body"</span>).clientWidth,
    height = <span class="hljs-number">500</span>;

<span class="hljs-keyword">const</span> svg = d3.select(<span class="hljs-string">"#d3_demo"</span>).attr(<span class="hljs-string">"viewBox"</span>, [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, width, height]);
</code></pre>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_demo"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>Next, to generate our map we'll need a projection to render spherical coordinates (in our data file) and a Path Generator to convert the projected coordinates to a SVG path which is then rendered on the screen:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> projection = d3.geoEquirectangular().center([<span class="hljs-number">0</span>, <span class="hljs-number">0</span>]);
</code></pre>
<p>D3 provides a lot of <a target="_blank" href="https://github.com/d3/d3-geo-projection">projections</a> (I only used this one because I like it). Now that we have chosen our projection, let's convert it to an SVG path. D3 handles the conversion for us when we use the <code>d3.geoPath()</code> method. This method takes in a projection (the one we defined above):</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> pathGenerator = d3.geoPath().projection(projection);
</code></pre>
<p>We don't want to draw the map directly on the SVG because we are going to be adding animations and zooming later on. So we append a <code>g</code> element to the selected SVG:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> g = svg.append(<span class="hljs-string">"g"</span>);
</code></pre>
<p>Then we'll load our data for the map:</p>
<pre><code class="lang-javascript">d3.json(<span class="hljs-string">"https://raw.githubusercontent.com/iamspruce/intro-d3/main/data/countries-110m.geojson"</span>)
  .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(data)
  });
</code></pre>
<p>If this doesn't make sense I suggest you re-read the data loading section.</p>
<p>Lastly let's use our <code>pathGenerator</code> to generate our paths:</p>
<pre><code class="lang-javascript"> g.selectAll(<span class="hljs-string">"path"</span>)
    .data(data.features)
    .join(<span class="hljs-string">"path"</span>)
    .attr(<span class="hljs-string">"d"</span>, pathGenerator);
</code></pre>
<p>Above we used D3 data join to append a path for each country and then set the <code>d</code> attribute to our <code>pathGenerator</code>:</p>
<pre><code class="lang-javascript">.attr(<span class="hljs-string">"d"</span>, pathGenerator);
</code></pre>
<p>And in case that isn't clear, it's the equivalent of writing this:</p>
<pre><code class="lang-javascript">.attr(<span class="hljs-string">'d'</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> pathGenerator(d))
</code></pre>
<p>You can find the <a target="_blank" href="https://codepen.io/Spruce_khalifa/pen/dyzLyxp">final code and live preview on Codepen</a>.</p>
<h3 id="heading-how-to-use-multiple-datasets-in-d3js">How to Use Multiple Datasets in D3.js</h3>
<p>Sometimes you'll want to visualize two datasets from different sources. For example I have a data <a target="_blank" href="https://github.com/iamspruce/intro-d3/blob/main/data/nigeria_state_boundaries.geojson">file</a> that contains the geographic data of Nigeria and another <a target="_blank" href="https://github.com/iamspruce/intro-d3/blob/main/data/nigeria-states.json">file</a> that contains information about states in Nigeria.</p>
<p>In the data loading section of this tutorial, we only covered loading a single data set. Loading multiple datasets in D3 looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">Promise</span>.all([
    d3.json(<span class="hljs-string">"https://raw.githubusercontent.com/iamspruce/intro-d3/main/data/nigeria_state_boundaries.geojson"</span>),
    d3.json(<span class="hljs-string">"https://raw.githubusercontent.com/iamspruce/intro-d3/main/data/nigeria-states.json"</span>)
]).then(<span class="hljs-function">(<span class="hljs-params">[geoJSONdata, countryData]</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(geoJSONdata)
    <span class="hljs-built_in">console</span>.log(countryData)
});
</code></pre>
<p>By adding all the D3 data loading methods <code>d3.json()</code> inside the <code>Promise.all</code>, the <code>.then()</code> callback will only get called when all the data have finished loading, although if one of the data file fails to load the callback will not be called and would result in an error.</p>
<h3 id="heading-map-with-city-names">Map with City Names</h3>
<p>Now let's use the <strong>loading multiple datasets</strong> idea to create a map with city names.</p>
<p>For simplicity we are going to leave out the part of creating the map because we already covered that above. Now, we'll only focus on adding the cities names:</p>
<p>Once we have loaded the data we need to format it:</p>
<pre><code class="lang-javascript">countryData.data.forEach(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> {
 d.info.Longitude = +d.info.Longitude;
 d.info.Latitude = +d.info.Latitude;
});
</code></pre>
<p>Above we converted the longitudes and latitudes. Next we need to fit our map to our container. To do that you'll use the <code>d3.fitSize()</code> method:</p>
<pre><code class="lang-javascript">projection.fitSize([width, height], geoJSONdata);
</code></pre>
<p>Lastly we need to add the city names:</p>
<pre><code class="lang-javascript">g.selectAll(<span class="hljs-string">"text"</span>)
 .data(countryData.data)
 .join(<span class="hljs-string">"text"</span>)
  .attr(<span class="hljs-string">"x"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> projection([d.info.Longitude, d.info.Latitude])[<span class="hljs-number">0</span>])
  .attr(<span class="hljs-string">"y"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> projection([d.info.Longitude, d.info.Latitude])[<span class="hljs-number">1</span>])
  .attr(<span class="hljs-string">"dy"</span>, <span class="hljs-number">-7</span>)
  .style(<span class="hljs-string">"fill"</span>, <span class="hljs-string">"black"</span>)
  .attr(<span class="hljs-string">"text-anchor"</span>, <span class="hljs-string">"middle"</span>)
  .text(<span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> d.Name);
</code></pre>
<p>And that's it! We have a map with name of cities (I might have added circles too, because I think it's cool). The <a target="_blank" href="https://codepen.io/Spruce_khalifa/pen/BadEywO">full code is on Codepen</a>.</p>
<h2 id="heading-event-handling-with-d3js">Event Handling with D3.js</h2>
<p>At the beginning of this tutorial we talked about selections, but one thing we didn't cover was event handling.</p>
<p>In D3 we can add or remove event handlers to or from selected document elements using the <code>.on()</code> method.</p>
<p>The <code>.on()</code> method accepts two arguments:</p>
<ol>
<li><p>Event type (usually a string)</p>
</li>
<li><p>A callback function that is called when our event is fired</p>
</li>
</ol>
<h3 id="heading-event-types-in-d3">Event Types in D3</h3>
<p>The D3 <code>.on()</code> event type can be any <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Events#Standard_events">DOM event type</a>, but the most common events with D3 are:</p>
<pre><code class="lang-javascript">| Event Type  | Description  |
|---|---|
| zoom  | selection is being panned and zoomed  |
| click  | selection got clicked  |
| mouseover  | mouse pointer moves over a selection  |
| mouseout  | mouse pointer leaves a slection  |
</code></pre>
<h3 id="heading-map-with-panning-and-zooming">Map with Panning and Zooming</h3>
<p>To see how D3 event handling works let's add pan and zoom to our previously created map.</p>
<p>The first thing we need to do is to define the zoom function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> zooming = d3
  .zoom()
  .scaleExtent([<span class="hljs-number">1</span>, <span class="hljs-number">8</span>])
  .on(<span class="hljs-string">"zoom"</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
   <span class="hljs-built_in">console</span>.log(event)
  })
</code></pre>
<p>Then the next thing we need to do is use the <code>d3.zoom()</code> method. We also set the <code>scaleExtent([1,8])</code>. We do this to set the limit of the zoom, otherwise you'll keep zooming to infinity. Now let's add the transformation to our map paths in the callback function:</p>
<pre><code class="lang-javascript">.on(<span class="hljs-string">"zoom"</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-comment">// transform paths when zoomed</span>
  g.selectAll(<span class="hljs-string">"path"</span>).attr(<span class="hljs-string">"transform"</span>, event.transform);

  <span class="hljs-comment">// transform circles when zoomed</span>
  g.selectAll(<span class="hljs-string">"circle"</span>)
    .attr(<span class="hljs-string">"transform"</span>, event.transform)
    .attr(<span class="hljs-string">"r"</span>, <span class="hljs-number">5</span> / event.transform.k);

  <span class="hljs-comment">// transform text when zoomed</span>
  g.selectAll(<span class="hljs-string">"text"</span>)
    .attr(<span class="hljs-string">"transform"</span>, event.transform)
    .style(<span class="hljs-string">"font-size"</span>, <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-number">18</span> / event.transform.k}</span>`</span>)
    .attr(<span class="hljs-string">"dy"</span>, <span class="hljs-number">-7</span> / event.transform.k);
});
</code></pre>
<p>NOTE: The <code>event.transform</code> is a short hand for setting the <code>translate('x','y')</code> and <code>scale</code> (event.transform.k).</p>
<p>Lastly let's call the zooming function on our SVG selection:</p>
<pre><code class="lang-javascript">svg.call(zooming)
</code></pre>
<p>You can find the <a target="_blank" href="https://codepen.io/Spruce_khalifa/pen/MWvROBq">full code and preview on Codepen</a>.</p>
<h3 id="heading-programmatic-zooming-in-d3">Programmatic zooming in D3</h3>
<p>Turns out in D3 we can control zooming programmatically, this let us create buttons that can be used to control the zoom behavior:</p>
<p>Let's add those buttons to our previous map:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn-group-vertical"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"group"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"..."</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"float-button-group"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn-default"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"zoomIn"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"svg-icon"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 20 20"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Zoom In<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    ...svg icon
    <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn-default"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"zoomOut"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"svg-icon"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 20 20"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Zoom Out<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  ...svg icon
    <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn-default"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"resetZoom"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"svg-icon"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 20 20"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Reset Zoom<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    ...svg icon
    <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d3_demo"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>The next step is to select those buttons and control the zoom behavior:</p>
<pre><code class="lang-javascript">d3.select(<span class="hljs-string">"#zoomIn"</span>).on(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
  svg.transition().call(zooming.scaleBy, <span class="hljs-number">2</span>);
});
d3.select(<span class="hljs-string">"#zoomOut"</span>).on(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
  svg.transition().call(zooming.scaleBy, <span class="hljs-number">0.5</span>);
});
d3.select(<span class="hljs-string">"#resetZoom"</span>).on(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
  svg.transition().call(zooming.scaleTo, <span class="hljs-number">1</span>);
});
</code></pre>
<p>What is <code>scaleBy</code> and <code>scaleTo</code>? <code>scaleBy</code> multiplies the current scale by our given value (2), while <code>scaleTo</code> sets the scale factor to our given value (1) which resets the zoom.</p>
<p>You can find the <a target="_blank" href="https://codepen.io/Spruce_khalifa/pen/eYEoyYo">preview and full code on Codepen</a>.</p>
<h3 id="heading-how-to-add-tooltips-in-d3">How to Add ToolTips in D3</h3>
<p>Let's add ToolTips to our map. A tooltip shows more information about an item when the user hovers over that item.</p>
<p>Let's first create the tooltip:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> tooltip = d3
  .select(<span class="hljs-string">"body"</span>)
  .append(<span class="hljs-string">"div"</span>)
  .attr(<span class="hljs-string">"class"</span>, <span class="hljs-string">"tooltip"</span>)
  .style(<span class="hljs-string">"opacity"</span>, <span class="hljs-number">0</span>);
</code></pre>
<p>Next let's add the tooltip when the circle is hovered over, and remove it when the mouse pointer leaves the circle:</p>
<pre><code class="lang-javascript">g.selectAll(<span class="hljs-string">"circle"</span>)
  ...
  .style(<span class="hljs-string">"fill"</span>, <span class="hljs-string">"green"</span>)
  .on(<span class="hljs-string">"mouseover"</span>, <span class="hljs-function">(<span class="hljs-params">event, d</span>) =&gt;</span> {
    tooltip.transition().duration(<span class="hljs-number">200</span>).style(<span class="hljs-string">"opacity"</span>, <span class="hljs-number">0.9</span>);
    tooltip.html(<span class="hljs-string">`&lt;p&gt;Population: <span class="hljs-subst">${d.info.Population}</span>&lt;/a&gt;`</span> + <span class="hljs-string">`&lt;p&gt;Name: <span class="hljs-subst">${d.Name}</span>&lt;/p&gt;`</span>)
    .style(<span class="hljs-string">"left"</span>, event.pageX + <span class="hljs-string">"px"</span>)
    .style(<span class="hljs-string">"top"</span>, event.pageY - <span class="hljs-number">28</span> + <span class="hljs-string">"px"</span>);
  })
  .on(<span class="hljs-string">"mouseout"</span>, <span class="hljs-function">(<span class="hljs-params">d</span>) =&gt;</span> {
    tooltip.transition().duration(<span class="hljs-number">500</span>).style(<span class="hljs-string">"opacity"</span>, <span class="hljs-number">0</span>);
  });
</code></pre>
<p>Here's the <a target="_blank" href="https://codepen.io/Spruce_khalifa/pen/mdMYEBJ">final code and preview</a> (try hovering on the circles):</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations D3 Ninja! You've made it this far. Hopefully you have learnt the basics of Data Visualization with D3.</p>
<p>Here are some next steps:</p>
<ul>
<li><p>Check out the <a target="_blank" href="https://www.freecodecamp.org/learn/data-visualization/">freeCodeCamp Data Visualization</a> certification</p>
</li>
<li><p>Check out the docs and more on <a target="_blank" href="https://d3js.org/">D3's officail website</a></p>
</li>
</ul>
<p>If you created something wonderful with this, please feel free to tweet about it and tag me <a target="_blank" href="https://twitter.com/sprucekhalifa">@sprucekhalifa</a>. And don't forget to hit the follow button.</p>
<p>Oh and happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Data Visualization in This Free 17-Hour Course ]]>
                </title>
                <description>
                    <![CDATA[ Business is becoming increasingly data driven and this data needs to be visualized to make it easier to understand. Data Visualization is a growing field with many opportunities. We've released a comprehensive 17-hour course on data visualization tha... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-data-visualization-in-this-free-17-hour-course/</link>
                <guid isPermaLink="false">66b2042ea2135cc2539a21af</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 23 Feb 2021 14:31:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/02/dataviz1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Business is becoming increasingly data driven and this data needs to be visualized to make it easier to understand. Data Visualization is a growing field with many opportunities.</p>
<p>We've released a comprehensive 17-hour course on data visualization that is perfect for anyone new to the field. The course focusses on visualizing data using D3.js, JavaScript, and React.</p>
<p>Curran Kelleher developed this course. Curran previously created one of the most popular data visualization courses on the internet and now he has completely redone and improved the course. This course comes out of his extensive experience developing data visualizations and teaching new developers.</p>
<p>You will learn how to conceptualize, design, and build interactive data visualizations with Web technologies.</p>
<p>Here is the list of topics covered in this thorough course:</p>
<ul>
<li>What is Data Visualization</li>
<li>Finding Visualizations</li>
<li>Introduction to Web Technologies</li>
<li>Let's Make a Face Part I (HTML, CSS, SVG)</li>
<li>Let's Make a Face Part II (React)</li>
<li>Let's Make a Face Part III (React &amp; D3)</li>
<li>Let's Make a Face Part IV (React Components &amp; ES6)</li>
<li>Let's Make a Face Part V multiple files with ES6 modules</li>
<li>Let's Make a Face Part VI (Compartmentalizing Complexity)</li>
<li>Preparing Data for Visualization</li>
<li>Loading Data with Fetch, Promises, Aync &amp; Await</li>
<li>Interaction With React</li>
<li>Parsing CSV Data with D3</li>
<li>Loading Data in React</li>
<li>Inputs for Visualization: Data &amp; Tasks</li>
<li>Iterating Fast with Vega Lite API</li>
<li>Marks &amp; Channels</li>
<li>Visualizing Data with React &amp; D3</li>
<li>Making a Bar Chart with React &amp; D3</li>
<li>Margins and Axes</li>
<li>Refactoring a Bar Chart</li>
<li>Stylized Bar Chart</li>
<li>Making a Scatter Plot</li>
<li>Working with Time</li>
<li>Making a Line Chart</li>
<li>Preparing Geospatial Data</li>
<li>Making a World Map with React &amp; D3</li>
<li>Menus with React</li>
<li>Scatter Plot with Menus</li>
<li>Polished Scatter Plot with Menus</li>
<li>Scatter Plot with Color</li>
<li>Making a Color Legend</li>
<li>Interactive Color Legend</li>
<li>Points on a Map</li>
<li>Using Size</li>
<li>Missing Migrants</li>
<li>Missing Migrants Part II: Aggregation by Month</li>
<li>Missing Migrants Part III: On a Map</li>
<li>Multiple Views</li>
<li>Why Use Modules</li>
<li>Multiple Views Cleanup</li>
<li>Multiple Views with Brushing</li>
<li>React Performance Optimization</li>
<li>Choropleth Map</li>
<li>Log Scales</li>
<li>Making a Choropleth Map</li>
<li>Basic Line Chart Project</li>
<li>Line Chart with Marker Lines</li>
<li>React &amp; D3 Axes with useRef and D3 axis</li>
<li>Line Chart with Log Scale and Labels</li>
<li>Line Chart with Multiple Colored Lines</li>
<li>Line Chart with Voronoi Overlay</li>
<li>Line Chart with Voronoi Tooltips</li>
<li>Organization Graph Diagram</li>
</ul>
<p><strong>Watch the full course on the <a target="_blank" href="https://www.youtube.com/watch?v=2LhoCfjm8R4">freeCodeCamp.org YouTube channel</a> (17-hour watch).</strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Basic Data Visualization with D3.js ]]>
                </title>
                <description>
                    <![CDATA[ Our goal is to learn the basics of data You'll learn the basics of data visualization using D3 through this project. What is D3.js? For those who are not familiar with D3, D3.js is a JavaScript library for manipulating documents based on data. D3 he... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-basic-data-visualization-with-d3-js/</link>
                <guid isPermaLink="false">66c3599cd372f14b49bdcbde</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ toothbrush ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 07 Feb 2020 01:37:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9cb8740569d1a4ca33cc.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-our-goal-is-to-learn-the-basics-of-data"><strong>Our goal is to learn the basics of data</strong></h2>
<p>You'll learn the basics of data visualization using D3 through this project.</p>
<p><img src="https://discourse-user-assets.s3.amazonaws.com/original/2X/2/2d46c5c1c76bd03b9e85d450da02695d3f07c75c.png" alt="screen shot 2016-05-17 at 5 02 41 pm" width="897" height="445" loading="lazy"></p>
<h2 id="heading-what-is-d3js"><strong>What is D3.js?</strong></h2>
<p>For those who are not familiar with D3, D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG and CSS.</p>
<p>D3.js helps you attach your data to DOM (Document Object Model) elements. Then you can use CSS3, HTML, and/or SVG showcase this data. Finally, you can make the data interactive through the use of D3.js data-driven transformations and transitions.</p>
<h2 id="heading-project-explanation"><strong>Project Explanation:</strong></h2>
<h3 id="heading-scenario"><strong>Scenario:</strong></h3>
<p>There”s a class of Online students interacting with different topics of the subject and gives quiz on those topics.</p>
<p>There are 15 topics and on each topic, we have a numbers of student who have taken quiz and have scored in three categories: Low, Mid and High</p>
<h3 id="heading-for-example-given-data"><strong>For example (Given data ):</strong></h3>
<p>Topic: “1”, low: 4, mid:13, high: 18</p>
<p>Topic: “2”, low: 11, mid:12, high: 6</p>
<p>Topic: “3”, low: 12, mid:24, high: 6 and so on.</p>
<p>Note that Topic 1 has<code>4 + 13 + 8 = 35</code> student has taken the quiz and Topic 2 has <code>11+12+6 = 29</code> student and topic 3 has 42 students and so on.</p>
<p>We want to make interactive Bar and Pie charts. For example, a mouse hover on one of the bars will change the pie chart accordingly and vice-versa.</p>
<p>With Interactive combination of bar chart and pie chart, where bar chart shows number of students who have interacted with particular topic(taken the quiz) and pie chart showing classification of that students performance in categories of “low, mid, high”, we can visualize our data and get more data analysis from it.</p>
<h2 id="heading-hints-and-resources"><strong>Hints and Resources:</strong></h2>
<h3 id="heading-step-by-step-instructions"><strong>Step by Step instructions:</strong></h3>
<p><a target="_blank" href="https://d3js.org/"><strong>D3 Introduction:</strong></a> where you can learn about Selections , Dynamic properties and Transitions in D3.js.</p>
<p>In the main javascript function, write a function to handle Histogram (Bar chart) - Histogram will show the total number of students who has taken the quiz (interacted with that topic) for 15 topics.</p>
<ul>
<li>(Here”s the <a target="_blank" href="https://bost.ocks.org/mike/bar/"><strong>Tutorial</strong></a> where you can learn how to make a bar chart using the D3 JavaScript library. The first tutorial teaches how to make a bare-bones version in HTML, then a more complete chart in Scalable Vector Graphics (SVG), and lastly animated transitions between views.)</li>
<li><a target="_blank" href="http://codepen.io/SundeepB/pen/CxveH">Create SVG for histogram</a></li>
<li>Create function for x-axis mapping and add x-axis to histogram SVG</li>
<li>Create function for y-axis mapping and Create bars for histogram to contain rectangles and topic labels.</li>
<li>Create the rectangles and topic labels</li>
<li>Create function to update the bars. This will be used by pie-chart</li>
</ul>
<p>Write a function to handle pieChart. – pie chart will have three slices – Low , Mid and High to represent scores.</p>
<ul>
<li><a target="_blank" href="http://zeroviscosity.com/d3-js-step-by-step/step-1-a-basic-pie-chart"><strong>Tutorial</strong></a> where you can learn how to make a pie chart, then transitions between views and how to create a legend.</li>
<li>Create svg for pie chart.</li>
<li>Create function to draw the arcs of the pie slices - pie slices will be Low , Mid and high</li>
<li>Create a function to compute the pie slice angles.</li>
<li>Draw the pie slices.</li>
<li>Create function to update pie-chart. This will be used by histogram.</li>
<li>Calculate total frequency by segment for all topic.</li>
<li>Calculate total frequency by state for all segment.</li>
</ul>
<h2 id="heading-result-of-data-analysis-and-what-can-we-infer-from-visualization"><strong>Result of Data Analysis and what can we infer from Visualization:</strong></h2>
<ul>
<li>Initial pie chart shows aggregate classification of all student score on all topic combined into three categories “low, mid ,high”</li>
<li>Initial bar chart showing number of students who have interacted on that particular topic</li>
<li>Any Selected category from pie chart will update bar chart, showing number of students who have interacted on various topics having score belonging to that particular category .</li>
<li>Screenshots below shows the mouse hover on “Mid” slice and “High” slice of the pie chart respectively and for that particular slice , topic-wise bar charts and number of students.</li>
</ul>
<p><img src="https://discourse-user-assets.s3.amazonaws.com/original/2X/1/106f06d412df6db5b4a421dc4769d22695cbec72.png" alt="screen shot 2016-05-17 at 5 13 53 pm" width="837" height="446" loading="lazy"></p>
<p><img src="https://discourse-user-assets.s3.amazonaws.com/original/2X/7/7b23ebe89f74f11090984dbc4dc68212e3beceb3.png" alt="screen shot 2016-05-17 at 5 14 05 pm" width="881" height="424" loading="lazy"></p>
<ul>
<li>Any selected bar chart”s bar will update pie chart showing classification of all students score on that particular topic into three categories Low , Mid and High. Screenshot below shows the mouse hover on Topic 2 and for that particular topic , how many student are in categories Low , Mid and High</li>
</ul>
<p><img src="https://discourse-user-assets.s3.amazonaws.com/original/2X/7/7bd7c613bdb882f2b7c1f76f9778a1bda3e886dd.png" alt="screen shot 2016-05-17 at 5 13 26 pm" width="867" height="444" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn data visualization using D3.js with a free 13-hour course ]]>
                </title>
                <description>
                    <![CDATA[ In this data visualization course for beginners from Curran Kelleher, you’ll learn how to transform data into meaningful graphical forms. You'll learn how to create visualizations using D3.js and web technologies. D3 is a JavaScript library for visua... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/data-visualization-using-d3-course/</link>
                <guid isPermaLink="false">66b201fa27569435a9255aa2</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Mon, 01 Jul 2019 13:10:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/dataviz.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this data visualization course for beginners from Curran Kelleher, you’ll learn how to transform data into meaningful graphical forms. You'll learn how to create visualizations using D3.js and web technologies. D3 is a JavaScript library for visualizing data with HTML, SVG, and CSS.</p>
<p>Besides teaching all about D3, the course also covers the basics of JavaScript, HTML, CSS, and SVG so you will have all the prerequisite knowledge to create stunning data visualizations.</p>
<p>This comprehensive course covers the following topics:</p>
<ul>
<li>Why Visualize Data?</li>
<li>Inputs for Data Visualization: Data &amp; Tasks</li>
<li>Intro to Javascript</li>
<li>Intro to HTML, CSS &amp; SVG</li>
<li>Intro to D3.js - Let's Make a Face!</li>
<li>Making a Bar Chart with D3.js and SVG</li>
<li>Customizing Axes of a Bar Chart with D3.js</li>
<li>Making a Scatter Plot with D3.js</li>
<li>Making Line and Area Charts with D3.js</li>
<li>The General Update Pattern of D3.js</li>
<li>Marks &amp; Channels in Data Visualization</li>
<li>Interaction with Unidirectional Data Flow using D3.js</li>
<li>Making a World Map with D3</li>
<li>Cheap Tricks for Interaction on a D3.js World Map</li>
<li>Blank Canvas</li>
<li>Building a Tree Visualization of World Countries with D3.js</li>
<li>Color and Size Legends with D3.js</li>
<li>Choropleth Map with D3.js</li>
<li>Interactive Filtering on a Choropleth Map</li>
<li>Using Color in Visualization</li>
<li>Scatter Plot with Menus</li>
<li>Circles on a Map</li>
<li>Line Chart with Multiple Lines</li>
<li>Melting and Munging Data with JavaScript</li>
<li>Selecting a Year on a Line Chart</li>
</ul>
<p>You can watch the full video course on the <a target="_blank" href="https://www.youtube.com/watch?v=_8V5o2UHG0E">freeCodeCamp.org YouTube channel</a> (13 hour watch).</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Visual Reference For D3 ]]>
                </title>
                <description>
                    <![CDATA[ By Zaid Humayun I’ve been using D3 quite a bit recently to build an analytics dashboard. The main reason I went with D3 was because I got tired of dealing with the limitations of the various charting libraries and trying to understand their documenta... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-visual-reference-for-d3/</link>
                <guid isPermaLink="false">66d461c53dce891ac3a9684c</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 27 Jun 2019 12:54:08 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/D3-article-image.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Zaid Humayun</p>
<p>I’ve been using D3 quite a bit recently to build an analytics dashboard. The main reason I went with D3 was because I got tired of dealing with the limitations of the various charting libraries and trying to understand their documentation.</p>
<p>I found myself in a situation where I was spending more time trying to figure out whether the library I was using could do what I wanted rather than actually trying to figure out how to do what I wanted.</p>
<p>With D3, there is almost never a case of whether you can do something. It’s always about how you can do something.</p>
<p>Granted, getting to grips with D3’s API is a mammoth challenge but it’s worth the hassle.</p>
<p>In this article, I’m going to try to give you a visual representation of my understanding of D3 after working with it for a while now.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*7Q2OWU3mpakpTMcr.jpg" alt="Image" width="1600" height="1213" loading="lazy">
<em>Main Ideas Behind D3</em></p>
<h3 id="heading-the-ups-and-downs-of-d3">The Ups And Downs Of D3</h3>
<p>The thing I love about D3 is that its built on top of the smallest primitives, and you have access to all of those primitives.</p>
<p>If you were to use a typical charting library for React, you’d probably do something like this</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { BarChart } <span class="hljs-keyword">from</span> <span class="hljs-string">'generic-charting-library'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Chart</span>() </span>{
  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BarChart</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{data}</span> /
    )
  }
}</span></span>
</code></pre>
<p>The above is perfectly fine for most use cases. However, the moment you want to do anything slightly more complicated like interacting with the bar chart in unique ways (think beyond just displaying a tool tip), my personal experience has been that it turns into a war with the documentation of the library.</p>
<p>First, you have to figure out if it is even possible to do this with the library, and then you have to figure out how to do it.</p>
<p>The first part, in my experience, is the hard bit. It is quite frustrating to look for something that you’re not sure exists. However, with D3, that isn’t the case. Pretty much anything you want to do can be done with D3. It is simply a matter of figuring out how to do it.</p>
<p>The downside of course is that D3’s API and documentation is so vast and expansive, that you end up having disparate pieces of knowledge of how things work. This is also a consequence of how I chose to learn D3, that is by building something with it. When you choose to build something with a technology, you only look up the pieces relevant to what you’re currently building.</p>
<p>Say, for instance, you wanted to build a bar chart. Well, you’re probably to going look up something like how to define and place axes on a web page. Then, you’ll probably look up how to define the actual bars of the chart themselves. These are well defined problems and have straightforward solutions.</p>
<p>I took pretty much the same route and ended up in a frustrating place where I could get things to work but I couldn’t quite understand how it was all coming together.</p>
<p>I’m going to explain my thought process of how I put together all the different pieces.</p>
<h3 id="heading-the-big-picture">The Big Picture</h3>
<p>The following image is that of a simplistic bar chart (something we’ll try to recreate for this post)</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*M2wwyv0H_FKdmvvv.jpg" alt="Image" width="1600" height="1200" loading="lazy">
<em>Typical Bar Chart</em></p>
<p>Now, here’s the same bar chart with the different components being marked out. By components, I mean the different things we will need to worry about when creating the bar chart using D3.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*j2P5HLdATpIsLCOM.jpg" alt="Image" width="1600" height="1200" loading="lazy">
<em>Labelled Bar Chart</em></p>
<ol>
<li>The X-axis</li>
<li>The Y-axis</li>
<li>The title</li>
<li>The bars (I’m counting all of them as one)</li>
<li>The spacing between the ticks on the X axis</li>
<li>The actual chart area itself</li>
<li>The spacing between the ticks on the Y axis</li>
</ol>
<p>We’ll explore everything except the spacing between ticks in detail. The spacing between ticks will take care of itself when figure out how to construct the axes.</p>
<h3 id="heading-the-small-things-that-make-up-the-big-picture">The Small Things That Make Up The Big Picture</h3>
<p>Before we can even start with composing the small pieces that make up the big picture, we need to understand the one element that is a part of every component in the chart above: the SVG element.</p>
<h3 id="heading-the-svg-element">The SVG Element</h3>
<p>A D3 chart is primarily composed of SVG elements. In the bar chart above, the x-axis, the y-axis, each individual bar are all instances of SVG elements.</p>
<p>I recommend reading <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/SVG">this page</a> to get a better understanding of what an SVG is. SVG’s are essentially how you describe 2D graphics on a web page.</p>
<p>The most basic example of an SVG element is the circle element.</p>
<p>See the Pen   <a target="_blank" href="https://codepen.io/redixhumayun/pen/qGMxzO/">qGMxzO</a> by Zaid Humayun (<a target="_blank" href="https://codepen.io/redixhumayun">@redixhumayun</a>)   on <a target="_blank" href="https://codepen.io">CodePen</a>.</p>
<p>Take a look at the codepen above and you should see the definition for the circle SVG inside the HTML file.</p>
<p>I’d advise going through the SVG documentation on MDN (linked above), and familiarizing yourself with it. D3 makes extensive use of SVG’s.</p>
<h4 id="heading-the-g-in-svg">The G in SVG</h4>
<p>There is a specific kind of SVG element called a G element. Similar to the way we defined the circle element above, we define this with</p>
<pre><code>&lt;svg viewBox=<span class="hljs-string">"0 0 100 100"</span> xmlns=<span class="hljs-string">"http://www.w3.org/2000/svg"</span>&gt;
  &lt;!-- Using g to inherit presentation attributes --&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">g</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"white"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"green"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"5"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">"40"</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">"40"</span> <span class="hljs-attr">r</span>=<span class="hljs-string">"25"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">"60"</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">"60"</span> <span class="hljs-attr">r</span>=<span class="hljs-string">"25"</span> /&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">g</span>&gt;</span></span>
&lt;/svg&gt;
</code></pre><p>Think of a <code>g</code> element as similar to a <code>div</code> element that is used as a container in HTML. They are both used to group certain elements.</p>
<p>Read the MDN documentation for <code>g</code> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g">here</a></p>
<p>If you want to understand why people make use of the <code>g</code> element, read <a target="_blank" href="http://tutorials.jenkov.com/svg/g-element.html">this</a></p>
<h3 id="heading-the-data-we-need">The Data We Need</h3>
<p>Before we continue any further, let’s quickly create the data we’ll be using. Here is a sample JSON file we can use to create a bar chart.</p>
<pre><code>[
  {
    <span class="hljs-string">"key"</span>: <span class="hljs-string">"A"</span>,
    <span class="hljs-string">"value"</span>: <span class="hljs-number">20</span>
  },
  {
    <span class="hljs-string">"key"</span>: <span class="hljs-string">"B"</span>,
    <span class="hljs-string">"value"</span>: <span class="hljs-number">40</span>
  },
  {
    <span class="hljs-string">"key"</span>: <span class="hljs-string">"C"</span>,
    <span class="hljs-string">"value"</span>: <span class="hljs-number">80</span>
  },
  {
    <span class="hljs-string">"key"</span>: <span class="hljs-string">"D"</span>,
    <span class="hljs-string">"value"</span>: <span class="hljs-number">55</span>
  },
  {
    <span class="hljs-string">"key"</span>: <span class="hljs-string">"E"</span>,
    <span class="hljs-string">"value"</span>: <span class="hljs-number">70</span>
  }
]
</code></pre><h3 id="heading-the-chart-area">The Chart Area</h3>
<p>Let’s start off with creating a simple chart area first. The way to create a chart area is to set up a basic SVG element and then assign a viewBox attribute to it.</p>
<p>Just ignore what the viewBox attribute is for now. It isn’t relevant to the discussion of this post.</p>
<pre><code>&lt;svg <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"chart"</span> viewBox=<span class="hljs-string">"0 0 800 600"</span>&gt;
</code></pre><p>You won’t see anything on the screen yet because the chart is transparent at this point. If you use the browser inspector, however, you will see the SVG element.</p>
<p>We’ll also define some dimensions for our chart area like the height, width and margins.</p>
<pre><code><span class="hljs-keyword">const</span> height = <span class="hljs-number">600</span>
<span class="hljs-keyword">const</span> width = <span class="hljs-number">800</span>
<span class="hljs-keyword">const</span> margin = { <span class="hljs-attr">top</span>: <span class="hljs-number">15</span>, <span class="hljs-attr">right</span>: <span class="hljs-number">30</span>, <span class="hljs-attr">bottom</span>: <span class="hljs-number">15</span>, <span class="hljs-attr">left</span>: <span class="hljs-number">30</span> }
</code></pre><p>Now that we’ve defined the dimensions we need to actually create the area for our chart in the DOM. To do that, we need to use something called <code>d3.select</code></p>
<p>Think of this as exactly the same as the set of <code>document.getElementBy[X]</code>commands the DOM offers natively.</p>
<p>When you use something like <code>d3.select('.chart')</code>, you are asking D3 to select an element with a class named chart.</p>
<p>Note that we’re saving the selection inside of a variable. This will be important later.</p>
<p>When you select something with <code>d3.select</code>, D3 allows you to use method chaining to alter attributes like width and height, like I've done here.</p>
<pre><code><span class="hljs-keyword">const</span> chart = d3.select(<span class="hljs-string">".chart"</span>)  
                .attr(<span class="hljs-string">"width"</span>, width)  
                .attr(<span class="hljs-string">"height"</span>, height)
</code></pre><p>What we’ll end up with is something like the following image</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*qNzjoEPBwmAozK2t.jpg" alt="Image" width="1600" height="1200" loading="lazy">
<em>Chart Display With Margins</em></p>
<p>Don’t worry about the margins for now. We’ll take care of that later.</p>
<h3 id="heading-defining-the-axes">Defining The Axes</h3>
<p>Now, we start with the meaty part of D3: creating and placing our axes.</p>
<p>Before we can start, we need to understand something fundamental about the way D3 axes work: they are essentially a mapping from one set of values to another set of values.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*LbKrhlEvRrf8iXKG.jpg" alt="Image" width="1600" height="1200" loading="lazy"></p>
<p>The two sets of values are called domain and range. D3’s mapping works from the domain onto the range.</p>
<p>I have defined two really simple number lines to illustrate the domain and range. The range is the exact same as the domain with double the number of markings.</p>
<p>In this example its really easy to see how the domain can be mapped to the range. You just need to multiply the value by 2 since the range has double the number of ticks and has the same starting tick value of 0.</p>
<p>I’ve drawn two dashed lines to show the following mappings</p>
<pre><code><span class="hljs-number">2</span> -&gt; <span class="hljs-number">4</span>
<span class="hljs-number">5.5</span> -&gt; <span class="hljs-number">11</span>
</code></pre><p>Now, D3 is not limited only to having real numbers (or even just numbers) to define scales. You can even use characters to define your scales.</p>
<h4 id="heading-the-y-scale">The Y Scale</h4>
<p>We’ll start with the Y scale.</p>
<p>D3 has different kinds of scales but the one we’ll be using is called the linear scale.</p>
<p>To define the scale we need two things: the domain and the range.</p>
<p>We’ll use a simple, stupid rule to define our domain. We’ll assume that the minimum value we can have for one of our categories is 0 and the max value is 100. No negative numbers. The domain then becomes <code>[0, 100]</code></p>
<pre><code><span class="hljs-keyword">const</span> y = d3.scaleLinear()            
            .domain([<span class="hljs-number">0</span>, <span class="hljs-number">100</span>])            
            .range([height - margin.bottom, margin.top])
</code></pre><p>One thing we need to examine here is the range. It took me a little while to understand why the range seems to be in “reverse”. My initial thought was that the range should be <code>[margin.top, height - margin.bottom]</code>. But, we want our Y axis for the chart to start at the bottom and moves vertically upwards.</p>
<p>We’ll consider the following two scenarios in a subsequent diagram to examine this.</p>
<pre><code><span class="hljs-number">1.</span> .range([height - margin.bottom, margin.top])
<span class="hljs-number">2.</span> .range([margin.top, height - margin.bottom])
</code></pre><p>The important difference between the two scenarios is that in the first scenario we are treating the value of height as our ‘zero’ value. In the second scenario, we are treating the <code>margin.top</code> value as our 'zero' value.</p>
<blockquote>
<p><em>One thing to remember before we proceed further: the point of origin of every SVG coordinate system is at the top left corner.</em></p>
</blockquote>
<p>Interpreted another way, the bottom of the Y-axis is our ‘zero’ value in the first scenario and the top of the Y-axis is our ‘zero’ value in the second scenario.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*4o4B62gZcCxV2tTu.jpg" alt="Image" width="1600" height="1200" loading="lazy">
<em>The Two Scenarios Represented Visually</em></p>
<p>In the image above, scenario 1 is on the left and scenario 2 is on the right. You can see the direction of movement for the domain in each image.</p>
<p>In scenario 1, the domain grows upwards from the bottom, which is what we want. In scenario 2, the domain grows downwards from the top, which is what we don’t want.</p>
<p>I appreciate that I might have made things more confusing for those of you who managed to grab the above intuitively but this is something that took me a while to figure out. If you understand intuitively, don’t worry about the above. If you still don’t get it, you will by the end of this post.</p>
<h4 id="heading-the-x-scale">The X Scale</h4>
<p>The X scale is a little easier to figure out. We need the X scale to grow from left to right keeping in mind the width of our chart area and also the margins on the left and right.</p>
<p>The domain on this scale is a little more confusing though because we aren’t dealing with numbers anymore. We are dealing with the letters of our categories instead.</p>
<p>To figure out how to construct this scale, we first need to understand something called the ordinal scale. The quickest way to understand the ordinal scale is to consider the differences between the linear and ordinal scales.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*VbuoXdb6_GMV98lk.jpg" alt="Image" width="1600" height="326" loading="lazy">
<em>The Linear And Ordinal Scale</em></p>
<p>In the image above, you can see a poor drawing of the two scales. The important difference to note is that the linear scale is a <strong>continuous</strong> scale and the ordinal scale is a <strong>discrete</strong> scale.</p>
<p>In the example of the linear scale, if you were to provide a value of 5.5, it would be mapped to the midway point between 5 and 6. However, if you were to provide a value of a letter somewhere between C and D (which doesn’t exist), D3 would have no idea how to map it. As far as D3 is concerned, there is no way to map that value because you have stated that all those values are discrete. That is, there are no connecting values in between.</p>
<p>Now, let’s construct the X axis.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getKeys</span>(<span class="hljs-params">array</span>) </span>{
  <span class="hljs-keyword">return</span> array.map(arrObj = {
    <span class="hljs-keyword">return</span> arrObj.category;
  });
}
<span class="hljs-keyword">const</span> keys = getKeys(data)

<span class="hljs-keyword">const</span> x = d3.scaleOrdinal()
            .domain([...keys])
            .range([margin.left, width - margin.right])
</code></pre><p>If you’re wondering about the function in there and the variable keys, that is to extract all the categories present in our data and provide it to the domain function as an array.</p>
<p>I could just as easily have written <code>.domain(['A', 'B', 'C', 'D', 'E'])</code> but then I would have had to manually update that every time my data changed.</p>
<p>The range, as I have already mentioned, needs to grow from left to right. So, we leave out the margin on the left, move the length of the width and leave out the margin on the right.</p>
<h4 id="heading-creating-the-actual-axes">Creating The Actual Axes</h4>
<p>Now, we have the chart area and the scales defined, we need to set up the axes themselves. Here is how we do that.</p>
<pre><code><span class="hljs-keyword">const</span> xAxis = d3.axisBottom(x)
</code></pre><p>Here, we are creating a <strong>function</strong> called xAxis which uses the <code>d3.axisBottom</code>function with our x scale provided as a parameter.</p>
<p>To actually display the X-axis on our chart, we need to do the following</p>
<pre><code>chart.append(<span class="hljs-string">'g'</span>)
      .attr(<span class="hljs-string">'transform'</span>, <span class="hljs-string">`translate(0, <span class="hljs-subst">${height}</span>)`</span>)
      .call(xAxis)
</code></pre><p>Two things to examine here.</p>
<p>We’re appending a <code>g</code> element to our chart. We discussed the <code>g</code> element in an earlier section. We then apply a transform to our <code>g</code> element. This transform is something that comes up in D3 all the time.</p>
<p>SVG’s have what are called transform functions. There are multiple kinds of transform functions, but the one we care about here is <code>translate</code>. <code>Translate</code>accepts two parameters an <code>x</code> and <code>y</code> co-ordinate. This signifies how many units of pixels to move the <code>g</code> element either in the X or the Y direction.</p>
<p>You can read more about transforms <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform">here</a>.</p>
<p>The two parameters we provide to the <code>translate</code> function are 0 and <code>height</code>. Remember that the point of origin of our SVG chart is at the top left corner. Since, we already know this is a horizontal axis that begins at the point of origin, we need to move it vertically down by <code>height</code> number of units.</p>
<p>If you didn’t provide the transform attribute, the X-axis would be situated at the top of your chart.</p>
<p>The last part of the method chain is a <code>call</code> function where the xAxis is provided as a parameter. This is probably the most confusing aspect so far because of the poor choice of terminology.</p>
<p>We’ll examine just these two lines first.</p>
<pre><code>.append(<span class="hljs-string">'g'</span>)
.attr(<span class="hljs-string">'transform'</span>, <span class="hljs-string">`translate(0, <span class="hljs-subst">${height}</span>)`</span>)
</code></pre><p>What you need to understand is that when you do something like <code>chart.append('g')</code>, this appends a <code>g</code> element onto the chart element, selects the <code>g</code> element and then returns it. You can test this by doing the following</p>
<pre><code><span class="hljs-keyword">const</span> test = chart.append(<span class="hljs-string">'g'</span>)      
            .attr(<span class="hljs-string">'transform'</span>, <span class="hljs-string">`translate(0, <span class="hljs-subst">${height}</span>)`</span>)          
            .call(xAxis)<span class="hljs-built_in">console</span>.log(test)
</code></pre><p>When the result of the log shows up, you’ll see a <code>g</code> element under a <code>Selection</code> object. This is actually what enables us to do method chaining on the <code>append</code> method. Since it returns the <code>g</code> element, we can transform as part of the same method chain.</p>
<p>Let’s go to the last line now</p>
<pre><code>.call(xAxis)
</code></pre><p>Here’s what D3’s documentation says about <code>call</code></p>
<blockquote>
<p><em>Invokes the specified function exactly once, passing in this selection along with any optional arguments. Returns this selection.</em></p>
</blockquote>
<p>So, we know we utilize call as a function and we have to pass it a function as a parameter. We know this because the documentation says, it invokes the specific function exactly once. Now, the other thing to realize is that xAxis is also a function. You can verify this again by logging xAxis.</p>
<p>But, if xAxis is also a function then that needs a parameter passed to it as well. Read the documentation for <code>call</code> again and you'll notice it says "passes in this selection...". This means that the xAxis function is being <strong>implicitly</strong> called with the <code>g</code> selection returned from calling <code>chart.append('g')</code></p>
<p>Having to explain how <code>call</code> works is precisely why I don't like it. There's too much implicitly happening that just seems like black magic.</p>
<p>If you’re still confused about how <code>call</code> works hopefully the following graphic clears it up for you.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*NQRME3mBTerW3CVWukVUZQ.jpeg" alt="Image" width="1600" height="550" loading="lazy">
<em>How Call Works</em></p>
<p>Creating the Y axis now that we know how the X axis works is far simpler. We use the same principles but swap out <code>axisBottom</code> for <code>axisLeft</code> and change the translate function slightly.</p>
<pre><code><span class="hljs-keyword">const</span> yAxis = d3.axisLeft(y);

chart
  .append(<span class="hljs-string">"g"</span>)
  .attr(<span class="hljs-string">"transform"</span>, <span class="hljs-string">`translate(<span class="hljs-subst">${margin.left}</span>, <span class="hljs-subst">${margin.bottom}</span>)`</span>)
  .call(yAxis);
</code></pre><p>You’ll notice that the <code>transform</code> attribute has a <code>translate</code> function where the <code>y</code> attribute is set to <code>margin.bottom</code>. If you go back to the range we set for the y scale, you'll notice we set it to <code>height - margin.bottom</code>.</p>
<p>When we call D3’s <code>axisBottom</code> function, D3 will place this at <code>height - margin.bottom</code>, but the bottom of the chart is actually at <code>height</code>, so we add the <code>margin.bottom</code> offset.</p>
<h3 id="heading-placing-the-bars">Placing The Bars</h3>
<p>This is the most visually important part of the chart because this is where the user actually gets to see the data.</p>
<p>First, let me just show you the code that will create the bars for us and then step through it.</p>
<pre><code>chart.selectAll(<span class="hljs-string">'rect'</span>)
    .data(data)
    .join(<span class="hljs-string">'rect'</span>)
    .attr(<span class="hljs-string">'x'</span>, <span class="hljs-function"><span class="hljs-params">d</span> =&gt;</span> x(d.category))
    .attr(<span class="hljs-string">'y'</span>, <span class="hljs-function"><span class="hljs-params">d</span> =&gt;</span> y(d.value))
    .attr(<span class="hljs-string">'width'</span>, x.bandwidth())
    .attr(<span class="hljs-string">'height'</span>, height - y(d.value))
    .style(<span class="hljs-string">'fill'</span>, <span class="hljs-string">'steelblue'</span>)
</code></pre><p>The first two lines are straightforward. <code>selectAll</code> works the same as <code>select</code>except it returns all possible selections of a specific elemenet.</p>
<p>Calling <code>.data</code> allows you to define the data you want to associate with the DOM elements.</p>
<p>Now, the <code>.join</code> is where the crux of D3 comes in. This is what makes D3 unbelievably powerful to create visualizations with.</p>
<p>If you want to read what Mike Bostock (the creator of D3) has to say on data joins, you can find that <a target="_blank" href="https://bost.ocks.org/mike/join/">here</a>.</p>
<p>What follows is my attempt at explaining what the <code>.join</code> function does in the context of a bar chart.</p>
<p>So, if you go back and look at the data we defined earlier in this post, you’ll notice that it is an array. The reason is because this is the data structure D3 expects.</p>
<p>The <code>.join</code> function then takes every element of the array and <strong>constructs a corresponding DOM element with this data point attached</strong>.</p>
<p><em>Note: The</em> <code>_.join_</code> <em>function used to earlier be separate functions called</em> <code>_.enter_</code><em>and</em> <code>_.append_</code><em>. However this syntax is a lot cleaner.</em> <a target="_blank" href="https://github.com/d3/d3-selection/issues/194"><em>Here</em></a> <em>is the GitHub issue where Mike Bostock first suggested it.</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*9Agl9_MBX5kNT8Dm.jpg" alt="Image" width="1600" height="601" loading="lazy">
<em>How .join() works visually</em></p>
<p><em>Note: In the graphic above, it should read</em> <code>_.join('rect')_</code> <em>not</em> <code>_.join('bar')_</code></p>
<p>The graphic above illustrates what is going on when you do a data join. If you take an array of 5 elements and perform a <code>.join('rect')</code> on it, what D3 will do is create a rect SVG element for each of those elements.</p>
<p>Another thing D3 will do is associate each data point from your array to its respective <code>rect</code> element.</p>
<pre><code><span class="hljs-keyword">const</span> data = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]

<span class="hljs-keyword">const</span> selection = d3.selectAll(<span class="hljs-string">'rect'</span>)
                    .data(data)
                    .join(<span class="hljs-string">'rect)

selection.each(function(d, i) {
  console.log(d)
})

//1, 2, 3, 4, 5</span>
</code></pre><p>The above code snippet shows you how to do the logging of each individual data point to satisfy your own curiosity.</p>
<p>You could, of course, replace the <code>rect</code> above with any other SVG element and you would have the same result.</p>
<p>Great, now we know how to create our bars but we still need to figure out how to place them. Before continuing, I recommend you read <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect">this MDN article</a>about rects.</p>
<p>One thing that tripped me up a lot about working with D3 intially was trying to figure out how the SVG coordinate system works.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*643mFxRq-pIzDknQ.jpg" alt="Image" width="1600" height="1199" loading="lazy"></p>
<p><em>If you want a deeper understanding of how SVG coordinate systems work, check out</em> <a target="_blank" href="https://www.sarasoueidan.com/blog/svg-coordinate-systems/"><em>this</em></a> <em>article</em></p>
<p>The graphic above shows you how different measurements would impact the placement of a rect in the SVG coordinate space.</p>
<p>A rect SVG element has four main attributes we’ll be concerned with: x, y, width and height.</p>
<p>You can see how each of them relate to the SVG coordinate space in the image.</p>
<p>Let’s translate the above into code.</p>
<pre><code>chart
  .selectAll(<span class="hljs-string">"rect"</span>)
  .data(data)
  .join(<span class="hljs-string">"rect"</span>)
  .attr(<span class="hljs-string">"x"</span>, <span class="hljs-function"><span class="hljs-params">d</span> =&gt;</span> <span class="hljs-keyword">return</span> x(d.category))
  .attr(<span class="hljs-string">"y"</span>, <span class="hljs-function"><span class="hljs-params">d</span> =&gt;</span> <span class="hljs-keyword">return</span> y(d.value))
  .attr(<span class="hljs-string">"width"</span>, x.bandwidth())
  .attr(<span class="hljs-string">"height"</span>, <span class="hljs-function"><span class="hljs-params">d</span> =&gt;</span> height - y(d.value))
  .style(<span class="hljs-string">"fill"</span>, <span class="hljs-string">"steelblue"</span>);
</code></pre><p>Let’s step through the bits of the code after the <code>.join</code> call.</p>
<p>When we set the <code>x</code> and <code>y</code> attributes, we make a call to the respective scales we defined earlier. Remember when we defined the scales, we said that each of them would be functions that could be called with a value to map it from the domain to the range. That's precisely what we're doing here.</p>
<p>Now, to understand the width attribute, we first need to go back to the <code>ordinalScale</code> we defined. D3 has a function associated with each scale called the <code>bandwidth</code> function. This returns the width of each band defined. D3 internally does this by dividing the range equally among each element of the domain.</p>
<p>So, we provided an array of 5 characters as the domain of the x axis and we set the range to <code>[margin.left, width - margin.right]</code>, where <code>width = 800</code>and <code>margin = { left: 60, right: 60 }</code></p>
<p>So, we have</p>
<pre><code>(<span class="hljs-number">800</span> - <span class="hljs-number">60</span> - <span class="hljs-number">60</span>) / <span class="hljs-number">5</span> = <span class="hljs-number">136</span>
All units are <span class="hljs-keyword">in</span> pixels.
</code></pre><p>Now, the height attribute is another thing that tripped me up for a long time because I couldn’t quite figure out why we were doing <code>height - y(d.value)</code>to represent the height of the rect. Surely, it should have just been <code>y(d.value)</code>?</p>
<p>This is answered again by remembering that the SVG coordinate has its point of origin in the top left corner and the +ve Y-axis goes downwards.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*bgKCtRR14RyZTBOI.jpg" alt="Image" width="1600" height="1252" loading="lazy">
<em>Measurements For A Bar in SVG Coordinate System</em></p>
<p>In the graphic above, I’ve presented my understanding of how the height of the bar is calculated. Again, if the calculation for the height of the bar makes intuitive sense for you, feel free to skip this.</p>
<p>The main thing to notice in the visual is that there is a difference between the axes of the SVG coordinate system and the axes of our chart. The Y axis for the SVG coordinate system is positive downwards but the Y axis for our chart is positive upwards.</p>
<p>This is the reason I’ve drawn two separate sets of axes for both X and Y. Technically, the two Y axes should be superimposed on top of one another but that would make it hard to visually see it. But, you can assume that they are overlayed on top of each other.</p>
<p>When we call the y scale function with <code>y(d.value)</code>, we get a value that <em>counts down</em> the +ve Y-axis of the SVG coordinate system starting from the top. The height is shown on the side which is the entire length of the Y axis and then what remains is <code>height - y(d.value)</code>, which is the height we are assigning to the bar.</p>
<h3 id="heading-adding-titles-and-labels">Adding Titles And Labels</h3>
<p>Now, we get to the easy bit. It’s only easy because of everything we’ve covered so far!</p>
<p>Similar to how we’ve appended <code>rects</code> to our SVG so far, we can also append <code>text</code> as an SVG element like below:</p>
<pre><code>chart.append(<span class="hljs-string">'text'</span>)
      .attr(<span class="hljs-string">'x'</span>, width / <span class="hljs-number">2</span>)
      .attr(<span class="hljs-string">'y'</span>, margin.top)
      .style(<span class="hljs-string">'font-size'</span>, <span class="hljs-number">32</span>px)
      .style(<span class="hljs-string">'text-anchor'</span>, <span class="hljs-string">'middle'</span>)
      .text(<span class="hljs-string">'Distribution Among Categories'</span>)
</code></pre><p>The text SVG element also has an <code>x</code> and <code>y</code> attribute that work very similarly to how the <code>x</code> and <code>y</code> attributes of the <code>rect</code> work.</p>
<p>You can set different style attributes to the text element and you set the text itself using the <code>.text</code> attribute.</p>
<p>Now, let’s place the Y-axis label</p>
<pre><code>chart
  .append(<span class="hljs-string">"text"</span>)
  .attr(<span class="hljs-string">"transform"</span>, <span class="hljs-string">"rotate(-90)"</span>)
  .attr(<span class="hljs-string">"x"</span>, -height / <span class="hljs-number">2</span>)
  .attr(<span class="hljs-string">"y"</span>, margin.left / <span class="hljs-number">4</span>)
  .text(<span class="hljs-string">"Values"</span>)
</code></pre><p>Okay, this one is a little confusing, so let’s step through it.</p>
<p>First, we apply a <code>transform</code> to the element and set that value to <code>rotate(-90)</code>. What this does is rotate the <em>SVG coordinate system itself</em> by -90 degrees.</p>
<p><em>Note: Everything that follows is my attempt to reverse engineer how the rotate function works. If I turn out to be wrong, please excuse me.</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*Om8G45AlhzM7Nxw6.jpg" alt="Image" width="1600" height="781" loading="lazy">
<em>Axis Rotation</em></p>
<p>The graphic above shows what happens to the coordinate system on applying <code>rotate(-90)</code>. Now, you're probably even more confused because a negative rotation typically means a clockwise rotation. Yet, it looks like I've rotated anti-clockwise here.</p>
<p>Well, remember that a typical coordinate system has the Y-axis pointing positively upwards. We have it pointing positively downwards. Therefore, our rotations are reversed.</p>
<p>Now, our new X axis points in the opposite direction of the old Y axis and our new Y axis points in the direction of the old X axis.</p>
<p>Now, in the context of this new information, looking at the values of the <code>x</code>and <code>y</code> attributes makes more sense. Since our new X points opposite to the direction of the old Y, we set a negative value to the <code>x</code> attribute.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Okay, that was quite the post. I wasn’t envisioning it becoming quite so massive but we did cover a lot in detail. I hope you enjoyed going through this post and more than anything, I hope you have a better grasp of how D3 works. This is a truly wonderful library that provides you with a set of very powerful tools.</p>
<p>I’ve created a <a target="_blank" href="https://codesandbox.io/s/blazing-pine-9vjw1">Code Sanbox here</a> with a working version of the code from this post. Feel free to fork it and play around with it!</p>
<hr>
<p><em>If you want to follow me, you can do so on</em> <a target="_blank" href="https://github.com/"><em>GitHub</em></a> <em>or</em> <a target="_blank" href="https://twitter.com/zz_humayun"><em>Twitter</em></a><em>. If you have any questions, please don’t hesitate to ask.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A linguistic introduction to d3.js ]]>
                </title>
                <description>
                    <![CDATA[ By Matt Oxley How to go from a tentative to a confident user d3.js is a fantastic library — but I can honestly tell you that for a long time I used it without fully understanding it. Lacking any solid mental model of what I was working with, I would... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-linguistic-introduction-to-d3-js-7a40a980bf97/</link>
                <guid isPermaLink="false">66c342ce4f7405e6476b015b</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 18 Apr 2019 18:50:15 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*x6CsLy79iYNsymXLhWlBXg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Matt Oxley</p>
<h4 id="heading-how-to-go-from-a-tentative-to-a-confident-user">How to go from a tentative to a confident user</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/yOdP1Z2NyjFQgxCQU7lCDfvPvKdLOXU9IXyP" alt="Image" width="800" height="414" loading="lazy"></p>
<p>d3.js is a fantastic library — but I can honestly tell you that for a long time I used it without fully understanding it. Lacking any solid mental model of what I was working with, I would admittedly tend to copy/paste pieces of code from various snippets over at <a target="_blank" href="http://bl.ocks.org">bl.ocks.org</a>, cross my fingers and hope for the best.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A gentle introduction to D3: how to build a reusable bubble chart ]]>
                </title>
                <description>
                    <![CDATA[ By Déborah Mesquita Getting Started with D3 When I started to learn D3, nothing made sense to me. Things only became more clear when I started to learn about reusable charts. In this article, I’ll show you how to create a reusable bubble chart and g... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-gentle-introduction-to-d3-how-to-build-a-reusable-bubble-chart-9106dc4f6c46/</link>
                <guid isPermaLink="false">66c342944f7405e6476b0157</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 11 Mar 2017 19:20:44 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*Ywul1VdNkWbdFz3x5iVYCA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Déborah Mesquita</p>
<h4 id="heading-getting-started-with-d3">Getting Started with D3</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/b1f4Gb2hEkCUMp9X0hyUcsXKVAMuRPFHYuvk" alt="Image" width="800" height="533" loading="lazy"></p>
<p>When I started to learn D3, nothing made sense to me. Things only became more clear when I started to learn about reusable charts.</p>
<p>In this article, I’ll show you how to create a reusable bubble chart and give you a gentle introduction to D3 along the way. The dataset we’ll use is composed of <a target="_blank" href="https://github.com/dmesquita/reusable_bubble_chart/blob/master/medium_january.csv">stories published in the freeCodeCamp in January 2017</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ST0umvE7-OejTYSovrDQQZQzVPbXqKGhtUnL" alt="Image" width="800" height="474" loading="lazy">
<em>This is the chart you’re going to build</em></p>
<h3 id="heading-about-d3">About D3</h3>
<p><a target="_blank" href="https://d3js.org/">D3</a> is a JavaScript library for data visualization. It brings data to life using HTML, SVG and CSS.</p>
<p>We often need to reuse a chart in another project, or event share the chart with others. For this, Mike Bostock (the creator of D3) proposed a model called <a target="_blank" href="https://bost.ocks.org/mike/chart/">reusable charts</a>. We’ll use his approach with some small modifications, as presented by Pablo Navarro Castillo in the book <a target="_blank" href="http://pnavarrc.github.io/book/">Mastering D3.js</a>.</p>
<p>We are using D3 version <strong>4.6.0</strong> here.</p>
<h3 id="heading-reusable-charts">?Reusable charts</h3>
<p>Graphs following the reusable chart pattern have two characteristics:</p>
<ul>
<li><strong>Configurability.</strong> We want to modify the appearance and behavior of the graph without having to modify the code itself.</li>
<li><strong>Ability to be built in an independent way.</strong> We want every graph element associated with a data point of our dataset independently. This has to do with the way D3 associates data instances with DOM elements. This will become more clear in a minute.</li>
</ul>
<blockquote>
<p>“To sum up: implement charts as <strong>closures with getter-setter methods.” —</strong> <a target="_blank" href="https://bost.ocks.org/mike/chart/">Mike Bostock</a></p>
</blockquote>
<h3 id="heading-the-bubble-chart">The bubble chart</h3>
<p>You first need to define which elements of the chart can be customized:</p>
<ul>
<li>The size of the chart</li>
<li>The input dataset</li>
</ul>
<h4 id="heading-defining-the-size-of-the-chart">Defining the size of the chart</h4>
<p>Let's start by creating a function to encapsulate all variables of the graph and set the default values. This structure is called a closure.</p>
<pre><code><span class="hljs-comment">// bubble_graph.js</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> bubbleChart = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{    <span class="hljs-keyword">var</span> width = <span class="hljs-number">600</span>,    height = <span class="hljs-number">400</span>;    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">chart</span>(<span class="hljs-params">selection</span>)</span>{        <span class="hljs-comment">// you gonna get here    }    return chart;}</span>
</code></pre><p>You want to create charts of different sizes without having to change the code. For this you will create charts as follows:</p>
<pre><code><span class="hljs-comment">// bubble_graph.html</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> chart = bubbleChart().width(<span class="hljs-number">300</span>).height(<span class="hljs-number">200</span>);
</code></pre><p>To do that, now you will define accessors for the width and height variables.</p>
<pre><code><span class="hljs-comment">// bubble_graph.js</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> bubbleChart = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{    <span class="hljs-keyword">var</span> width = <span class="hljs-number">600</span>    height = <span class="hljs-number">400</span>;
</code></pre><pre><code>    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">chart</span>(<span class="hljs-params">selection</span>)</span>{        <span class="hljs-comment">// we gonna get here    }    chart.width = function(value) {        if (!arguments.length) { return width; }        width = value;        return chart;    }</span>
</code></pre><pre><code>    chart.height = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{        <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">arguments</span>.length) { <span class="hljs-keyword">return</span> height; }        height = value;        <span class="hljs-keyword">return</span> chart;    }    <span class="hljs-keyword">return</span> chart;}
</code></pre><p>If you call <code>bubbleChart()</code> (without width or height attributes) the graph is created with the default width and heights values you defined inside the closure. If called without arguments, the method returns the variable value.</p>
<pre><code><span class="hljs-comment">// bubble_graph.html</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> chart = bubbleChart();bubbleChart().width(); <span class="hljs-comment">// returns 600</span>
</code></pre><p>You may be wondering why the methods return the chart function. This is a JavaScript pattern used to simplify the code. It's called method chaining. With this pattern you can create new objects like this:</p>
<pre><code><span class="hljs-comment">// bubble_graph.html</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> chart = bubbleChart().width(<span class="hljs-number">600</span>).height(<span class="hljs-number">400</span>);
</code></pre><p>instead of:</p>
<pre><code><span class="hljs-comment">// bubble_graph.html</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> chart = bubbleChart(); chart.setWidth(<span class="hljs-number">600</span>); chart.setHeight(<span class="hljs-number">400</span>);
</code></pre><h4 id="heading-joining-data-with-our-chart">Joining data with our chart</h4>
<p>Now let’s learn how to join data with chart elements. Here’s how the chart is structured: the div with the graph has an SVG element, and each data point corresponds to a circle in the chart.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/KDQtSripZjkfZlWAGwt1RMOhoOEtuZy6BvbV" alt="Image" width="800" height="301" loading="lazy"></p>
<pre><code><span class="hljs-comment">// bubble_graph.html, after the bubbleChart() function is called</span>
</code></pre><pre><code>&lt;svg width=<span class="hljs-string">"600"</span> height=<span class="hljs-string">"400"</span>&gt;;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">circle</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">circle</span>&gt;</span></span> <span class="hljs-comment">// a story from data    &lt;circle&gt;&lt;/circle&amp;gt; // another story from data    ...&lt;/svg&gt;</span>
</code></pre><h4 id="heading-d3data">? d3.data()</h4>
<p>The <code>d3.selection.**data**([data[,key]])</code> function returns a new selection that represents an element successfully bound to data. To do that, you first need to load the data from the .csv file. You will use the <code>d3.**csv**(_url_[[, _row_], _callback_])</code> function.</p>
<pre><code><span class="hljs-comment">// bubble_graph.html</span>
</code></pre><pre><code>d3.csv(<span class="hljs-string">'file.csv'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error, our_data</span>) </span>{    <span class="hljs-keyword">var</span> data = our_data; <span class="hljs-comment">//here you can do what you want with the data}</span>
</code></pre><pre><code><span class="hljs-comment">// medium_january.csv|                title                 |   category   | hearts ||--------------------------------------|--------------|--------|| Nobody wants to use software         | Development  |  2700  |  | Lossless Web Navigation with Trails  |    Design    |  688   |   | The Rise of the Data Engineer        | Data Science |  862   |</span>
</code></pre><h4 id="heading-d3-selection">? d3-selection</h4>
<p>You will use the <strong>d3-select()</strong> and the <strong>data()</strong> functions to pass our data to the chart.</p>
<blockquote>
<p>Selections allow powerful data-driven transformation of the document object model (DOM): set <a target="_blank" href="https://github.com/d3/d3-selection/blob/master/README.md#selection_attr">attributes</a>, <a target="_blank" href="https://github.com/d3/d3-selection/blob/master/README.md#selection_style">styles</a>, <a target="_blank" href="https://github.com/d3/d3-selection/blob/master/README.md#selection_property">properties</a>, <a target="_blank" href="https://github.com/d3/d3-selection/blob/master/README.md#selection_html">HTML</a> or <a target="_blank" href="https://github.com/d3/d3-selection/blob/master/README.md#selection_text">text</a> content, and more. — <a target="_blank" href="https://github.com/d3/d3-selection/">D3 documentation</a></p>
</blockquote>
<pre><code><span class="hljs-comment">// bubble_graph.html</span>
</code></pre><pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"chart-example"</span> id=<span class="hljs-string">"chart"</span>&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>&lt;/div&gt;
</code></pre><pre><code>d3.csv(<span class="hljs-string">'medium_january.csv'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error, our_data</span>) </span>{    <span class="hljs-keyword">if</span> (error) {        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error getting or parsing the data.'</span>);        <span class="hljs-keyword">throw</span> error;    }
</code></pre><pre><code>    <span class="hljs-keyword">var</span> chart = bubbleChart().width(<span class="hljs-number">600</span>).height(<span class="hljs-number">400</span>);    d3.select(<span class="hljs-string">'#chart'</span>).data(our_data).call(chart);
</code></pre><pre><code> });
</code></pre><p>Another important selector is <strong>d3.selectAll()</strong>. Let's say you have the following structure:</p>
<pre><code>&lt;body&gt;    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>&lt;/body&gt;
</code></pre><p><code>d3.select("body").selectAll("div")</code> selects all those divs for us.</p>
<h4 id="heading-d3enter">?? d3.enter()</h4>
<p>And now you’re going to learn about an important D3 function: <strong>d3.enter()</strong>. Let's say you have an empty body tag and an array with data. You want to go through each element of the array and create a new div for each element. You can do this with the following code:</p>
<pre><code>&lt;!-- before --&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> //empty<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span></span>
</code></pre><pre><code>----<span class="hljs-comment">// js script</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> our_data = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]<span class="hljs-keyword">var</span> div = d3.select(<span class="hljs-string">"body"</span>) .selectAll(<span class="hljs-string">"div"</span>) .data(our_data) .enter() .append(<span class="hljs-string">"div"</span>);---
</code></pre><pre><code>&lt;!-- after --&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span></span>
</code></pre><p>Why do you need <code>selectAll("div")</code> if the the divs don't even exist yet? Because in D3 instead of telling <strong>how</strong> to do something, we tell <strong>what</strong> we want.</p>
<p>In this case, you want to associate each div with a element of the array. That's what you are saying with the <code>selectAll("div")</code>.</p>
<pre><code><span class="hljs-keyword">var</span> div = d3.select(<span class="hljs-string">"body"</span>) .selectAll(<span class="hljs-string">"div"</span>) <span class="hljs-comment">// here you are saying 'hey d3, each data element      of the array that comes next will be bound to a div' .data(our_data) .enter().append("div");</span>
</code></pre><p>The <code>enter()</code> returns the selection with the data bound to the element of the array. You then finally add this selection to the DOM with the <code>.append("div")</code></p>
<h4 id="heading-d3forcesimulation">?d3.forceSimulation()</h4>
<p>You need something to simulate the physics of the circles. For this you will use <code>d3.forceSimulation([nodes])</code>. You also need to tell what kind of force will change the position or the velocity of the nodes.</p>
<p>In our case, we’ll use the <code>d3.forceManyBody()</code>.</p>
<pre><code><span class="hljs-comment">// bubble_chart.js</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> simulation = d3.forceSimulation(data) .force(<span class="hljs-string">"charge"</span>, d3.forceManyBody().strength([<span class="hljs-number">-50</span>])) .force(<span class="hljs-string">"x"</span>, d3.forceX()) .force(<span class="hljs-string">"y"</span>, d3.forceY()) .on(<span class="hljs-string">"tick"</span>, ticked);
</code></pre><p>A positive strength value causes the nodes to attract each other, while a negative strength value causes them to repel each other.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/wMJSa903Hk1t5odK27XEEl0vhpYS8eq6odq5" alt="Image" width="800" height="301" loading="lazy">
<em>The strength() effect</em></p>
<p>We don't want the nodes spreading out through the whole SVG space, though, so we use <code>d3.forceX(0)</code> and<code>d3.forceY(0)</code>. This "drags" the circles to the 0 position. Go ahead and try removing this from the code to see what happens.</p>
<p>When you refresh the page, you can see that the circles adjust until they finally stabilize. The <code>ticked()</code> function updates the positions of the circles. The <code>d3.forceManyBody()</code> keeps updating the x and y position of each node, and the the <code>ticked()</code> function updates the DOM with these values (the cx and cy attributes).</p>
<pre><code><span class="hljs-comment">// bubble_graph.js</span>
</code></pre><pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ticked</span>(<span class="hljs-params">e</span>) </span>{    node.attr(<span class="hljs-string">"cx"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> d.x; })        .attr(<span class="hljs-string">"cy"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> d.y; });    <span class="hljs-comment">// 'node' is each circle of the bubble chart</span>
</code></pre><pre><code> }
</code></pre><p>Here's the code with everything together:</p>
<pre><code><span class="hljs-keyword">var</span> simulation = d3.forceSimulation(data)     .force(<span class="hljs-string">"charge"</span>, d3.forceManyBody().strength([<span class="hljs-number">-50</span>]))     .force(<span class="hljs-string">"x"</span>, d3.forceX())     .force(<span class="hljs-string">"y"</span>, d3.forceY())     .on(<span class="hljs-string">"tick"</span>, ticked);
</code></pre><pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ticked</span>(<span class="hljs-params">e</span>) </span>{     node.attr(<span class="hljs-string">"cx"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> d.x; })         .attr(<span class="hljs-string">"cy"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> d.y; }); }
</code></pre><p>To sum up, all this simulation does is give each circle an x and y position.</p>
<h4 id="heading-d3scales">? d3.scales</h4>
<p>Here comes the most exciting part: actually adding the circles. Remember the <strong>enter()</strong> function? You will use it now. In our chart the radius of each circle is proportional to the number of recommendations of each story. To do that you will use a linear scale: <strong>d3.scaleLinear()</strong></p>
<p>To use scales you need to define two things:</p>
<ul>
<li><strong>Domain</strong>: the minimum and maximum values of the input data (in our case, the minimum and maximum number of recommendations). To get the minimum and maximum values, you’ll use the <strong>d3.min()</strong> and <strong>d3.max()</strong> functions.</li>
<li><strong>Range</strong>: the minimum and maximum output values of the scale. In our case, we want the smallest radius of size 5 and the biggest radius of size 18.</li>
</ul>
<pre><code><span class="hljs-comment">// bubble_graph.js</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> scaleRadius = d3.scaleLinear()            .domain([d3.min(data, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> +d.views; }),                     d3.max(data, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> +d.views; })])            .range([<span class="hljs-number">5</span>,<span class="hljs-number">18</span>]);
</code></pre><p>And then you finally create the circles:</p>
<pre><code><span class="hljs-comment">// bubble_graph.js</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> node = svg.selectAll(<span class="hljs-string">"circle"</span>)   .data(data)   .enter()   .append(<span class="hljs-string">"circle"</span>)   .attr(<span class="hljs-string">'r'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> scaleRadius(d.views)})});
</code></pre><p>To color the circles, you’ll use a categorical scale: <strong>d3.scaleOrdinal()</strong>. This scale returns discrete values.</p>
<p>Our dataset has 3 categories: Design, Development and Data Science. You will map each of these categories to a color. <code>d3.schemeCategory10</code> gives us a list of 10 colors, which is enough for us.</p>
<pre><code><span class="hljs-comment">// bubble_graph.js</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> colorCircles = d3.scaleOrdinal(d3.schemeCategory10);<span class="hljs-keyword">var</span> node = svg.selectAll(<span class="hljs-string">"circle"</span>)    .data(data)    .enter()    .append(<span class="hljs-string">"circle"</span>)    .attr(<span class="hljs-string">'r'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> scaleRadius(d.views)})    .style(<span class="hljs-string">"fill"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> colorCircles(d.category)});
</code></pre><p>You want the circles drawn in the middle of the SVG, so you’ll move each circle to the middle (half the width and half the height). Go ahead and remove this from the code to see what happens.</p>
<pre><code><span class="hljs-comment">// bubble_graph.js</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> node = svg.selectAll(<span class="hljs-string">"circle"</span>) .data(data) .enter() .append(<span class="hljs-string">"circle"</span>) .attr(<span class="hljs-string">'r'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> scaleRadius(d.views)}) .style(<span class="hljs-string">"fill"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{<span class="hljs-keyword">return</span> colorCircles(d.category)}) .attr(<span class="hljs-string">'transform'</span>, <span class="hljs-string">'translate('</span> + [width / <span class="hljs-number">2</span>, height / <span class="hljs-number">2</span>] + <span class="hljs-string">')'</span>);
</code></pre><p>Now you’ll add tooltips to the chart. They need to appear whenever we place the mouse over the circles.</p>
<pre><code><span class="hljs-keyword">var</span> tooltip = selection .append(<span class="hljs-string">"div"</span>) .style(<span class="hljs-string">"position"</span>, <span class="hljs-string">"absolute"</span>) .style(<span class="hljs-string">"visibility"</span>, <span class="hljs-string">"hidden"</span>) .style(<span class="hljs-string">"color"</span>, <span class="hljs-string">"white"</span>) .style(<span class="hljs-string">"padding"</span>, <span class="hljs-string">"8px"</span>) .style(<span class="hljs-string">"background-color"</span>, <span class="hljs-string">"#626D71"</span>) .style(<span class="hljs-string">"border-radius"</span>, <span class="hljs-string">"6px"</span>) .style(<span class="hljs-string">"text-align"</span>, <span class="hljs-string">"center"</span>) .style(<span class="hljs-string">"font-family"</span>, <span class="hljs-string">"monospace"</span>) .style(<span class="hljs-string">"width"</span>, <span class="hljs-string">"400px"</span>) .text(<span class="hljs-string">""</span>);
</code></pre><pre><code><span class="hljs-keyword">var</span> node = svg.selectAll(<span class="hljs-string">"circle"</span>) .data(data) .enter() .append(<span class="hljs-string">"circle"</span>) .attr(<span class="hljs-string">'r'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> scaleRadius(d.views)}) .style(<span class="hljs-string">"fill"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{<span class="hljs-keyword">return</span> colorCircles(d.category)}) .attr(<span class="hljs-string">'transform'</span>, <span class="hljs-string">'translate('</span> + [width / <span class="hljs-number">2</span>, height / <span class="hljs-number">2</span>] + <span class="hljs-string">')'</span>) .on(<span class="hljs-string">"mouseover"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>)</span>{     tooltip.html(d.category +<span class="hljs-string">"&lt;br&gt;"</span>+ d.title+<span class="hljs-string">"&lt;br&gt;"</span>+d.views);      <span class="hljs-keyword">return</span> tooltip.style(<span class="hljs-string">"visibility"</span>, <span class="hljs-string">"visible"</span>);}) .on(<span class="hljs-string">"mousemove"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{   <span class="hljs-keyword">return</span> tooltip.style(<span class="hljs-string">"top"</span>, (d3.event.pageY-       <span class="hljs-number">10</span>)+<span class="hljs-string">"px"</span>).style(<span class="hljs-string">"left"</span>,(d3.event.pageX+<span class="hljs-number">10</span>)+<span class="hljs-string">"px"</span>);}) .on(<span class="hljs-string">"mouseout"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{<span class="hljs-keyword">return</span> tooltip.style(<span class="hljs-string">"visibility"</span>, <span class="hljs-string">"hidden"</span>);});
</code></pre><p>The <code>mousemove</code> follows the cursor when the mouse is moving. <code>d3.event.pageX</code> and <code>d3.event.pageY</code> return the mouse coordinates.</p>
<p>And that's it! You can see the final code <a target="_blank" href="https://github.com/dmesquita/reusable_bubble_chart">here</a>.</p>
<p>You can play with the bubble chart <a target="_blank" href="https://bl.ocks.org/dmesquita/37d8efdb3d854db8469af4679b8f984a">here</a>.</p>
<p>Did you found this article helpful? I try my best to write a deep dive article each month, you can <a target="_blank" href="https://goo.gl/forms/SLrJDrGtxgAoILkt1">receive an email when I publish a new one</a>.</p>
<p>Any questions or suggestions? Leave them in the comments. Thanks for reading! ?</p>
<p><em>Special thanks to <a target="_blank" href="https://www.freecodecamp.org/news/a-gentle-introduction-to-d3-how-to-build-a-reusable-bubble-chart-9106dc4f6c46/undefined">John Carmichael</a> and <a target="_blank" href="https://www.freecodecamp.org/news/a-gentle-introduction-to-d3-how-to-build-a-reusable-bubble-chart-9106dc4f6c46/undefined">Alexandre Cisneiros</a>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ D3 and Canvas in 3 steps ]]>
                </title>
                <description>
                    <![CDATA[ By lars verspohl The bind, the draw and the interactivity Let’s say you’re building a data visualization using D3 and SVG. You may hit a ceiling when you try to display several thousand elements at the same time. Your browser may start to puff under... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/d3-and-canvas-in-3-steps-8505c8b27444/</link>
                <guid isPermaLink="false">66c3487f3a31d2480bb383a7</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 18 Feb 2017 05:32:17 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*KCOutWkXvU7YhGY2f76kfQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By lars verspohl</p>
<h4 id="heading-the-bind-the-draw-and-the-interactivity">The bind, the draw and the interactivity</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/LJWqERx6v-qDQFc5jb7w2gFCP3YKaNuU36AA" alt="Image" width="800" height="533" loading="lazy"></p>
<p>Let’s say you’re building a data visualization using <a target="_blank" href="https://d3js.org/">D3</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">SVG</a>. You may hit a ceiling when you try to display several thousand elements at the same time. Your browser may start to puff under the weight of all those <a target="_blank" href="https://css-tricks.com/dom/">DOM elements</a>.</p>
<p>Well here comes <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial">HTML5 Canvas</a> to the rescue! It’s much faster, so it can solve your browser’s puffing problems.</p>
<p>But you may quickly find yourself daunted. Because D3 and Canvas works a bit differently from D3 and SVG — especially when it comes to drawing and adding interactivity.</p>
<p>But fear not — it’s not that complicated. Any experience you’ve had with building visuals with D3 and SVG — or approaching D3 with a different renderer — will help you tremendously.</p>
<p>This tutorial built on the shoulders of giants who have already covered Canvas well. I learned these three tutorials by heart and I recommend you do, too:</p>
<ul>
<li><a target="_blank" href="https://bocoup.com/weblog/d3js-and-canvas">Working with D3.js and Canvas: When and How</a> from Irene Ros</li>
<li><a target="_blank" href="https://bocoup.com/weblog/2d-picking-in-canvas">Needles, Haystacks, and the Canvas API</a> from Yannick Assogba</li>
<li><a target="_blank" href="http://www.visualcinnamon.com/2015/11/learnings-from-a-d3-js-addict-on-starting-with-canvas.html">Learnings from a D3.js addict on starting with Canvas</a> from Nadieh Bremer</li>
</ul>
<p>So why continue reading this, then? Well, when I want to learn something new, it helps me a great deal to look at the same subject from slightly different angles. And this tutorial <em>is</em> a slightly different angle.</p>
<p>Also, this tutorial covers the three key steps: <strong>binding data</strong>, <strong>drawing elements</strong>, and <strong>adding interactivity</strong> — and it does all this in one go, with an added <strong>step-by-step manual</strong> to set you up.</p>
<h3 id="heading-what-do-we-build">What do we build?</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lYZIDOUAORE42uN6Xx872jkaX1iG3Lx2TTJ3" alt="Image" width="755" height="478" loading="lazy">
<em>A grid of pretty colours</em></p>
<p>A grid of (many) squares. Their colours aren’t of any deep meaning but don’t they look pretty? The important bit is that you can update it (to cover binding and updating data), that it has many elements (up to 10,000 in order for canvas to pay out), and that you can hover over each square to show square-specific information (interactivity). You can play with it <a target="_blank" href="http://bl.ocks.org/larsvers/raw/d187337850d58a444082841c739985ca/">here on a full screen</a> or <a target="_blank" href="http://blockbuilder.org/larsvers/d187337850d58a444082841c739985ca">here with all the code</a></p>
<h3 id="heading-the-mental-model">The mental model</h3>
<p>Before we actually dive in, let’s quickly step back and grasp conceptually what we do when we create elements with D3 to draw them to the screen. Skip this if you just want to make things.</p>
<p>The first step when using D3 usually doesn’t involve drawing — it involves preparing all your elements you want to draw. It’s a bit like building some LEGO. You can rip open the box and start building something or you can look at the manual first and build it according to the blueprint. The manual is your mental model, a blueprint or recipe of what you want to build.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/7BFtJOkOIVODiluRi9004udf0p2F-6zS9C5o" alt="Image" width="640" height="480" loading="lazy">
_A mental model turned material (Mike, 2009 [https://creativecommons.org/licenses/by/2.0/](https://creativecommons.org/licenses/by/2.0/" rel="noopener" target="<em>blank" title="))</em></p>
<p>What is D3’s model? Apart from the large number of helpful functions and methods that calculate positions, re-shape datasets (the layouts) and generate functions that draw, for example, paths for us, D3 has a model for how the elements’ lives should evolve on the screen. It has a certain way to think about the lifecycle of each element.</p>
<p>Less ethereally, you inject data into a yet non-existent DOM, and D3 creates new elements of your choice as per the data you inject. Usually one element per datapoint. If you want to inject new data into the DOM you can do so and D3 identifies which elements have to be newly created, which elements are allowed to stay and which elements should pack up and leave the screen.</p>
<p>D3 is usually used in conjunction with SVG or sometimes with HTML-elements. In this orthodox case, you can see the data in the DOM when you choose to look at it through the console, for example. You can grab it, you can move it up or down the DOM and you can — importantly — add interactivity to each element you like to show, for example, a tooltip.</p>
<p>But — on the downside — you can’t show a lot of elements. Why? Because the more elements you push into the DOM, the harder the browser has to work to display them all. Let them also move around and the browser needs to re-calculate them constantly. The more knackered the browser gets the lower your frame rate or FPS (Frames Per Second), which measures how many frames the browser can paint each second. A frame rate of 60 is good and enables a fluid experience as long as no frames are missed — a frame rate of anything under 30 can equal a choppy ride. So when you want to show more elements, you can revert to canvas.</p>
<p>Why canvas? Canvas is an HTML5 element which comes with its own API to paint on it. All elements drawn on the canvas element won’t manifest in the DOM and save a lot of work for the browser. They are drawn in <a target="_blank" href="https://en.wikipedia.org/wiki/Immediate_mode_%28computer_graphics%29">immediate mode</a>. This means the rendered elements won’t get saved in the DOM but your instructions draw them directly to a particular frame. The DOM only knows the one canvas element; everything on it is only in memory. If you want to change your canvas elements you have to redraw the scene for the next frame.</p>
<p>The problem with this is of course that you can’t communicate directly with these non-material elements living in memory. You have to find a way to talk to them indirectly. This is where the D3 model comes in as well as custom or ‘virtual’ DOM-elements. What you’ll do in principal is:</p>
<ol>
<li>Bind your data to custom DOM elements. They don’t live in the DOM but only in memory (in a ‘virtual’ DOM) and describe the life-cycle of these elements in a known D3 way.</li>
<li>Use canvas to draw these elements.</li>
<li>Add interactivity with a technique called ‘picking’.</li>
</ol>
<p>Let’s do it.</p>
<h3 id="heading-the-data">The data</h3>
<p>Before we start to code, let’s produce some data. Let’s say you want 5,000 datapoints. So let’s create an array with 5,000 elements, each of which is an object with just a single property value carrying the element’s index. Here’s how you create it with <code>d3.range()</code>. <code>[d3.range()](https://github.com/d3/d3-array/blob/master/README.md#range)</code> is a D3 utility function, that creates an array based on its argument:</p>
<pre><code><span class="hljs-keyword">var</span> data = [];
</code></pre><pre><code>d3.range(<span class="hljs-number">5000</span>).forEach(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">el</span>) </span>{
</code></pre><pre><code>  data.push({ <span class="hljs-attr">value</span>: el });
</code></pre><pre><code>});
</code></pre><p>Here’s how the data looks in the console</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9KKliKgPxgMlDmp4MzZQQ5-RXRAvUVbUzkWm" alt="Image" width="177" height="317" loading="lazy"></p>
<p>Thrills!</p>
<h3 id="heading-the-canvas-container-and-its-tools">The canvas container and its tools</h3>
<p>The canvas element is an HTML element. It’s conceptually very much like any SVG-parent-element, which I at least usually add to a simple container div as in:</p>
<pre><code>&lt;div id=“container”&gt;&lt;/div&gt;
</code></pre><p>So, let’s add it to your container with D3 as in…</p>
<pre><code><span class="hljs-keyword">var</span> width = <span class="hljs-number">750</span>, height = <span class="hljs-number">400</span>;
</code></pre><pre><code><span class="hljs-keyword">var</span> canvas = d3.select(<span class="hljs-string">'#container'</span>)  .append(<span class="hljs-string">'canvas'</span>)  .attr(<span class="hljs-string">'width'</span>, width)  .attr(<span class="hljs-string">'height'</span>, height);
</code></pre><pre><code><span class="hljs-keyword">var</span> context = canvas.node().getContext(<span class="hljs-string">'2d'</span>);
</code></pre><p>You also need to add the context, which is the canvas toolbox. The context variable is from now on the object carrying all the properties and methods, the brushes and colours you need to draw on the canvas. Without the context, the canvas element would remain empty and white. That’s all you need to setup — a canvas and its tools…</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Qf47F2fKGkcjFa6czkWrFEllQvSVtzkgIOKh" alt="Image" width="800" height="400" loading="lazy">
_Base by Stilfehler — Own work, CC BY-SA 3.0, [https://creativecommons.org/licenses/by/2.0/](https://commons.wikimedia.org/w/index.php?curid=5899171" rel="noopener" target="_blank" title=""&gt;https://commons.wikimedia.org/w/index.php?curid=5899171; blue Lego by David Lofink, 2008 &lt;a href="https://creativecommons.org/licenses/by/2.0/" rel="noopener" target="<em>blank" title=")</em></p>
<h3 id="heading-the-html">The HTML</h3>
<p>…is simple. The main HTML structure of your site will be:</p>
<pre><code>&lt;!-- A title --&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Coloured grids<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span></span>
</code></pre><pre><code>&lt;!-- An input field <span class="hljs-keyword">with</span> a <span class="hljs-keyword">default</span> value. --&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"text-input"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"5000"</span>&gt;</span></span>
</code></pre><pre><code>&lt;!-- An explanation... --&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"text-explain"</span>&gt;</span>...takes numbers between 1 and 10k<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre><pre><code>&lt;!-- ...and a container <span class="hljs-keyword">for</span> the canvas element. --&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre><h3 id="heading-the-javascript-structure">The Javascript structure</h3>
<p>On a top level you only need 2 functions:</p>
<pre><code>databind(data) {
</code></pre><pre><code>  <span class="hljs-comment">// Bind data to custom elements.</span>
</code></pre><pre><code>}
</code></pre><pre><code>draw() {
</code></pre><pre><code>  <span class="hljs-comment">// Draw the elements on the canvas.</span>
</code></pre><pre><code>}
</code></pre><p>Pretty straight forward so far.</p>
<h3 id="heading-bind-the-elements">Bind the elements</h3>
<p>To bind data to the elements you first create a base element for all your custom elements you will produce and draw. If you know D3 well, think of it as a replacement to the SVG element:</p>
<pre><code><span class="hljs-keyword">var</span> customBase = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'custom'</span>);
</code></pre><pre><code><span class="hljs-keyword">var</span> custom = d3.select(customBase); <span class="hljs-comment">// This is your SVG replacement and the parent of all other elements</span>
</code></pre><p>Then you add some settings for your grid. In short, these settings allow you to draw a grid of squares. 100 squares build a ‘parcel’ and there is a line break after 10 parcels (or after 1,000 squares). You can adjust this for different ‘parceling’ of the squares or different line-breaking. Or just not worry about it. I suggest the latter…</p>
<pre><code><span class="hljs-comment">// Settings for a grid with 10 cells in a row, // 100 cells in a block and 1000 cells in a row.</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> groupSpacing = <span class="hljs-number">4</span>; <span class="hljs-keyword">var</span> cellSpacing = <span class="hljs-number">2</span>; <span class="hljs-keyword">var</span> offsetTop = height / <span class="hljs-number">5</span>; <span class="hljs-keyword">var</span> cellSize = <span class="hljs-built_in">Math</span>.floor((width - <span class="hljs-number">11</span> * groupSpacing) / <span class="hljs-number">100</span>) - cellSpacing;
</code></pre><p>Now let’s start the data-binding mission. Let’s get the necessities out of the way first and create a colour scale you will apply to your squares a little later.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">databind</span>(<span class="hljs-params">data</span>) </span>{
</code></pre><pre><code><span class="hljs-comment">// Get a scale for the colours - not essential but nice.</span>
</code></pre><pre><code>colourScale = d3.scaleSequential(d3.interpolateSpectral)                      .domain(d3.extent(data, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> d; }));
</code></pre><p>Now let’s join your data to the ‘replacement-SVG’ you called <code>custom</code> above and add yet non-existing custom elements with the class <code>.rect</code></p>
<pre><code><span class="hljs-keyword">var</span> join = custom.selectAll(<span class="hljs-string">'custom.rect'</span>)  .data(data);
</code></pre><p>You enter the custom elements (remember nothing enters the DOM, this is all in memory).</p>
<pre><code><span class="hljs-keyword">var</span> enterSel = join.enter()  .append(<span class="hljs-string">'custom'</span>)  .attr(<span class="hljs-string">'class'</span>, <span class="hljs-string">'rect'</span>)  .attr(<span class="hljs-string">"x"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d, i</span>) </span>{    <span class="hljs-keyword">var</span> x0 = <span class="hljs-built_in">Math</span>.floor(i / <span class="hljs-number">100</span>) % <span class="hljs-number">10</span>, x1 = <span class="hljs-built_in">Math</span>.floor(i % <span class="hljs-number">10</span>);         <span class="hljs-keyword">return</span> groupSpacing * x0 + (cellSpacing + cellSize) * (x1 + x0 * <span class="hljs-number">10</span>); })  .attr(<span class="hljs-string">"y"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d, i</span>) </span>{  <span class="hljs-keyword">var</span> y0 = <span class="hljs-built_in">Math</span>.floor(i / <span class="hljs-number">1000</span>), y1 = <span class="hljs-built_in">Math</span>.floor(i % <span class="hljs-number">100</span> / <span class="hljs-number">10</span>);   <span class="hljs-keyword">return</span> groupSpacing * y0 + (cellSpacing + cellSize) * (y1 + y0 * <span class="hljs-number">10</span>); })  .attr(<span class="hljs-string">'width'</span>, <span class="hljs-number">0</span>)  .attr(<span class="hljs-string">'height'</span>, <span class="hljs-number">0</span>);
</code></pre><p>When an element enters your model, you just give it an x and a y position as well as a width and a height of 0, which you’ll change in the upcoming update selection…</p>
<p>You merge the enter selection into the update selection and define all attributes for the update and enter selection. This includes a width and a height value as well as a colour from the colour scale you built earlier:</p>
<pre><code>join   .merge(enterSel)  .transition()  .attr(<span class="hljs-string">'width'</span>, cellSize)  .attr(<span class="hljs-string">'height'</span>, cellSize)  .attr(<span class="hljs-string">'fillStyle'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> colourScale(d); });
</code></pre><p>Two things of note about this last line. When you work with SVG this line would be</p>
<pre><code>.style(<span class="hljs-string">'color'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ <span class="hljs-keyword">return</span> colourScale(d); })
</code></pre><p>But with canvas you use <code>.attr()</code>. Why? Your main interest here is to find a pain-free way to transfer some element-specific information. Here you want to transfer a colour-string from the <code>databind()</code> to the <code>draw()</code> function. You use the element simply as a vessel to transport your data over to where it is being rendered to the canvas.</p>
<p>That's a very important distinction: when working with SVG or HTML you can bind data to elements and draw or apply styles to the elements in one step. In canvas you need two steps. First you bind the data then you draw the data. You can't style the elements while binding. They only exist in memory and canvas can't be styled via CSS style properties, which is exactly what you access when using <code>.style()</code>.</p>
<p>At first, this might seem limiting as you can do less in one step, but it’s conceptually almost cleaner and also gives you some freedom. <code>.attr()</code> allows us to send any key-value pairs on the journey. You could use other methods like the HTML <code>.dataset</code> property for example, but <code>.attr()</code> will do just fine.</p>
<p>Notice we don't say <code>color</code> but <code>fillStyle</code>. To be honest, you could use <code>color</code> or you could use <code>chooChooTrain</code> here. You would only need to remember this when you fetch the information later during drawing. However, as canvas uses a property called <code>fillStyle</code> to style elements, it seems more appropriate in this case.</p>
<p>Finally, you also define the exit selection, deciding what should happen to exiting elements.</p>
<pre><code><span class="hljs-keyword">var</span> exitSel = join.exit()  .transition()  .attr(<span class="hljs-string">'width'</span>, <span class="hljs-number">0</span>)  .attr(<span class="hljs-string">'height'</span>, <span class="hljs-number">0</span>)  .remove();
</code></pre><p>That’s it! You can close your <code>databind()</code> function and move on...</p>
<pre><code>} <span class="hljs-comment">// databind()</span>
</code></pre><p>This is not really scary coming from D3 as it’s pretty much exactly the same. You have now successfully created your data model, the way the application will think about data. Each element will get the properties it needs to be drawn via the <code>.attr()</code> functions and each element will be assigned a life-cycle state depending on the injected data. Our standard D3 model.</p>
<h3 id="heading-drawing-the-elements">Drawing the elements</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ZaCpM7PV8TG1tI1LzZ4n5d6bsxNiBQNxDDYk" alt="Image" width="800" height="530" loading="lazy">
_By Kristina Alexanderson, 2011 [https://creativecommons.org/licenses/by-nc-nd/2.0/](https://creativecommons.org/licenses/by-nc-nd/2.0/" rel="noopener" target="<em>blank" title=")</em></p>
<p>Now you need to write the draw function to get the elements on screen. Let’s just note here that nothing has happened yet. You haven’t called <code>databind()</code> yet because you need to find a way to draw it to the canvas first. So here we go... The <code>draw()</code> function doesn't need to take any arguments in this case:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">draw</span>(<span class="hljs-params"></span>) </span>{
</code></pre><p>As mentioned fleetingly above, you need to take care of cleaning the canvas every time you draw afresh. The DOM is material, in that when you draw a rect-element on it and you change its x value, it will move in the x-direction and the DOM will take care of this move (or the re-paint) automatically.</p>
<p>If you move a rect from x = 0 to x = 1 at a certain point in time (after a button press for example) the browser will move the rect from 0 to 1 within one tick or frame-paint (which is roughly 16ms long). If you move it from 0 to 10, it will do so in a time depending on the duration you asked this transition to happen, maybe 1 pixel per tick maybe 8 pixel per tick (for more read <a target="_blank" href="https://www.html5rocks.com/en/tutorials/speed/unnecessary-paints/">this</a> blog post).</p>
<p>But it will tell the pixel at 0 that the rect has disappeared and the pixel at 1 that there is a rect now. Canvas doesn’t do this. You need to tell canvas what to paint, and if you paint something new, you need to tell it to remove the previous paint.</p>
<p>So let’s start with cleaning up anything that might be on the canvas before you draw. Here’s how:</p>
<pre><code>context.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, width, height); <span class="hljs-comment">// Clear the canvas.</span>
</code></pre><p>Simple.</p>
<p>Now you…</p>
<ol>
<li>…get hold of all elements in order to</li>
<li>loop through all elements and</li>
<li>take the information you have stored in the <code>databind()</code> function to draw the element:</li>
</ol>
<pre><code><span class="hljs-comment">// Draw each individual custom element with their properties.</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> elements = custom.selectAll(<span class="hljs-string">'custom.rect'</span>);<span class="hljs-comment">// Grab all elements you bound data to in the databind() function.</span>
</code></pre><pre><code>elements.each(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d,i</span>) </span>{ <span class="hljs-comment">// For each virtual/custom element...</span>
</code></pre><pre><code>  <span class="hljs-keyword">var</span> node = d3.select(<span class="hljs-built_in">this</span>);   <span class="hljs-comment">// This is each individual element in the loop.     context.fillStyle = node.attr('fillStyle');   // Here you retrieve the colour from the individual in-memory node and set the fillStyle for the canvas paint</span>
</code></pre><pre><code>  context.fillRect(node.attr(<span class="hljs-string">'x'</span>), node.attr(<span class="hljs-string">'y'</span>), node.attr(<span class="hljs-string">'width'</span>), node.attr(<span class="hljs-string">'height'</span>));  <span class="hljs-comment">// Here you retrieve the position of the node and apply it to the fillRect context function which will fill and paint the square.</span>
</code></pre><pre><code>}); <span class="hljs-comment">// Loop through each element.</span>
</code></pre><p>And that’s it! You can close the <code>draw()</code> function</p>
<pre><code>} <span class="hljs-comment">// draw()</span>
</code></pre><p>When I started with canvas after a while of wanting to dive into it, this simplicity really upped my spirits.</p>
<p>However, nothing has happened in the browser yet. We have the tools in the <code>databind()</code> and the <code>draw()</code> function, but nothing has been drawn yet. How do you do this? If you just wanted to draw a static visual or image, you just call:</p>
<pre><code>databind(data);
</code></pre><pre><code>draw();
</code></pre><p>This would bind the data to the custom elements, which would live in memory and then draw it — once!</p>
<p>But you have transitions. Remember above: when you wrote the <code>databind()</code> function you transitioned the cell width and height from 0 to their size as well as the colour from black (the default) to the respective element’s colour. A default D3 transition lasts 250 milliseconds, so you need to redraw the squares many times in these 250 ms in order to get a smooth transition. How do you do this?</p>
<p>It’s again simple. You just call <code>databind(data)</code> to create our custom elements before you repeatedly call <code>draw()</code> for as long as it takes the transition to run. So in our case at least 250 ms. You could use <code>setInterval()</code> for this but we really should use <code>requestAnimationFrame()</code> in order to be as performant as possible (for more <a target="_blank" href="https://css-tricks.com/using-requestanimationframe/">read this</a>). There are a few ways to use it, but keeping within the D3 spirit, I suggest using <code>d3.timer()</code> which implements <code>requestAnimationFrame()</code> as well as being straight forward to use. So here we go:</p>
<pre><code><span class="hljs-comment">// === First call === //</span>
</code></pre><pre><code>databind(d3.range(value)); <span class="hljs-comment">// Build the custom elements in memory.</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> t = d3.timer(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">elapsed</span>) </span>{
</code></pre><pre><code>  draw();
</code></pre><pre><code>  <span class="hljs-keyword">if</span> (elapsed &gt; <span class="hljs-number">300</span>) t.stop();
</code></pre><pre><code>}); <span class="hljs-comment">// Timer running the draw function repeatedly for 300 ms.</span>
</code></pre><p><code>d3.timer()</code> calls the callback repeatedly until <code>elapsed</code> (which is the passed time in milliseconds from instantiation) is past 300 and then the timer is stopped. In these 300 milliseconds, it runs the <code>draw()</code> at each tick (roughly each 16ms). <code>draw()</code> then looks at each element's attributes and draws them accordingly.</p>
<p>This is how a transition works in canvas. You call the drawing function right after the binding function many times. Whatever your D3-model is set up to transition (positions, colours, sizes) will be re-drawn many times with small incremental changes for each draw</p>
<p>Note that <code>draw()</code> needs to come right after the <code>databind()</code> function. You couldn't ask the machine to run <code>databind()</code>, then do something else for a second and then call <code>draw()</code>. Because after 1 second the transitioned states calculated by your <code>databind()</code> function have all transitioned already. Done, dusted and forgotten.</p>
<p>That’s it! You’ve bound data to custom elements and you’ve drawn it to the canvas.</p>
<h4 id="heading-let-the-user-update-the-number-of-squares">Let the user update the number of squares</h4>
<p>To give the user the chance to repeat this feat with a custom number of elements (ok, semi-custom with a maximum of 10,000) you add the following listener and handler to your text-input box:</p>
<pre><code><span class="hljs-comment">// === Listeners/handlers === //</span>
</code></pre><pre><code>d3.select(<span class="hljs-string">'#text-input'</span>).on(<span class="hljs-string">'keydown'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
</code></pre><pre><code><span class="hljs-keyword">if</span> (d3.event.keyCode === <span class="hljs-number">13</span>) { <span class="hljs-comment">// Only do something if the user hits return (keycode 13).</span>
</code></pre><pre><code>  <span class="hljs-keyword">if</span> (+<span class="hljs-built_in">this</span>.value &lt; <span class="hljs-number">1</span> || +<span class="hljs-built_in">this</span>.value &gt; <span class="hljs-number">10000</span>) {   <span class="hljs-comment">// If the user goes lower than 1 or higher than 10k...         d3.select('#text-explain').classed('alert', true);     // ... highlight the note about the range and return.</span>
</code></pre><pre><code>    <span class="hljs-keyword">return</span>;
</code></pre><pre><code>  } <span class="hljs-keyword">else</span> {   <span class="hljs-comment">// If the user types in a sensible number...</span>
</code></pre><pre><code>    d3.select(<span class="hljs-string">'#text-explain'</span>).classed(<span class="hljs-string">'alert'</span>, <span class="hljs-literal">false</span>);     <span class="hljs-comment">// ...remove potential alert colours from the note...</span>
</code></pre><pre><code>    value = +<span class="hljs-built_in">this</span>.value; <span class="hljs-comment">// ...set the value...</span>
</code></pre><pre><code>    databind(d3.range(value)); <span class="hljs-comment">// ...and bind the data.</span>
</code></pre><pre><code>    <span class="hljs-keyword">var</span> t = d3.timer(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">elapsed</span>) </span>{
</code></pre><pre><code>      draw();        <span class="hljs-keyword">if</span> (elapsed &gt; <span class="hljs-number">300</span>) t.stop();
</code></pre><pre><code>    }); <span class="hljs-comment">// Timer running the draw function repeatedly for 300 ms.     } // If user hits return.</span>
</code></pre><pre><code>}); <span class="hljs-comment">// Text input listener/handler</span>
</code></pre><p>Here it is again, our colourful grid of canvas squares, ready to be updated and redrawn:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-FueZaUWkrLNINguKlHuQ1P6YMLlzz4B4QkQ" alt="Image" width="769" height="486" loading="lazy"></p>
<h3 id="heading-interactivity">Interactivity</h3>
<p>The biggest ‘pain’ with canvas in comparison to SVG or HTML is that there are no material elements living in the DOM. If there were you could just register listeners to the elements and add handlers to the listeners. For example you can trigger a mouse-over on an SVG <code>rect</code> element and whenever the listener triggers, you could do something to the rect. Like showing data values stored with the <code>rect</code> in a tooltip.</p>
<p>With canvas you have to find another way to make an event heard on our canvas elements. Luckily there are a number of clever people who thought of an indirect but logical way.</p>
<p>So what interactivity do we want? As said above let’s go for a tooltip and let’s assume you want to show the index of the square in a tooltip as soon as you hover over the element. Not very thrilling, but the key is that you can access the data bound to the element by hovering over it.</p>
<h4 id="heading-picking">Picking</h4>
<p>There are a few steps involved (all logical though). But in short you will build two canvases to achieve this. One <strong>main canvas</strong> that produces our visual and one <strong>hidden canvas</strong> (as in we can’t see it) that produces the same visual. The key here is that all elements on the second canvas will be at the exact same position in relation to the canvas origin compared to the first canvas. So square 1 starts on 0,0 on the main canvas as well as on the hidden canvas. Square 2 starts on 8,0 on the main canvas as well as on the hidden canvas and so on.</p>
<p>There is only one important difference. Each element on the hidden canvas will get a unique colour. We will create an object (or rather an <a target="_blank" href="https://en.wikipedia.org/wiki/Associative_array">associative array</a> or <em>map</em> for brevity) that links each unique colour to each element’s data.</p>
<p>Why? Because next we attach a mouse-move listener to the main-canvas to retrieve a stream of mouse-positions. At each mouse-position we can use a canvas-own method to “pick” the colour at this exact position. Then we just look up the colour in our associative array and we have the data ! And we’re flying…</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/19HOxzrPQbTQEcdVlJxpnid99YSrjfbozdxy" alt="Image" width="640" height="425" loading="lazy">
_By Kenny Louie, 2010 [https://creativecommons.org/licenses/by/2.0/](https://creativecommons.org/licenses/by/2.0/" rel="noopener" target="<em>blank" title=")</em></p>
<p>You could say “well, my squares have already got a unique colour, I can use those?” And indeed, you could use them. However, your interactivity would go out of the window as soon as you decide to bereft your squares from the colours. So you should make sure to always have one canvas — the hidden canvas — that has a guaranteed set of unique colours for the squares.</p>
<p>Let’s apply this technique step by step. The code you’ve built so far can stay as it is — you just add to it as you go along.</p>
<h4 id="heading-1-prepare-the-hidden-canvas">1. Prepare the hidden canvas</h4>
<p>First let’s create the hidden canvas that will harbour our visual with a unique colour per square.</p>
<p>1.1 Create hidden canvas element and set its CSS to <code>{ display: none; }</code>.</p>
<pre><code><span class="hljs-comment">// Rename the main canvas and add a 'mainCanvas' class to it.</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> mainCanvas = d3.select(<span class="hljs-string">'#container'</span>)  .append(<span class="hljs-string">'canvas'</span>)  .classed(<span class="hljs-string">'mainCanvas'</span>, <span class="hljs-literal">true</span>)  .attr(<span class="hljs-string">'width'</span>, width) .attr(<span class="hljs-string">'height'</span>, height); <span class="hljs-comment">// new -----------------------------------</span>
</code></pre><pre><code><span class="hljs-comment">// Add the hidden canvas and give it the 'hiddenCanvas' class.</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> hiddenCanvas = d3.select(<span class="hljs-string">'#container'</span>)  .append(<span class="hljs-string">'canvas'</span>)  .classed(<span class="hljs-string">'hiddenCanvas'</span>, <span class="hljs-literal">true</span>)   .attr(<span class="hljs-string">'width'</span>, width)   .attr(<span class="hljs-string">'height'</span>, height);
</code></pre><p>In fact, I won’t set the canvas to hidden in this example to show what is going on. But to do so, just add <code>.hiddenCanvas { display: none; }</code> to your CSS and the deed is done.</p>
<p>1.2 Build the context variable in the <code>draw()</code> function and pass two arguments to the function: the canvas as well as a boolean called 'hidden' determining which canvas we build (hidden = true || false) as in:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">draw</span>(<span class="hljs-params">canvas, hidden</span>) </span>{
</code></pre><p>1.3 You now need to adapt all draw functions to include the two new <code>draw()</code> arguments. So from now on, you don't just call <code>draw()</code> you call either <code>draw(mainCanvas, false)</code> or <code>draw(hiddenCanvas, true)</code></p>
<h4 id="heading-2-apply-unique-colours-to-the-hidden-elements-and-map-them">2. Apply unique colours to the hidden elements and map them</h4>
<p>Here, dear reader, comes the key part of our operation, the engine of our truck, the spice in our soup.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/DOlN5RCi8jbLQTNI821trNukfFg4PVtBjiHC" alt="Image" width="800" height="600" loading="lazy">
_By Andrew Becraft, 2007 [https://creativecommons.org/licenses/by-nc-sa/2.0/](https://creativecommons.org/licenses/by-nc-sa/2.0/" rel="noopener" target="<em>blank" title=")</em></p>
<p>2.1 Include a function to generate a new unique colour every time it gets called (via <a target="_blank" href="http://stackoverflow.com/a/15804183">Stack Overflow</a>)</p>
<pre><code><span class="hljs-comment">// Function to create new colours for the picking.</span>
</code></pre><pre><code><span class="hljs-keyword">var</span> nextCol = <span class="hljs-number">1</span>;
</code></pre><pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">genColor</span>(<span class="hljs-params"></span>)</span>{     <span class="hljs-keyword">var</span> ret = [];
</code></pre><pre><code>  <span class="hljs-keyword">if</span>(nextCol &lt; <span class="hljs-number">16777215</span>){         ret.push(nextCol &amp; <span class="hljs-number">0xff</span>); <span class="hljs-comment">// R     ret.push((nextCol &amp; 0xff00) &gt;&gt; 8); // G     ret.push((nextCol &amp; 0xff0000) &gt;;&gt; 16); // B</span>
</code></pre><pre><code>    nextCol += <span class="hljs-number">1</span>;     }
</code></pre><pre><code><span class="hljs-keyword">var</span> col = <span class="hljs-string">"rgb("</span> + ret.join(<span class="hljs-string">','</span>) + <span class="hljs-string">")"</span>;
</code></pre><pre><code><span class="hljs-keyword">return</span> col;
</code></pre><pre><code>}
</code></pre><p><code>genColour()</code> produces a colour defining string in the form rgb(0,0,0). Every time it's called it increments the R value by one. Once it reaches 255, it increments the G value by 1 and resets the R value to 0. Once it reaches r(255,255,0) it increments the B value by 1 resetting the R and the G to 0 and so on.</p>
<p>So in total you can have 256<em>256</em>256 = 16.777.216 elements to retain a unique colour. However, I can assure you your browser will die beforehand. Even with canvas (webGL tutorial to follow).</p>
<p>2.2 Create the map-object that will keep track of which custom element has which unique colour:</p>
<pre><code><span class="hljs-keyword">var</span> colourToNode = {}; <span class="hljs-comment">// Map to track the colour of nodes.</span>
</code></pre><p>You can add the <code>genColour()</code> function wherever you want in your script, as long as it's outside the <code>databind()</code> and <code>draw()</code> function scope. But note that your map variable needs to be created before and beyond the scope of the <code>databind()</code> function.</p>
<p>2.3 Add a a unique colour to each custom element as for example <code>.attr('fillStyleHidden')</code> and<br>2.4 build the map-object during element creation</p>
<p>Here you’ll use your ‘colour-canon’ <code>genColour()</code> in our <code>databind()</code> function when assigning the <code>fillStyle</code> to our elements. As you also have access to each datapoint while it's being bound to each element, you can bring colour and data together in your <code>colourToNode</code> map.</p>
<pre><code>join   .merge(enterSel)   .transition()   .attr(<span class="hljs-string">'width'</span>, cellSize)   .attr(<span class="hljs-string">'height'</span>, cellSize)   .attr(<span class="hljs-string">'fillStyle'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{     <span class="hljs-keyword">return</span> colorScale(d.value);   });
</code></pre><pre><code>  <span class="hljs-comment">// new -----------------------------------------------------         .attr('fillStyleHidden', function(d) {</span>
</code></pre><pre><code>    <span class="hljs-keyword">if</span> (!d.hiddenCol) {
</code></pre><pre><code>      d.hiddenCol = genColor();       colourToNode[d.hiddenCol] = d;
</code></pre><pre><code>    }
</code></pre><pre><code>    <span class="hljs-comment">// Here you (1) add a unique colour as property to each element     // and(2) map the colour to the node in the colourToNode-map.</span>
</code></pre><pre><code>    <span class="hljs-keyword">return</span> d.hiddenCol;
</code></pre><pre><code>});
</code></pre><p>2.5 You can now colour the elements according to the canvas the <code>draw()</code> function is rendering. You add a conditional on the <code>fillStyle</code> in the <code>draw()</code> function applying the colours for our visual to the main canvas and the unique colours to the hidden canvas. It's a simple one-liner:</p>
<pre><code>context.fillStyle = hidden ? node.attr(<span class="hljs-string">'fillStyleHidden'</span>) : node.attr(<span class="hljs-string">'fillStyle'</span>);
</code></pre><pre><code><span class="hljs-comment">// The node colour depends on the canvas you draw.</span>
</code></pre><p>The main canvas still looks the same of course:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iiJNAhyR0ReK2tU1aoHuRjnODkWsgr83906J" alt="Image" width="769" height="486" loading="lazy"></p>
<p>Let’s finally add some interactivity and start with drawing the hidden canvas whenever we move the mouse onto our main canvas.</p>
<h4 id="heading-3-pick-up-the-colours-with-the-mouse">3. Pick up the colours with the mouse</h4>
<p>3.1 First, simply register a listener to the main canvas, listening to mouse-move events.</p>
<pre><code>d3.select(<span class="hljs-string">'.mainCanvas'</span>).on(<span class="hljs-string">'mousemove'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
</code></pre><pre><code>});
</code></pre><p>Why mousemove? As you can’t register listeners with individual squares but have to use the entire canvas you won’t be able to work with mouseover or -out events as they will only trigger when entering the canvas not the elements. In order to get the mouse position on your canvas you can do mousemove or click/mousedown.</p>
<pre><code>d3.select(<span class="hljs-string">'.mainCanvas'</span>).on(<span class="hljs-string">'mousemove'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
</code></pre><pre><code>  draw(hiddenCanvas, <span class="hljs-literal">true</span>); <span class="hljs-comment">// Draw the hidden canvas.</span>
</code></pre><pre><code>});
</code></pre><p>This way, the first thing our user triggers when mousing over the main canvas is to unknowingly create the hidden canvas. As said, in production this canvas would be hidden, but for our educational purposes we want to see it and indeed, trigger the hidden canvas to be drawn when the mouse moves over the main canvas like so:</p>
<p>The colours on the main canvas range from black to red, from rgb(0,0,0) to rgb(255,0,0) and then it looks as if the same range from black to red is repeated. However, now the colour ranges from a slightly greener black, precisely from rgb(0,1,0) to rgb(255,1,0):</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/jypEjz7sRIAVtg1uf7YLNbza2ban7FkvAYKF" alt="Image" width="765" height="411" loading="lazy"></p>
<p>Zooming into the first couple of hundred squares, here are the colours of the first, the 256th and the 257th square:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/R3tNkcWdwboHcnNxeyNNlw3gV42GoMErCHSu" alt="Image" width="400" height="200" loading="lazy"></p>
<p>3.3 As our hidden canvas is structurally a carbon copy of our main canvas, all the hidden canvas elements will be at the same position as the elements on our main canvas. So, you can now use the mouse’s x and y positions you are collecting from the listener on the main canvas to establish the same location on the hidden canvas. Back in the listener, you add:</p>
<pre><code>d3.select(<span class="hljs-string">'.mainCanvas'</span>).on(<span class="hljs-string">'mousemove'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{       <span class="hljs-comment">// Draw the hidden canvas.  draw(hiddenCanvas, true);</span>
</code></pre><pre><code>  <span class="hljs-comment">// Get mouse positions from the main canvas.  var mouseX = d3.event.layerX || d3.event.offsetX;   var mouseY = d3.event.layerY || d3.event.offsetY; });</span>
</code></pre><p>Note here we take the <code>event.layerX</code> and <code>event.layerY</code> properties which return the mouse position including scrolling. <a target="_blank" href="https://developer.mozilla.org/en/docs/Youb/API/UIEvent/layerX">This can break</a> so use offsetX as a fallback (or just use offsetX).</p>
<p>3.4 The picking: Canvas greatly allows access to the pixel-data the mouse is hovering over with the <code>getImageData()</code> function and its <code>.data</code> property. In full bloom this will look like:</p>
<p><code>getImageData(posX, posY, 1, 1).data</code> .</p>
<p>It will return an array with four numbers: the R, the G, the B and the alpha value. As you diligently built the <code>colourToNode</code> map assigning the element data to each of its hidden colours, you can now access this element's data simply by looking up the colour in the map!</p>
<pre><code>d3.select(<span class="hljs-string">'.mainCanvas'</span>).on(<span class="hljs-string">'mousemove'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
</code></pre><pre><code>  <span class="hljs-comment">// Draw the hidden canvas.  draw(hiddenCanvas, true);</span>
</code></pre><pre><code>  <span class="hljs-comment">// Get mouse positions from the main canvas.  var mouseX = d3.event.layerX || d3.event.offsetX;   var mouseY = d3.event.layerY || d3.event.offsetY;</span>
</code></pre><pre><code><span class="hljs-comment">// new -----------------------------------------------</span>
</code></pre><pre><code>  <span class="hljs-comment">// Get the toolbox for the hidden canvas.  var hiddenCtx = hiddenCanvas.node().getContext('2d');</span>
</code></pre><pre><code>  <span class="hljs-comment">// Pick the colour from the mouse position.   var col = hiddenCtx.getImageData(mouseX, mouseY, 1, 1).data;</span>
</code></pre><pre><code>  <span class="hljs-comment">// Then stringify the values in a way our map-object can read it.  var colKey = 'rgb(' + col[0] + ',' + col[1] + ',' + col[2] + ')';</span>
</code></pre><pre><code>  <span class="hljs-comment">// Get the data from our map!   var nodeData = colourToNode[colKey];</span>
</code></pre><pre><code>  <span class="hljs-built_in">console</span>.log(nodeData);
</code></pre><pre><code>});
</code></pre><p>And indeed, logging the <code>nodeData</code> to the console returns an object every time you hover over a square:</p>
<p>The data per node now shows the <code>value</code> which constitutes the original data as well as the key <code>hiddenCol</code> showing this node's colour for the hidden canvas:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ldW0tKW2CWZY5oMgBqQIDknGQ60lLb9eK3Iq" alt="Image" width="227" height="72" loading="lazy"></p>
<p>3.5 Finally — and that’s a formality — you add the tooltip</p>
<pre><code>d3.select(<span class="hljs-string">'.mainCanvas'</span>).on(<span class="hljs-string">'mousemove'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
</code></pre><pre><code>  <span class="hljs-comment">// Draw the hidden canvas.  draw(hiddenCanvas, true);</span>
</code></pre><pre><code>  <span class="hljs-comment">// Get mouse positions from the main canvas.  var mouseX = d3.event.layerX || d3.event.offsetX;   var mouseY = d3.event.layerY || d3.event.offsetY;</span>
</code></pre><pre><code>  <span class="hljs-comment">// Get the toolbox for the hidden canvas.  var hiddenCtx = hiddenCanvas.node().getContext('2d');</span>
</code></pre><pre><code>  <span class="hljs-comment">// Pick the colour from the mouse position.   var col = hiddenCtx.getImageData(mouseX, mouseY, 1, 1).data;</span>
</code></pre><pre><code>  <span class="hljs-comment">// Then stringify the values in a way our map-object can read it.  var colKey = 'rgb(' + col[0] + ',' + col[1] + ',' + col[2] + ')';</span>
</code></pre><pre><code>  <span class="hljs-comment">// Get the data from our map!   var nodeData = colourToNode[colKey];     console.log(nodeData);</span>
</code></pre><pre><code>  <span class="hljs-comment">// new -----------------------------------------------</span>
</code></pre><pre><code>  <span class="hljs-keyword">if</span> (nodeData) {   <span class="hljs-comment">// Show the tooltip only when there is nodeData found by the mouse</span>
</code></pre><pre><code>    d3.select(<span class="hljs-string">'#tooltip'</span>)       .style(<span class="hljs-string">'opacity'</span>, <span class="hljs-number">0.8</span>)       .style(<span class="hljs-string">'top'</span>, d3.event.pageY + <span class="hljs-number">5</span> + <span class="hljs-string">'px'</span>)       .style(<span class="hljs-string">'left'</span>, d3.event.pageX + <span class="hljs-number">5</span> + <span class="hljs-string">'px'</span>)         .html(nodeData.value);
</code></pre><pre><code>  } <span class="hljs-keyword">else</span> {   <span class="hljs-comment">// Hide the tooltip when the mouse doesn't find nodeData.      d3.select('#tooltip').style('opacity', 0);     }</span>
</code></pre><pre><code>}); <span class="hljs-comment">// canvas listener/handler</span>
</code></pre><p>That’s it! You’ve visualised a large number of elements on canvas — more than you would’ve been able to enjoy problem-free with SVG. You still used D3’s lifecycle model and you added some interactivity to access the data attached to each element. These three steps should enable you to do pretty much anything or at least more than what you’re used to when working with D3 and SVG.</p>
<p>There’s a <a target="_blank" href="http://www.datamake.io/blog/d3-canvas-full#manual">step-by-step manual</a> from scratch to interactive D3/canvas on my blog which allows internal page links. This way you can see the whole process in one view and click your way through it with ease:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/WFMyJnhsCus25iIwedpkhmFOyR5GhIDK-1Pk" alt="Image" width="500" height="700" loading="lazy">
<em>Click to get to the manual</em></p>
<p>…and <a target="_blank" href="http://blockbuilder.org/larsvers/6049de0bcfa50f95d3dcbf1e3e44ad48">here’s the full code again</a>.</p>
<p>I hope you enjoyed reading this and please do say <a target="_blank" href="http://www.datamake.io/contact">hello</a> and/or …</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/U2X4aQqHtu8wQ4tmHtx31iS1aTNRabBRO2h5" alt="Image" width="400" height="183" loading="lazy"></p>
<p>_lars verspohl <a target="_blank" href="http://www.datamake.io">www.datamake.io</a> @lars<em>vers <a target="_blank" href="https://www.linkedin.com/in/larsverspohl">https://www.linkedin.com/in/larsverspohl</a></em></p>
<p><em>…is always grateful for a like? or a follow he can return.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ One year in the Free Code Camp Data Science Room ]]>
                </title>
                <description>
                    <![CDATA[ By Evaristo Caraballo I joined Free Code Camp’s community 18 months ago as a data scientist who was curious about web development. I quickly discovered that not only did they take data science seriously — they already had plans to release their datas... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/one-year-experience-in-the-free-code-camp-data-science-room-c97eb905af1f/</link>
                <guid isPermaLink="false">66c35c43e9895571912a0cea</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ open data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Social Media Analytics ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 21 Aug 2016 23:38:06 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*ef3sgKjwAFm2tAnfgL7_hg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Evaristo Caraballo</p>
<p>I joined Free Code Camp’s community 18 months ago as a data scientist who was curious about web development. I quickly discovered that not only did they take data science seriously — they already had plans to release their datasets to the public as open data.</p>
<p>After some discussion, <a target="_blank" href="https://www.freecodecamp.org/news/one-year-experience-in-the-free-code-camp-data-science-room-c97eb905af1f/undefined">Quincy Larson</a> promoted me to Free Code Camp’s core team and gave me the green light to create the <a target="_blank" href="https://gitter.im/FreeCodeCamp/DataScience">Data Science Room</a>. This would serve as an official chat room for discussing data science, data visualization, and open data.</p>
<p>All of this happened at the end of July 2015 — just over one year ago.</p>
<p>Since that time, my experience in the Data Science Room has been rich and motivating. As of August 2016, the Data Science Room is composed of more than 700 moderately active users. Its logs contains a wealth of useful resources. And many of its participants have built projects involving real Free Code Camp data.</p>
<p>This article is a brief overview of some of the more interesting developments over the past year in our Data Science Room.</p>
<h3 id="heading-the-open-data-vision">The Open Data Vision</h3>
<p>The first message in our Data Science Room came from <a target="_blank" href="https://www.freecodecamp.org/news/one-year-experience-in-the-free-code-camp-data-science-room-c97eb905af1f/undefined">Quincy Larson</a>, who summarized Free Code Camp’s interest in Open Data as natural extension of the Open Source movement:</p>
<blockquote>
<p>“Our near-term plans are to open up our entire anonymized dataset for academic study.” - <a target="_blank" href="https://www.freecodecamp.org/news/one-year-experience-in-the-free-code-camp-data-science-room-c97eb905af1f/undefined">Quincy Larson</a> in July 2015</p>
</blockquote>
<p>Six month later, Free Code Camp conducted its first open data experiment by releasing a large open dataset containing the progress of more than 100,000 campers who’d opted in, on Christmas Eve:</p>
<p><a target="_blank" href="https://medium.freecodecamp.com/free-code-camp-christmas-special-giving-the-gift-of-data-6ecbf0313d62"><strong>Free Code Camp Christmas Special: Giving the Gift of Open Data</strong></a><br><a target="_blank" href="https://medium.freecodecamp.com/free-code-camp-christmas-special-giving-the-gift-of-data-6ecbf0313d62">_To the countless researchers and data scientists who have politely asked for our data over the past few months: Merry…_medium.freecodecamp.com</a></p>
<p>Then a few months later, the Data Science Room released survey results from the 2016 New Coder Survey. This included data from 15,000 respondents, each of whom answered up to 48 questions:</p>
<p><a target="_blank" href="https://medium.freecodecamp.com/we-asked-15-000-people-who-they-are-and-how-theyre-learning-to-code-4104e29b2781"><strong>We asked 15,000 people who they are, and how they’re learning to code</strong></a><br><a target="_blank" href="https://medium.freecodecamp.com/we-asked-15-000-people-who-they-are-and-how-theyre-learning-to-code-4104e29b2781">_More than 15,000 people responded to the 2016 New Coder Survey, granting researchers an unprecedented glimpse into how…_medium.freecodecamp.com</a></p>
<p>The results of the survey are currently one of the most popular datasets on <a target="_blank" href="https://www.kaggle.com/forums/f/1318/2016-new-coder-survey">Kaggle</a>, and are also available in raw and normalized form on <a target="_blank" href="https://github.com/FreeCodeCamp/2016-new-coder-survey">GitHub</a>.</p>
<p>Members of our Data Science Room have also joined in on the data analysis, focusing their energies on datasets generated from the many platforms used by the Free Code Camp community.</p>
<h3 id="heading-gitter-chat-rooms">Gitter chat rooms</h3>
<p>Gitter has been a core social hub for Free Code Camp since the beginning, barring a short “Slack interlude”:</p>
<p><a target="_blank" href="https://medium.freecodecamp.com/so-yeah-we-tried-slack-and-we-deeply-regretted-it-391bcc714c81"><strong>So Yeah We Tried Slack… and We Deeply Regretted It</strong></a><br><a target="_blank" href="https://medium.freecodecamp.com/so-yeah-we-tried-slack-and-we-deeply-regretted-it-391bcc714c81">_Back in April, all was well with our community of busy adults learning to code. We were communicating using Gitter.im…_medium.freecodecamp.com</a></p>
<p>Gitter chat rooms have been the main venue for welcoming new campers, asking for programming help, and coordinating contributions to open source projects. And Gitter has become quite popular.</p>
<blockquote>
<p>There were close to 2,000,000 messages posted in the Free Code Camp main chat room alone between January 1, 2015 and May 31, 2016.</p>
</blockquote>
<p>Between all the Free Code Camp chat rooms, the main one (<a target="_blank" href="https://www.gitter.im/freecodecamp/freecodecamp">FreeCodeCamp/FreeCodeCamp</a>) is the most popular. It bottoms out at around 1 message per minute, and jumps to <em>6–9 messages per minute</em> during peak time.</p>
<h3 id="heading-a-community-driven-effort-to-help-newcomers">A community-driven effort to help newcomers.</h3>
<p>Since Free Code Camp is a volunteer-driven open source community, a big part of its success depends upon campers who are willing to share their time and expertise. Our community is designed to keep that engine of helpfulness always running.</p>
<p>Every month, hundreds of campers are able to land their first developer jobs, and as a result become less active in chat. But new generations of campers rise up to fill the gap they leave behind. That’s how the community sustains itself.</p>
<p>When one camper helps another, they are rewarded by “brownie points” within Free Code Camp’s platform. Want to see which campers have been the most helpful lately? Check out the unofficial Free Code Camp <a target="_blank" href="https://fcctop100.herokuapp.com/">top 100 leaderboard</a> (built by <a target="_blank" href="https://github.com/roelver">Roel Verbunt</a> using in React, MongoDB, and node.js).</p>
<h3 id="heading-local-study-groups">Local study groups</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*p6poZi8CySNa-m8wFT75sA.jpeg" alt="Image" width="800" height="600" loading="lazy">
<em>Free Code Camp Mexico City.</em></p>
<p>Campers also meet in-person through Free Code Camp’s 1,500+ local <a target="_blank" href="https://medium.freecodecamp.com/free-code-camps-1-000-study-groups-are-now-fully-autonomous-d40a3660e292#.vidk0bnns"><strong>study groups</strong></a>.</p>
<p>These groups organize events through Facebook groups. The average group has 40 campers, and major cities like San Francisco, London, Toronto, and Delhi have more than 1,000 members each.</p>
<p><a target="_blank" href="https://github.com/alicejiang1">Alice Jiang</a>, <a target="_blank" href="https://github.com/samosale">Aleksandar B</a>, and myself ran an analysis and found that around 45% of registered study groups had future events scheduled.</p>
<p>Here are some other community statistics:</p>
<ul>
<li>By July 2016 there were at least 430 people who have made at least one commit to Free Code Camps’ <a target="_blank" href="https://github.com/freecodecamp/freecodecamp">core open source repository</a></li>
<li>Free Code Camp has the <a target="_blank" href="http://toppub.xyz/">13th most popular</a> publication on Medium</li>
<li>Our <a target="_blank" href="https://www.youtube.com/freecodecamp">YouTube</a> channel has more than 40,000 followers</li>
<li>We recently introduced a forum, which now has more than 30,000 users and 1,000 visitors per day.</li>
</ul>
<p>I also analyzed the words in Free Code Camp’s 222 most recent tweets:</p>
<blockquote>
<p>(‘code’, 44),<br> (‘freecodecamp’, 40),<br> (‘time’, 35),<br> (‘design’, 28),<br> (‘make’, 24),<br> (‘medium’, 24),<br> (‘trying’, 21),<br> (‘write’, 20),<br> (‘browser’, 20),<br> (‘history’, 19),<br> (‘future’, 19),<br> (‘developer’, 18),<br> (‘inspiration’, 17),<br> (‘programming’, 16),<br> (‘read’, 16),<br> (‘javascript’, 16),<br> (‘stories’, 13),<br> (‘coding’, 13),<br> (‘learn’, 12),<br> (‘spend’, 12),<br> (‘declarative’, 11),<br> (‘imperative’, 11),<br> (‘work’, 11),<br> (‘people’, 11),<br> (‘using’, 11),<br> (‘become’, 11),<br> (‘perfect’, 10),<br> (‘finding’, 10),<br> (‘better’, 10)</p>
</blockquote>
<p>In short — coding, learning, and hard work.</p>
<p>A huge thanks to everyone in the <a target="_blank" href="https://gitter.im/freecodecamp/datascience">Data Science Room</a> who helped with the data analysis and visualization necessary to create this article.</p>
<p>Until next time, stay social! And happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A semi-automatic way to create your own grid map ]]>
                </title>
                <description>
                    <![CDATA[ By Krist Wongsuphasawat In the past year, the grid map style visualization has gained a lot of popularity in the US [2,4]. It has a quite a few nice properties, which inspired me to create one for Thailand. The rest of this article will explain grid ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/creating-grid-map-for-thailand-397b53a4ecf/</link>
                <guid isPermaLink="false">66c3481dfe2a6da72cef337a</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 12 Jan 2016 01:13:20 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*XFuuGyX5Ffi96DLWgupCtA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Krist Wongsuphasawat</p>
<p>In the past year, the gr<em>id map</em> style visualization has gained a lot of popularity in the US [2,4]. It has a quite a few nice properties, which inspired me to create one for Thailand.</p>
<p>The rest of this article will explain grid maps, and how I created the grid map for Thailand map you see above.</p>
<p><strong>But if you are interested in using the map already without reading the details of how to create one yourself, jump straight to my <a target="_blank" href="https://github.com/kristw/gridmap-layout-thailand">gridmap-layout-thailand</a> github repository</strong>.</p>
<h4 id="heading-what-is-a-grid-map-and-what-are-its-properties">What is a Grid Map, and what are its properties?</h4>
<p>In a grid map, each region is represented as a tile of the equal shape and size. The tiles are placed to fit within a grid at positions that approximate real geographic position. If the tile is a square, the grid is rectangular. If the tile is a hexagon, then the grid is like a honeycomb. See the US maps below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ge3DyNssY0xnjHtgn0-Urg.png" alt="Image" width="800" height="181" loading="lazy">
_Maps of the US: (left) Hexagon Tile Grid Map (center) Square Tile Grid Map (right) Geographic Map. Source: [NPR Blog](http://blog.apps.npr.org/2015/05/11/hex-tile-maps.html" rel="noopener" target="<em>blank" title=")</em></p>
<p>Most of grid map visualizations are <a target="_blank" href="https://en.wikipedia.org/wiki/Choropleth_map"><em>choropleth maps</em></a> that use colors to encode values, such as amount of rainfall, average population age, or political alignment. Creating choropleth maps from geographic maps has some disadvantages, because the different sizes of each region introduce biases while interpreting the results. Also, many small regions are often too small to be notice on a map.</p>
<p><strong>Pros: g</strong>rid maps do not introduce biases due to different sizes of the regions, making it an interesting choice when creating a choropleth map. Small regions are now guaranteed to be big enough to be seen. It’s also easier to implement and faster to load than a geographic map.</p>
<p><strong>Cons:</strong> The positions of the regions are only approximations, and could be inaccurate. For example, some adjacent regions may not appear adjacent on the grid map. It also distorts the distance between regions.</p>
<h4 id="heading-creating-grid-map-for-thailand">Creating Grid Map for Thailand</h4>
<p>Here are the requirements:</p>
<ul>
<li>The overall map still looks similar to the geographical shape of Thailand. The neighboring regions should appear adjacent or close by.</li>
<li>Use square tiles for ease of curation and application. For example, this map can be drawn in Excel [3] or Google Sheets easily.</li>
<li>The map does not have any holes in the middle to avoid confusion.</li>
</ul>
<p>Of course, the most straightforward approach to create this map is to draw the map manually from scratch. However, I would like to save some energy with a semi-automatic approach:</p>
<ol>
<li>For each province, create one rectangle centered at its centroid.</li>
<li>Use a <a target="_blank" href="https://github.com/mbostock/d3/wiki/Force-Layout">force-directed simulation</a> to detect collisions between rectangles and remove overlaps. Each rectangle has its own center of gravity at the centroid of its province (<a target="_blank" href="http://bl.ocks.org/mbostock/1804919">multi-foci force-directed layout</a>). The solid lines in the figure below show displacements of the rectangles from their ideal positions.</li>
<li>Snap the rectangles to a rectangular grid.</li>
<li><a target="_blank" href="https://gist.github.com/kristw/31be36fa0df6a85c1cbd">Export results from Step 3 as CSV file</a> and manually curate in Google Sheets or Excel. The goal of this step is to remove unnecessary gaps, connect the map into one contiguous piece, and adjust the positions of some provinces.</li>
<li>Done! The new map only requires 40% of the original space.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*BRBbGurtiCLcUhM1P5kJYQ.png" alt="Image" width="799" height="497" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*2D2Pm7z5jxVxTepAe1JAkA.png" alt="Image" width="535" height="495" loading="lazy"></p>
<h4 id="heading-usage">Usage</h4>
<p>The output from this process can be used as JS, CSV or JSON files. Please see <a target="_blank" href="https://github.com/kristw/gridmap-layout-thailand">gridmap-layout-thailand</a> on GitHub for instructions. The code I used for steps 1–5 above are also in that repo.</p>
<p>Lastly, this method still depends a lot on manual curation at the end, which may not produce the best optimization. If you have any suggestions or would like to recommend a better approach, the comment box below is yours. :)</p>
<h4 id="heading-references">References</h4>
<p>[1] Mike Bostock. “<a target="_blank" href="http://bl.ocks.org/mbostock/1804919">Multi-Foci Force Layout</a>” <em>bl.ocks.org</em> Published 11 February 2012<br>[2] Danny DeBelius. “<a target="_blank" href="http://blog.apps.npr.org/2015/05/11/hex-tile-maps.html">Let’s Tesselate: Hexagons For Tile Grid Maps</a>” <em>NPR Blog.</em> Published 11 May 2015<br>[3] Caitlin Dempsey Morais. “<a target="_blank" href="http://www.gislounge.com/how-to-make-a-tile-grid-map-using-excel/">How to Make a Tile Grid Map Using Excel</a>” <em>GIS Lounge</em>. Published 10 November 2015<br>[4] Nathan Yau. “<a target="_blank" href="https://flowingdata.com/2015/05/12/the-great-grid-map-debate-of-2015/">The Great Grid Map Debate of 2015</a>” <em>Flowing Data.</em> Published 12 May 2015</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
