{"id":13714525,"url":"https://github.com/sgratzl/d3tutorial","last_synced_at":"2025-04-06T22:12:14.686Z","repository":{"id":40267269,"uuid":"74661515","full_name":"sgratzl/d3tutorial","owner":"sgratzl","description":"📊📈 A D3 v7 tutorial - interactive bar chart and multiple coordinated views (MCV)","archived":false,"fork":false,"pushed_at":"2024-03-22T00:51:28.000Z","size":2750,"stargazers_count":256,"open_issues_count":0,"forks_count":55,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-30T21:08:07.817Z","etag":null,"topics":["barchart","codepen","css","d3","d3-js","d3js","d3v4","d3v5","d3v6","d3v7","data-join","html","javascript","mcv","multiple-coordinated-view","svg","tutorial","typescript"],"latest_commit_sha":null,"homepage":"https://www.sgratzl.com/d3tutorial/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sgratzl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["sgratzl"]}},"created_at":"2016-11-24T10:11:43.000Z","updated_at":"2025-01-18T06:04:57.000Z","dependencies_parsed_at":"2024-01-17T03:59:38.622Z","dependency_job_id":"9179c07c-50e3-4939-8cf9-5e0a371388e8","html_url":"https://github.com/sgratzl/d3tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sgratzl%2Fd3tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sgratzl%2Fd3tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sgratzl%2Fd3tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sgratzl%2Fd3tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sgratzl","download_url":"https://codeload.github.com/sgratzl/d3tutorial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247557770,"owners_count":20958047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["barchart","codepen","css","d3","d3-js","d3js","d3v4","d3v5","d3v6","d3v7","data-join","html","javascript","mcv","multiple-coordinated-view","svg","tutorial","typescript"],"created_at":"2024-08-03T00:00:26.428Z","updated_at":"2025-04-06T22:12:14.668Z","avatar_url":"https://github.com/sgratzl.png","language":"HTML","readme":"# D3 Tutorial\n\nThis is a short interactive tutorial introducing the basic elements and concepts of D3. At the beginning of this tutorial the foundations of D3 namely HTML, CSS, SVG, and JavaScript are briefly explained.\n\nThen, the basic principles of D3 and its functions are introduced by incrementally implementing an interactive bar chart.\nThe example can be implemented manually or directly by editing the [CodePen](https://codepen.io) examples.\n\nThe final result looks like:\n\n![barchart](https://user-images.githubusercontent.com/4129778/92122056-49442b80-edfb-11ea-9591-756680f36bc5.gif)\n\nIn the second part of this tutorial a more complex multiple coordinated view (MCV) setup is incrementally implemented. A multiple coordinated view setup consists of multiple visualizations that are interactively linked together such\nas selecting an element in one visualization filters the data in a second one. This is also called linking and brushing. Along with this example some guidelines\nregarding code structure and advanced D3 transitions are given.\n\nThe final result looks like:\n\n![mcv](https://user-images.githubusercontent.com/4129778/92122327-94f6d500-edfb-11ea-9856-6c8770c1400b.gif)\n\nThis tutorial concludes with a brief introduction into other visualization libraries and hints about how to use D3 with [TypeScript](https://www.typescriptlang.org/).\n\nNow, shall we begin...\n\n---\n\nD3 stands for Data-Driven Documents and is a very popular JavaScript library written by [Mike Bostock](https://bost.ocks.org/mike/).\n\nHomepage: https://d3js.org/\n\nGithub: https://github.com/d3/d3\n\nAPI Documentation: https://github.com/d3/d3/blob/master/API.md\n\nGallery: https://github.com/mbostock/d3/wiki/Gallery\n\nExamples: **everywhere** just google it\n\nLicense: BSD-3-Clause license\n\nDownload / Include:\n\n- `\u003cscript src=\"https://d3js.org/d3.v7.js\" charset=\"utf-8\"\u003e\u003c/script\u003e`\n- https://github.com/d3/d3/releases/latest\n\n## Credits\n\nThis tutorial is created and maintained by [Samuel Gratzl](https://github.com/sgratzl/d3tutorial), with contributions from [Holger Stitz](https://github.com/thinkh/d3tutorial), and based on a tutorial by [Alexander Lex](https://dataviscourse.net/2016/tutorials/).\n\n---\n\n# Content\n\n- [Development Environment](#dev-environment)\n- [HTML - Hypertext Markup Language](#html)\n- [CSS - Cascading Style Sheets](#css)\n- [SVG - Scalable Vector Graphics](#svg)\n- [JS - JavaScript / JSON (JavaScript Object Notation)](#js)\n\nPart 1: Student's First Barchart\n\n- [D3 - Data-Driven Documents](#d3)\n- [Simple Selections and Manipulations](#d3-selections)\n- [Data Join: Enter / Update / Exit](#d3-data-join)\n- [Data Loading: d3.json, d3.csv](#d3-data-loading)\n- [Scales and Axes](#d3-scales-axes)\n- [Interactivity](#d3-interactivity)\n- [Transitions](#d3-transitions)\n\nPart 2: Student's First Multiple Coordinated View\n\n- [Code Structure](#code-structure)\n- [D3 Layouts](#layouts)\n- [Interactivity 2](#interaction2)\n- [Reusability](#reuse)\n- [Transitions 2](#transitions2)\n\nExtras\n\n- [More D3](#more-d3)\n- [D3 Boilerplate](#boilerplate)\n- [What Else Besides D3](#beside-d3)\n\nAppendix\n\n- [TypeScript and D3](#typescript)\n\n\u003e SURVEY: What do you guys already know?\n\n---\n\n\u003ca id=\"dev-environment\"\u003e\u003c/a\u003e\n\n# Development Environment\n\nUsing a good development environment can save you time and prevent you from pain. Editors like [Visual Studio Code](https://code.visualstudio.com), [Sublime](https://www.sublimetext.com/), or [Atom](https://atom.io) are a good start. Fully fledged integrated development environments such as [WebStorm](https://www.jetbrains.com/webstorm/) or [Eclipse](https://www.eclipse.org/webtools/) may be complex at a first glance but provide a bunch of useful features.\n\n## Chrome Developer Tools\n\nThe [Chrome Developer Tools](https://developer.chrome.com/devtools) are a great set of utilities for web development.\n\nAmong other you have:\n\n- Web Inspector\n  - Properties\n  - CSS Style Selector\n- Console\n  - in-place coding\n  - `console.log`, `console.error`\n- Debugger\n  - (Conditional) Breakpoints\n  - Callstack\n  - Console context\n  - `debugger` statement a hard-coded breakpoint forcing the debugger to stop (if the developer tools are opened)\n- Profiler profile your JS code for bottlenecks\n- Network look at all the requests/responses of your website\n\nEvery major web browser (Firefox, Safari, Edge, Internet Explorer, etc.) has integrated developer tools.\n\n## Local WebServer\n\nWhile you can view local sites (`file:///`), Chrome doesn't allow you to load additional external files, e.g., JSON files, for security reasons. Therefore, you need a local webserver running for development. As alternative you can use an integrated IDE (such as [WebStorm](https://www.jetbrains.com/webstorm/)) that has a webserver already integrated.\n\nIn case you are using Visual Studio Code we can recommend the [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) extension.\n\nStarting a simple python static webserver:\n\n```bash\npython -m SimpleHTTPServer\n```\n\nFull list: https://gist.github.com/willurd/5720255\n\n## Git (Version Control)\n\nUsing a version control tool (in our case git) tracks changes to your code. Git keeps copies of multiple states of files, which allows you to go back to an older version.\n\nWe are using [Github](https://github.com), an online tool for hosting git repositories. You can sign up there and create a public git repository for free.\n\nYou should already have git installed, if not see the [official documentation](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) on how to install git on your operating system. Alternatively, you can use [GitHub Desktop](https://desktop.github.com/).\n\n---\n\n\u003ca id=\"html\"\u003e\u003c/a\u003e\n\n# HTML - Hypertext Markup Language\n\nIn HTML the markup is represented by elements. An HTML element is a portion of the content that is surrounded by a pair of tags of the same name. Like this:\n\n```html\n\u003cstrong\u003eThis is an HTML element.\u003c/strong\u003e\n```\n\nHTML elements can be nested:\n\n```html\n\u003cstrong\u003eThis is an \u003cu\u003eHTML\u003c/u\u003e element.\u003c/strong\u003e\n```\n\nThe opening tag of an element can contain extra information as attributes:\n\n```html\n\u003ca href=\"https://www.google.com\"\u003eA link to Google's main page\u003c/a\u003e\n```\n\nThe `a` element (which stood for \"anchor\") describes a link. The attribute `href` means \"HTML reference\". The meaning given to each attribute changes from element to element.\n\nElements contain attributes, for instance `id`, `class`, and `style`. The `id` attribute must be unique through the entire document and can be accessed easily from JavaScript. It can be seen as a global variable.\nThe attributes `class` and `style` are used in conjunction with CSS and will be explained in the CSS section below.\n\nSome elements are self-closing, i.e. `\u003cfoo /\u003e` is equivalent to `\u003cfoo\u003e\u003c/foo\u003e`\n\n```html\n\u003cimg src=\"logo.png\" alt=\"Logo\" /\u003e\n```\n\nBelow are a couple of tags that don’t have visual equivalents on the website, but they are used to define document metadata:\n\n- `\u003chtml\u003e` creates the entire HTML container.\n- `\u003chead\u003e` creates the header (generally where the title and links to style sheets/scripts are found).\n- `\u003cscript\u003e` links to or embeds a script (we will do that a lot).\n- `\u003cstyle\u003e` for embedding a style in the website.\n- `\u003clink\u003e` to reference an external document, often a CSS document like that: `\u003clink rel=\"stylesheet\" type=\"text/css\" href=\"theme.css\"\u003e`. The `rel` attribute defines the relationship to the active document, the `type` attribute tells the browser which type of file to expect.\n- `\u003cbody\u003e` marks the container of the content of the website.\n\nA comprehensive and well structured list of all elements can be found at [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).\n\n## DOM - Document Object Model\n\nThe markup document is a tree structure: it has a root, the HTML element, and elements can have children that are containing elements themselves.\n\nWhile HTML is a textual representation of a markup document, the DOM (Document Object Model) is a programming interface for it. DOM Elements contain further internal properties and can be accessed and modified from JavaScript.\n\n---\n\n\u003ca id=\"css\"\u003e\u003c/a\u003e\n\n# CSS - Cascading Style Sheets\n\nHTML specifies the content of a web page. CSS (Cascading Style Sheets) are external declarations that control the way HTML elements will get rendered by a web browser. A full discussion of CSS syntax can be found at [MDN CSS website](https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax); in following only the very basics are shown.\n\nA stylesheet will usually consist of a list of CSS rules that are inserted in `\u003cstyle\u003e` elements on the HTML header, `\u003chead\u003e`. A single CSS rule associates a CSS selector with a set of CSS declarations. These are easier to see through examples.\n\nMore important than styling, however, are the rules on how we identify elements in the DOM, the selectors.\n\n## Selectors\n\nGreat way to separate the style from the actual content. In addition, the selector notation is used for navigation and selections in D3.\n\nGood overview of CSS Selectors: https://code.tutsplus.com/tutorials/the-30-css-selectors-you-must-memorize--net-16048\n\nMost important selectors explained in an example\n[![Open in CodePen][codepen]](https://codepen.io/thinkh/pen/rybJVE):\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eCSS Example\u003c/title\u003e\n    \u003cstyle\u003e\n      /* select all `div` elements */\n      div {\n        border: 1px solid blue;\n        margin: 10px;\n      }\n\n      /* select elements having class `header` */\n      .header {\n        background: steelblue;\n        color: white;\n      }\n\n      /* select the element with the id `main` */\n      #main {\n        border: 1px solid red; /* Overrides the rules from `div`, because `#main` is more specific */\n      }\n\n      /* select all `div` with class `header` */\n      div.header {\n        background: green; /* Overrides the rules from `.header`, because `div.header` is more specific */\n      }\n\n      /* select all descendent `p` within a `div` */\n      div p {\n        font-size: 200%;\n      }\n\n      /* matches when the mouse hovers a `div` */\n      div:hover {\n        background-color: orange;\n      }\n    \u003c/style\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cdiv class=\"header\"\u003eD3 Test\u003c/div\u003e\n    \u003cdiv id=\"main\"\u003e\n      \u003cp class=\"header\"\u003eLorem Impsum Header\u003c/p\u003e\n      \u003cp\u003eLorem Impsum\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Other ways of declaring CSS\n\nCSS rules can be also stored as external file. This is very useful when sharing CSS rules across many different documents. In that case, include the following element in the document `\u003chead\u003e`:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"style.css\" /\u003e\n```\n\n---\n\n\u003ca id=\"svg\"\u003e\u003c/a\u003e\n\n# SVG - Scalable Vector Graphics\n\n\u003cimg src=\"https://upload.wikimedia.org/wikipedia/commons/6/6b/Bitmap_VS_SVG.svg\" height=\"200px\"\u003e\n\nImage Source: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics\n\nSVG describes the image to be drawn instead of drawing it pixel by pixel.\n\nExample:\n\n```html\n\u003csvg\u003e\n  \u003ccircle r=\"10\" cx=\"20\" cy=\"20\" fill=\"green\" /\u003e\n  \u003crect x=\"18\" y=\"18\" width=\"30\" height=\"20\" style=\"fill: blue\" /\u003e\n  \u003ctext x=\"10\" y=\"30\"\u003eTest\u003c/text\u003e\n\u003c/svg\u003e\n```\n\nDraws a circle at `20,20` (origin is the top left corner) with a radius of `10` filled with a `green` color. **Hint:** the order defines the visibility order --\u003e the last one is on top\n\n\u003cimg src=\"https://cdn.rawgit.com/sgratzl/d3tutorial/master/i/primitives.svg\" height=\"100px\"\u003e\n\nSee source code for this image at [i/primitives.svg](i/primitives.svg)\n\nImportant elements:\n\n- `circle(cx, cy, r)`\n- `rect(x, y, width, height)`\n- `line(x1, y1, x2, y2)`\n- `text` ... text as the body of the element\n- `path(d)` ... complex shapes\n- `g` ... grouping of elements\n- **Hint:** `title` ... can be a child of each element for creating a description shown as a tooltip\n\nA list of all SVG elements at [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Element).\n\nImportant attributes:\n\n- `style` ... set CSS style attribute\n- `fill` ... fill color\n- `stroke` ... stroke color\n- `transform` ... apply a linear transformation on the element and its children (in case of a `g` element), e.g., `transform=\"translate(100,10)rotate(90)scale(2,2)\"`\n\nA list of all SVG attributes at [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute).\n\n3 ways for specifying the fill color of an element:\n\n1. inline style: `style=\"fill: green\"`\n2. fill attribute: `fill=\"blue\"`\n3. css rule: `circle { fill: blue; }`\n\n---\n\n\u003ca id=\"js\"\u003e\u003c/a\u003e\n\n# JS - JavaScript\n\nHTML and SVG code are only static; JavaScript can manipulate the DOM and thus create interactive sites and applications. JavaScript is the most important programming language of the web, and the only programming language that can be used on most web-browsers without any plugins.\n\nJavaScript can be used with imperative/procedural, object-oriented, and functional programming styles.\n\nIt is a dynamically typed language, which can be strange for developers who mainly work with strongly typed languages such as C/C++ and Java.\n\n**Note** To follow the examples below, you can open the JavaScript console on a browser window, and type the examples to see what they do. Or\n[![Open in CodePen][codepen]](https://codepen.io/thinkh/pen/qrwxdb).\n\n```js\n// variables\nconst x = 5;\nconst s = \"abc\";\nconst s2 = \"abc\";\nconst arr = [1, 2, 4];\nconst obj = { a: 10, b: \"test\" };\n// access: obj.a or obj['a']\n\n// conditionals\nif (x \u003c 10) {\n  console.log(\"small\");\n} else {\n  console.log(\"large\");\n}\n\n// ternary operator\nconst x2 = x \u003c 10 ? 20 : 30;\n\n// loops\nfor (let i = 0; i \u003c arr.length; i++) {\n  x += arr[i];\n}\n// for of\nfor (const ai of arr) {\n  x += ai;\n}\n\nlet i = 0;\nwhile (i \u003c 10) {\n  x += i++ * 10;\n}\n\n// functions\nfunction add(a, b) {\n  return a + b;\n}\nconst sub = (a, b) =\u003e {\n  return a - b;\n};\nconsole.log(add(10, 30), sub(10, 5));\n\n// functional style programming\narr.forEach((d) =\u003e (x += d));\nconst arr2 = arr.map((d) =\u003e d * 10);\nconst arrf = arr.filter((d) =\u003e d \u003c 3);\n// function are first-level objects\nfunction compute(f, a, b) {\n  return f(a, b);\n}\nconsole.log(compute(add, 20, 10));\n```\n\nFurther reading about JavaScript at [MDN](https://developer.mozilla.org/en-US/docs/Web/javascript).\n\n---\n\n\u003ca id=\"d3\"\u003e\u003c/a\u003e\n\n# Part 1: Dive into D3 aka. Student's First Barchart\n\nA fundamental concept in D3 is binding a DOM element to a data item and manipulate the attributes according to the bound data item. For example, you have a list of persons each having two numerical attributes (age, weight) and a categorical one (gender). You bind each person to an SVG circle element and set the circle's x-position according to the age and the y-position according to the weight. If you additionally fill the circle according to the person's gender, you end up with a simple colored scatterplot visualization.\n\nCode: [persons.html](examples/persons.html)\n\n\u003ca id=\"d3-selections\"\u003e\u003c/a\u003e\n\n## Simple Selections and Manipulations\n\nAll functions of D3 are available under the namespace: `d3`. The most important functions are `select` and `selectAll`. `select` requires in the simplest form an CSS selector string as argument and returns an selector object for the first matching element only. `selectAll` returns a list of matched elements respectively. **Hint:** both functions won't throw an error if no element was found, in either cases they return a dummy selector, having no effect.\n\n```js\nconst header = d3.select(\"div.header\");\n```\n\nSelectors provides a couple of function for manipulating the DOM element including: `attr`, `style`, `classed`, `text`, and `html`.\n\n```js\nconst circle = d3.select(\"circle\");\ncircle.attr(\"r\", 10);\ncircle.attr(\"cx\", 20);\ncircle.attr(\"cy\", 23);\n\n// alternative syntax via chaining\ncircle.attr(\"r\", 10).attr(\"cx\", 20).attr(\"cy\", 23);\n\n// set css styles\ncircle.style(\"stroke-width\", 2);\n\n// add, remove css classes\ncircle.classed(\"highlight\", true);\n\n// set inner text\nd3.select(\"text\").text(\"Hello\");\nd3.select(\"div\").html(`\u003cstrong\u003eHello\u003c/strong\u003e`);\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/POVKRj)\n\nThe function come in different shapes: as setter (previous examples) as in a getter version. In the later case the value of the first element in the list will be returned. e.g., `circle.attr('cx')`\n\n### DOM Manipulation\n\nThe DOM elements can be manipulated using. `append` and `remove`\n\n```js\nconst body = d3.select(\"body\");\nbody.append(\"svg\").attr(\"width\", 800).attr(\"height\", 600);\n\nd3.select(\"svg\").remove();\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/YEBxaW)\n\n\u003ca id=\"d3-data-join\"\u003e\u003c/a\u003e\n\n## Data Join: Enter / Update / Exit\n\nThe basic idea of D3 is binding data items to DOM elements and manipulate them accordingly. We can distinguish three different cases when binding a bunch of data items to a set of DOM elements:\n\n![D3 Data Join Set Relationship](i/join.png)\n\n![D3 Data Join Set Relationship](i/join_types.png)\n\nFor each of the cases we have to tell D3 what to do. e.g., when we have more data items than DOM elements, we are in the _enter_ phase and need to specify a way how to create the remaining ones. Similarly if we have more DOM elements than data items we are in the _exit_ phase and need to take care of removing the superfluous ones.\n\nBasic workflow:\n\nHTML boilerplate\n\n```html\n\u003csvg width=\"300\" height=\"300\"\u003e\u003c/svg\u003e\n```\n\n```js\nconst data = [1, 2, 3];\n// select svg element\n// select all circles - even if there none yet - and bind the data array `data` onto them\n// call .join to specify the data binding / joining\nconst circles = d3\n  .select(\"svg\")\n  .selectAll(\"circle\")\n  .data(data)\n  .join(\n    (enter) =\u003e {\n      // append an element matching the selector and set constant attributes\n      const circles_enter = enter.append(\"circle\");\n      circles_enter.attr(\"r\", 10);\n      return circles_enter;\n    },\n    // update existing elements\n    (update) =\u003e update,\n    (exit) =\u003e {\n      // exit phase\n      return exit.remove();\n    }\n  );\n\n// update phase ... actually update all including the newly created ones\n\n// function argument given two parameters:\n// 1. argument (common name: d): the current data item\n// 2. argument (common name: i): the index of the data item in the data array\n// this context: the current DOM element\ncircles.attr(\"cx\", (d, i) =\u003e d * 10);\ncircles.attr(\"cy\", (d, i) =\u003e i * 50);\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/poozzga)\n\nCommon shortcut:\n\n```js\nconst data = [1, 2, 3];\nd3.select(\"svg\")\n  .selectAll(\"circle\")\n  .data(data)\n  .join((enter) =\u003e enter.append(\"circle\").attr(\"r\", 10))\n  .attr(\"cx\", (d, i) =\u003e d * 10)\n  .attr(\"cy\", (d, i) =\u003e i * 50);\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/oNNvvxv)\n\nEven shorter:\n\n```js\nconst data = [1, 2, 3];\nd3.select(\"svg\")\n  .selectAll(\"circle\")\n  .data(data)\n  .join(\"circle\")\n  .attr(\"r\", 10)\n  .attr(\"cx\", (d, i) =\u003e d * 10)\n  .attr(\"cy\", (d, i) =\u003e i * 50);\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/GRRKKZq)\n\n**Notes**\n\n- if instead of a `enter` function a string is given it is a shortcut for appending an element of this type. So `join('circle')` is similar to `.join((enter) =\u003e enter.append('circle'))`\n- if no `update` function is given, nothing will be done\n- if no `exit` function is given, the default `exit.remove()` will be used\n\n---\n\n**INTERACTIVE**\n\nCreating a bar chart: [barchart01_initial.html](examples/barchart01_initial.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/xRrrgp)\n\n---\n\n### Nested Selections and Nested Data Joins\n\nNested selections can be used for adding inner elements. A common approach is creating one `g` element for each data item and add several sub DOM elements. The sub element will be created during the enter-phase and updated using `select`. By using `select` function the data-join remains using `selectAll` a nested data join will be created. Nested data joins are useful for hierarchical data.\n\nNested data join [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/yLLBBOj):\n\n```js\n// hierarchical data\nconst data = [\n  { name: \"a\", arr: [1, 2, 3] },\n  { name: \"b\", arr: [3, 2, 4] },\n];\n\nconst groups = d3.select(\"svg\").selectAll(\"g\").data(data).join(\"g\");\n\ngroups.attr(\"transform\", (d, i) =\u003e `translate(${i * 20 + 10},10)`);\n\n// select all circles within each group and bind the inner array per data item\nconst circles = groups\n  .selectAll(\"circle\")\n  .data((d) =\u003e d.arr)\n  .join(\"circle\");\n\ncircles.attr(\"r\", (d) =\u003e d * 2).attr(\"cy\", (d, i) =\u003e i * 20);\n```\n\nNested selection [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/VwwZZjY):\n\n```js\nconst data = [1, 2, 3];\nconst circles = d3\n  .select(\"svg\")\n  .selectAll(\"circle\")\n  .data(data)\n  .join((enter) =\u003e {\n    const circles_enter = enter.append(\"circle\").attr(\"r\", 10);\n    // need to be separate since .append returns the appended element\n    circles_enter.append(\"title\");\n    return circles_enter;\n  });\n\ncircles.attr(\"cx\", (d, i) =\u003e d * 10).attr(\"cy\", (d, i) =\u003e i * 50);\n\ncircles.select(\"title\").text((d) =\u003e d);\n```\n\n---\n\n**INTERACTIVE**\n\nAdding a title attribute: [barchart02_title.html](examples/barchart02_title.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/PooYYzb)\n\n---\n\n\u003ca id=\"d3-data-loading\"\u003e\u003c/a\u003e\n\n## Data Loading: d3.json, d3.csv\n\nIn the current version we have static hard-coded data in our files. D3 provides a bunch of function for loading external files. The most important ones are `d3.json` for loading JSON files and `d3.csv` for CSV files respectively. Both return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) that will resolve when the file has been loaded.\n\n**Important: Data loading is asynchronous**! That means you won't get the data immediately as a return value. But you get a Promise that will be resolved , as soon as the data are ready. You can't predict when this happens. You have to structure your code accordingly.\n\n```js\nd3.json(\"file_to_load.json\")\n  .then((data) =\u003e {\n    // do something with the data\n  })\n  .catch((error) =\u003e {\n    console.error(\"Error loading the data\");\n  });\n```\n\n```js\nd3.csv(\"file_to_load.csv\")\n  .then((data) =\u003e {\n    // array of objects\n    console.log(data.length);\n    // do something with the data\n  })\n  .catch((error) =\u003e {\n    console.error(\"Error loading the data\");\n  });\n```\n\nSee also: https://github.com/d3/d3-request/blob/master/README.md#csv for formatting and parsing options.\n\n**Warning**: Chrome prevents accessing local files using XMLHttpRequest by default (from `file:///`); Firefox does allow this. So, you need a local webserver running on your machine.\n\n---\n\n**INTERACTIVE**\n\nLoading [weather.json](examples/weather.json): [barchart03_json.html](examples/barchart03_json.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/poozzbL)\n\n---\n\n\u003ca id=\"d3-scales-axes\"\u003e\u003c/a\u003e\n\n## Scales and Axes\n\nAs seen in the barchart example, mapping a value to a pixel value manually is a pain. D3 provides scales for this case. The idea is creating a mapping function between the _domain_ values (data space) and the output _range_ (pixel space).\n\n![D3 scales](./i/scale.png)\n\nD3 provides different scales:\n\n- quantitative\n  - `d3.scaleLinear()` ... linear mapping between domain and range\n  - `d3.scalePow()`\n  - `d3.scaleSqrt()`\n  - `d3.scaleLog()`\n  - `d3.scaleTime()`\n- ordinal\n  - `d3.scaleOrdinal()`\n- `d3.scaleBand()`\n- `d3.scalePoint()`\n- more specialized ones see https://github.com/d3/d3-scale\n\n### Colors\n\nWith version 5 D3 extracted the color schemes to it on repository located at\nhttps://github.com/d3/d3-scale-chromatic. Including both D3 standard schemes (e.g., `d3.schemeCategory10`) but also the ones from [ColorBrewer](https://colorbrewer2.org/) (e.g., `d3.schemeSet3`). These can be used as `range` for an ordinal scale.\n\n```js\nconst cscale = d3.scaleOrdinal().domain([\"a\", \"b\", \"c\"]).range(d3.schemeCategory10);\n```\n\n```js\nconst scale = d3.scaleLinear().domain([0, 5]).range([0, 200]);\nconst cscale = d3.scaleLinear().domain([0, 5]).range(['black', 'white']);\n\n...\n// the scale can be applied as a function\ncircles\n  .attr('cx', (d) =\u003e scale(d))\n  .style('fill', (d) =\u003e cscale(d));\n```\n\n```js\n// domain is a list of strings or numbers\nconst scale = d3.scaleOrdinal().domain(['a', 'b', 'c']).range([10, 20, 30]);\n// distribute as a band for each item\nconst bscale = d3.scaleBand().domain(['a', 'b', 'c']).range([0, 200]);\n\n...\n// the scale can be applied as a function\ncircles.attr('cx', (d) =\u003e scale(d));\n\n// hint: bscale.bandwidth() returns the width of a band\n```\n\nIn addition, it is quite common adding a axis for your charts. D3 provides a utility function for this case : `d3.axisBottom()`, `d3.axisLeft()`, `d3.axisRight()`, `d3.axisTop()`. It uses a scale as input and the necessary SVG elements for you.\n\n```js\nconst scale = d3.scaleLinear().domain([0, 5]).range([0, 200]);\n\nconst axis = d3.axisBottom().scale(scale);\n\n// create a container to put the axis\nconst axis_container = d3.select(\"svg\").append(\"g\").attr(\"class\", \"axis\").attr(\"transform\", \"translate(0,200)\");\n\n// call axis to create the SVG elements for you\naxis_container.call(axis);\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/zPedpX)\n\n---\n\n**INTERACTIVE**\n\nAdding linear and ordinal scale: [barchart04_scale.html](examples/barchart04_scale.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/oNNvvzv)\n\n---\n\n\u003ca id=\"d3-interactivity\"\u003e\u003c/a\u003e\n\n## Interactivity\n\nInteractivity is event-driven as in the usual DOM. However, you have easy access to the currently bound data-item as the second argument to the event listener. The first argument is the DOM event itself, which is useful for stopping the event propagation (bubbling) or preventing the default behavior. Moreover, the current context of the function `this` is the current DOM element.\n\n```js\nconst data = [1, 2, 3];\nconst circles = d3\n  .select(\"svg\")\n  .selectAll(\"circle\")\n  .data(data)\n  .join((enter) =\u003e\n    enter\n      .append(\"circle\")\n      .attr(\"r\", 10)\n      .attr(\"cy\", 40)\n      .attr(\"cx\", (d, i) =\u003e 30 + i * 30)\n      .on(\"click\", function (event, d) {\n        console.log(`clicked on: ${d}`);\n        const circle = d3.select(this); // can't use arrow scoping\n        circle.style(\"stroke\", \"orange\");\n      })\n  );\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/zYYOOKe)\n\nCommonly used events: `click`, `mouseover/mouseout`, `mouseenter/mouseleave`, `change`, `input`\n\n---\n\n**INTERACTIVE**\n\nFilter US cities: [barchart05_interactive.html](examples/barchart05_interactive.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/JjjPPRQ)\n\n---\n\n\u003ca id=\"d3-transitions\"\u003e\u003c/a\u003e\n\n## Transitions\n\nAnimated transitions can help the user understanding changes and are just fun to watch. Transitions in D3 are very simple. Just add `.transition()` within a selector and the changes afterwards are done in an animated fashion. D3 is very smart when it comes to interpolating values, colors, and much more. Transitions can be used during all phases: enter, update, and exit. By nesting transitions you can create fancy animations with just a bunch line of code.\n\n```js\nconst data = [1, 2, 3];\nconst circles = d3\n  .select(\"svg\")\n  .selectAll(\"circle\")\n  .data(data)\n  .join(\n    (enter) =\u003e enter.append(\"circle\").attr(\"r\", 10).attr(\"cx\", 100).attr(\"cy\", 100) // useful default values for animation\n  );\n\ncircles\n  .transition()\n  .duration(1000) // duration of the animation\n  .delay(200) // delay animation start\n  .attr(\"cx\", (d, i) =\u003e d * 50)\n  .attr(\"cy\", (d, i) =\u003e 40 + i * 100)\n  .transition() // start another transition after the first one ended\n  .attr(\"r\", 20);\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/QWWLLGa)\n\nD3 is rather dumb when it comes to mapping data items to DOM elements. It doesn't take the order into account. So, if element 'a' was previously at the first position and now on the third it will bind it to the third element. However, this hampers animations, i.e. animated sorting. By using the _key_ argument of the `data` function, one can force that the same DOM element is bound to the same data item regardless of the item order.\n\n```js\nconst cscale = d3.scaleOrdinal(d3.schemeCategory10).domain([\"a\", \"b\", \"c\", \"d\"]);\nconst xscale = d3.scaleBand().domain([\"a\", \"b\", \"c\", \"d\"]).range([10, 200]);\n\nfunction update(data) {\n  const s = d3.select(\"svg\");\n  // key argument return a unique key/id per data-item (string)\n  const circles = s\n    .selectAll(\"circle\")\n    .data(data, (d) =\u003e d)\n    .join((enter) =\u003e enter.append(\"circle\").attr(\"r\", 10).attr(\"cx\", xscale).style(\"fill\", cscale));\n\n  // a will be bound to the first DOM element\n  circles.transition().attr(\"cy\", (d, i) =\u003e 10 + i * 20);\n}\n\nlet data = [\"a\", \"b\", \"c\"];\nupdate(data);\n\n// later on... 2secs\nsetTimeout(() =\u003e {\n  data = [\"c\", \"a\", \"d\"];\n  // the items will move to their new position,\n  // and the DOM element for 'b' will be removed\n  // and another one for 'd' created\n  update(data);\n}, 2000);\n```\n\n[![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/ExxYYNM)\n\n---\n\n**INTERACTIVE**\n\nAnimated filter: [barchart06_animation.html](examples/barchart06_animation.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/dyybbNP)\n\n---\n\n---\n\n**INTERACTIVE**\n\nFinal results [barchart07_final.html](examples/barchart07_final.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/NWWKKda)\n\n---\n\n\u003ca id=\"part2\"\u003e\u003c/a\u003e\n\n# Part 2: Student's First Multiple Coordinated View\n\n\u003ca id=\"code-structure\"\u003e\u003c/a\u003e\n\n## Code Structure\n\nOne interactive visualization is nice multiple coordinated ones are better. Combined with filtering and linking and brushing it enables explore datasets in way more detail and discover new insights. Before creating a multiple coordinated view setup a proper code structure helps. A possible way to structure ones code based on its function is\n\n```js\n\nconst state = {\n  data: [],\n  // e.g., user selection\n}\n\nfunction filterData() {\n  // filter the raw data according to user selection\n}\n\nfunction wrangleData(filtered) {\n  // wrangles the given filtered data to the format required by the visualizations\n}\n\nfunction createVis() {\n  // initialized for creating the visualizations, e.g., setup SVG, init scales, ...\n\n  function update(new_data) {\n    // updates the specific visualization with the given data\n  }\n\n  // return the update function to be called\n  return update;\n}\n\n// create a specific instance\nconst vis = createVis();\n\nfunction updateApp() {\n  // updates the application\n\n  const filtered = filterData();\n  const new_data = wrangleData(filtered);\n\n  // update visualization\n  vis(new_data);\n}\n\n// init interaction, e.g., listen to click events\nd3.select(...).on('click', () =\u003e {\n  // update state\n  updateApp();\n})\n\nd3.json(...).then((data) =\u003e {\n  // load data, e.g., via d3.json and update app afterwards\n  state.data = data;\n  updateApp();\n});\n\n```\n\nBesides this functional approach an object oriented way is an valid alternative.\n\n---\n\n**INTERACTIVE**\n\nMCV Initial Setup: [mcv01_initial.html](examples/mcv01_initial.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/bQzNBO)\n\n---\n\n\u003ca id=\"layouts\"\u003e\u003c/a\u003e\n\n## Layouts\n\nD3 provides a bunch of standard layouts. A layout does not actually render the visualization but prepares your data, such that you can render, e.g., a pie chart. Most of the time the work with helper tools for SVG from D3. e.g., the `d3.pie()` works best with `d3.arc()`.\n\n### Pie Layout\n\nA pie-layout is a simple layout algorithm. It takes the data and a way to sort/compute the value per slice. It wraps the data and enhance it with additional attributes for the pie slice, such as start end end angle. _Hint_ the angles and arcs are computed relatively to the pie's center. The computed attributes with another utility function `d3.arc()` which converts the given values to a SVG path.\n\n![D3 Pie Layout](./i/pie.png)\n\n---\n\nSEE: [pie.html](examples/pie.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/BaaBBdZ)\n\n---\n\n### Force Layout\n\nA force layout is a graph layout algorithm, which uses a simulation for positioning nodes. The goal is to minimize the force applied on the system introduced by gravity, node repulsive force, and edge attraction forces. In this case it is not a one layout step, but a continuous one, where on each `tick` a new set of positions are available.\n\n![D3 Force Layout](./i/force.png)\n\n---\n\nSEE: [miserables.html](examples/miserables.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/poozzrK)\n\n---\n\n### D3 Geo\n\nD3 Geo is the D3 package for creating maps and other geo location based visualization. Similar to the other layouts D3 only helps to create the data structure and transformations but one has to render the map itself using SVG path elements. D3 provides numerous different geo projection methods, commonly used are `d3.geoAlbersUsa` and `d3.geoMercator`. A `d3.geoPath` uses a geo projection to transform geographical shape data in [GeoJSON](http://geojson.org/) or its derivative [TopoJSON](https://github.com/topojson/topojson) to SVG Path descriptions.\n\nFor example using `d3.geoAlbersUsa` and the [US Atlas](https://github.com/topojson/us-atlas) shape data one can create a simple Choropleth chart in which each US state is encoded using a continuous colored value.\n\n![D3 Choropleth](./i/choropleth.png)\n\n---\n\nSEE: [choropleth.html](examples/choropleth.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/LYGbObX)\n\n---\n\n**INTERACTIVE**\n\nPie chart layout: [mcv02_piechart.html](examples/mcv02_piechart.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/abbooyg)\n\n---\n\n\u003ca id=\"interaction2\"\u003e\u003c/a\u003e\n\n## Interaction And Filtering\n\nSo far the visualizations doesn't influence each other and the user can only filter data using form elements (drop downs, checkboxes). More intuitive is to interact with the visualization directly, e.g., by clicking on a bar to select this bar and filter all other visualizations to this selected subset.\n\n---\n\n**INTERACTIVE**\n\nInteractive Visualizations: [mcv03_interaction.html](examples/mcv03_interaction.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/QWWLLqm)\n\n---\n\n\u003ca id=\"reuse\"\u003e\u003c/a\u003e\n\n## Reusability\n\nAn advantage of our code structure is that we can use the factory methods to create multiple instances of the same visualization kind showing different aspect of the data. This is a simple yet effective way to improve the overall multiple coordinated setup.\n\n---\n\n**INTERACTIVE**\n\nReuse Visualizations: [mcv04_morevisses.html](examples/mcv04_morevisses.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/VVgYqx)\n\n---\n\n\u003ca id=\"transition2\"\u003e\u003c/a\u003e\n\n## Advanced Transitions\n\nIn addition to the simple `.transition()` D3 provides a more fine granular way to define and transition elements.\n\n- `.duration()` to define the duration of the animation.\n- `.delay()` to delay the animation.\n- `.ease()` to define the way how the interpolation should be performed, e.g., linear with ease in/out, ...\n\nEach variant allows like most D3 data bound functions either a constant as an argument (`.duration(2000)`) or a function that returns the value for the given data element (`.duration((d, i) =\u003e i * 1000)`). By naming a transition `.transition(name)` multiple transitions of different bindings can be synchronized. `.interrupt()` can be used to abort a currently running animation. For more information see [D3-Transition](https://github.com/d3/d3-transition/)\n\nThe biggest flexibility is to specify how attributes or styles should be tweened using interpolators [D3 Interpolator](https://github.com/d3/d3-interpolate). For example instead of `.attr('width', (d) =\u003e d * 10)`, one can use the `.attrTween('width', (d) =\u003e d3.interpolateNumber(0, d * 10))` to create a function that take a number of the range [0..1](t) as argument and returns the interpolated value. This can become handy in cases in which the simple interpolation doesn't work anymore, such as when interpolating the `d` attribute of paths.\n\n---\n\n**INTERACTIVE**\n\nCustom Transition: [mcv05_transitions.html](examples/mcv05_transitions.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/WNNeeXM)\n\n---\n\n---\n\n**INTERACTIVE**\n\nFinal Outcome: [mcv06_final.html](examples/mcv06_final.html) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/yLLBBPx)\n\n---\n\n\u003ca id=\"more-d3\"\u003e\u003c/a\u003e\n\n# More D3\n\nD3 provides way more that has not been covered in this tutorial including:\n\n- Geo Projection: GeoJSON, TopoJSON, Projection: https://observablehq.com/collection/@d3/d3-geo\n- Time: Scales, Formatting/Parsing, ...\n- Behaviors:\n  - Zoom\n  - Drag\n- Array Utilities: `d3.sum`, `d3.max`, `d3.set`, `d3.map`\n- Selector Utilities: `.sort()`, `.filter()`, `.raise()`, `.lower()`\n\n---\n\n\u003ca id=\"boilerplate\"\u003e\u003c/a\u003e\n\n# Boilerplate\n\n## Basic Setup\n\nOnline: https://codepen.io/sgratzl/pen/mOwrxO\n\nGithub repository: https://github.com/sgratzl/d3boilerplate\n\n---\n\n\u003ca id=\"beside-d3\"\u003e\u003c/a\u003e\n\n# What Else Besides D3?\n\n## Vega\n\n[Vega](https://vega.github.io/vega/) is a visualization grammar, a declarative language for creating, saving, and sharing interactive visualization designs. With Vega, you can describe the visual appearance and interactive behavior of a visualization in a JSON format, and generate web-based views using Canvas or SVG.\n\n![Vega Examples](./i/vega.png)\n\n## PowerBI\n\nhttps://powerbi.microsoft.com/\n\nThe big player for commercial data visualization.\n\n![PowerBI Screenshot](./i/powerbi.png)\n\n(c) https://docs.microsoft.com\n\n## Tableau\n\nhttps://www.tableau.com/\n\nAnother big player for commercial data visualization.\n\n![Tableau Screenshot](./i/tableau.png)\n\n(c) https://www.marketwatch.ro\n\n## Plot.ly\n\nhttps://plot.ly\n\nfree and commercial charting library.\n\n![Plot.ly Screenshot](./i/plotly.png)\n\n(c) https://aperiodical.com/\n\n## Chart.js\n\nhttps://chartjs.org\n\nOpen source canvas based charting library\n\n![Chart.js Screenshot](./i/chartjs.png)\n\n## Processing\n\nhttps://processing.org/ and https://processingjs.org/ for a web-version\n\nOwn programming language for visualizations with OpenGL backend\n\n![Processing Screenshot](./i/processing.jpg)\n\n## HighCharts\n\nhttps://www.highcharts.com/\n\nCommercial JavaScript Plot library\n\n![HighCharts Screenshot](./i/highcharts.jpg)\n\n(c) https://www.webdesignbooth.com\n\n## Vis.gl and Deck.gl\n\nhttps://vis.gl/\n\nOpen Source Visualization suite by Uber with a focus on high-performance big data visualizations.\n\n![Deck.gl Screenshot](./i/deck-gl.jpg)\n\n## Frameworks on top of D3:\n\n- NVD3 (https://nvd3.org/) - reusable plots on top of D3\n- Cubism (https://square.github.io/cubism/) - Time Series Data\n- Vega (https://vega.github.io/vega/) - declarative description of plots\n- Crossfilter (https://square.github.io/crossfilter/) - Fast Multidimensional Filtering for Coordinated Views\n- ...\n\n\u003ca id=\"typescript\"\u003e\u003c/a\u003e\n\n# Appendix\n\n## TypeScript and D3\n\n[TypeScript](https://www.typescriptlang.org/) is a programming language on top of JavaScript. Foremost it allows to specify types to variables and parameters similar to other typed languages such as Java, C#, and so on. The TypeScript compiler compiles the TypeScript code to regular JavaScript code and also performs checks on it. Every JavaScript code is valid TypeScript code.\n\nExamples\n\nThe following JavaScript code can be rewritten to TypeScript\n\n```js\nlet x = 5;\n\nfunction add(a, b) {\n  return a + b;\n}\n\nconsole.log(add(x, 3));\nconsole.log(add(\"text\", 3))ö\n```\n\n```ts\nlet x: number = 5;\n\nfunction add(a: number, b: number): number {\n  return a + b;\n}\n\nconsole.log(add(x, 3));\nconsole.log(add(\"text\", 3)); // will result in a compile error\n```\n\nMoreover, the TypeScript compiler is able to derive a lot which one can use to omit type declarations in some cases.\n\n```ts\nlet x = 5; // can be derived from the assignment\n\nfunction add(a: number, b: number) {\n  // same for return type\n  return a + b;\n}\n\nconsole.log(add(x, 3));\nconsole.log(add(\"text\", 3)); // will result in a compile error\n```\n\nOne can declare the types of variables and functions in ones own code. However, for external libraries, such as D3, the TypeScript compiler needs additional information such just the untyped JavaScript code is available. These are so called typings. [Definitely Typed](https://definitelytyped.org/) is a collection of typings for various JavaScript libraries including D3.\n\nSo, when installing D3 using NPM one can install the typings alongside. Usually it is just by prepending the `@types/` scope.\n\n```sh\nnpm install d3 @types/d3\n```\n\nDue to some heavy typing a D3 Selection (such as returned by `d3.select` or `d3.selectAll`) has four generic arguments:\n\n1.  the element type of the selected element, e.g., `d3.selectAll(\"div\")` will be a `HTMLDivElement`.\n1.  the data type bound to this element, e.g., `d3.selectAll(\"div\").data([1, 2, 3])` will be a `number`.\n1.  the element type of the parent element, e.g., `d3.select(\"body\").selectAll(\"div\").data([1, 2, 3])` will be a `HTMLBodyElement`.\n1.  the data type of the parent element, e.g., `d3.select(\"body\").datum(\"data\").selectAll(\"div\").data([1, 2, 3])` will be a `string`.\n\nIn my experience the third and fourth argument are barely of any use of which it can be simplified and set to e.g., `unknown` or `any`. However, one has to fully define a selection if you wanna explicitly define a variable containing a D3 selection,\n\n```ts\nimport * as d3 from \"d3\";\n\nlet rects: Selection\u003cSVGRectElement, number, SVGGElement, unknown\u003e;\n\nrects = d3.select(\"g\").selectAll(\"rect\").data([1, 2, 3]);\n```\n\nOne can specify the type in more detail by specifying the generic argument of the function. This is useful when the selector is more complex that just the element type. e.g., `d3.select\u003cSVGGElement, unknown\u003e(\".chart\")`. One also has to specify the generic arguments when using scales that are not just numbers but e.g., a linear scale for generating colors as `d3.scaleLinear\u003cstring, number\u003e().domain([0, 1]).range([\"white\", \"black\"]);`.\n\n---\n\nBarchart final results in TypeScript [barchart07_final_ts.ts](examples/barchart07_final_ts.ts) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/gObqdEG)\n\nMCV final results in TypeScript [mcv06_final_ts.ts](examples/mcv06_final_ts.ts) [![Open in CodePen][codepen]](https://codepen.io/sgratzl/pen/pojoNNL)\n\n### Hints\n\n#### Axis\n\nThe typings declare that an axis `d3.axisLeft`, ... can just be called on a `SVGGElement` thus one has to make sure that the typings are correct of the selection. For example:\n\n```ts\nconst axis = d3.axisLeft();\nd3.select\u003cSVGGElement, unknown\u003e(\".axis.x\").call(axis);\n```\n\n---\n\nThank You\n\n[codepen]: https://img.shields.io/badge/CodePen-open-blue?logo=codepen\n","funding_links":["https://github.com/sponsors/sgratzl"],"categories":["D3"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsgratzl%2Fd3tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsgratzl%2Fd3tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsgratzl%2Fd3tutorial/lists"}