{"id":16928002,"url":"https://github.com/pearmini/learning-d3","last_synced_at":"2025-07-30T03:06:00.954Z","repository":{"id":124231668,"uuid":"241832440","full_name":"pearmini/learning-d3","owner":"pearmini","description":"前端和 D3 入门教程：用条形图可视化 covid-19 疫情数据。🦠","archived":false,"fork":false,"pushed_at":"2022-10-19T05:39:27.000Z","size":93,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T02:41:41.320Z","etag":null,"topics":["barchart","covid-19","d3","frontend","visualization"],"latest_commit_sha":null,"homepage":"https://pearmini.github.io/learning-d3/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pearmini.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2020-02-20T08:35:20.000Z","updated_at":"2023-08-27T20:45:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"804499ca-7001-49e5-9e2a-adf3a686bd62","html_url":"https://github.com/pearmini/learning-d3","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pearmini/learning-d3","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearmini%2Flearning-d3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearmini%2Flearning-d3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearmini%2Flearning-d3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearmini%2Flearning-d3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pearmini","download_url":"https://codeload.github.com/pearmini/learning-d3/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pearmini%2Flearning-d3/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267802774,"owners_count":24146509,"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","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","covid-19","d3","frontend","visualization"],"created_at":"2024-10-13T20:35:39.769Z","updated_at":"2025-07-30T03:06:00.927Z","avatar_url":"https://github.com/pearmini.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 前端和 D3 入门教程\n\n这个仓库是一个简单的前端和 D3 的入门教程。\n\n教程从网页开发最基础的 HTML 讲起，涉及 SVG 的介绍，然后到 CSS 以及 JavaScript 和 D3 的基本使用。\n\n最后会开发一个响应式的网页：用 D3 通过条形图的方式对 covid-19 的确诊数进行了简单的可视化，该网页可以在电脑、平板和移动端访问。\n\n这里是在线 [demo](https://pearmini.github.io/learning-d3/)。\n\n## HTML\n\nHTML 是网页的结构层，用来描述网页的结构。\n\nHTML 文档是超文本标记语言( Hyper Text Markup Language )的简称。它不是一门编程语言，是一种标记语言，用来描述网页。一般来说 HTML 文档就是网页。\n\nHTML 文件由一系列的标记标签和存文本组成。不同的标签有不同的性质和功能，这些标签组合在一起就是我们的页面。\n\n下面是一个 HTML 文件基本结构。\n\n```html\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003c!-- 一些不可见，用来描述文档信息的元素 --\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003c!-- 一些可见，组成页面的元素 --\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n### 常见的元素\n\n```html\n\u003c!-- tab 上的标题 --\u003e\n\u003ctitle\u003ehello d3\u003c/title\u003e\n\n\u003c!-- 指定使用字符集合 --\u003e\n\u003cmeta charset=\"utf-8\" /\u003e\n\n\u003c!-- 适配移动端 --\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /\u003e\n```\n\n- 块状元素：div、section、article、aside、header、footer：div 的语意不是很丰富。\n- 段落、标题、图片等：p、h1、h2、img、a\n- 行内元素：span、em、strong\n- 列表元素：ul、ol、li、dl、dt、dd\n- 表单元素：form、input、textarea、button、select\n- 更多……\n\n### DOM 节点\n\n浏览器把 HTML 解析为一棵 DOM Tree，每一个节点就是一个 DOM 节点。\n\n### SVG\n\nSVG，指可缩放矢量图形（Scalable Vector Graphics），是用于描述二维矢量图形的一种图形格式。除了 IE8 之前的版本外，绝大部分浏览器都支持 SVG。\n\n在浏览器中可以通过下面的方式使用 SVG。\n\n```html\n\u003csvg viewBox=\"0 0 400 400\"\u003e\n  \u003crect\n    width=\"100\"\n    height=\"200\"\n    fill=\"red\"\n    x=\"50\"\n    y=\"50\"\n    transform=\"rotate（45)\"\n  /\u003e\n\u003c/svg\u003e\n```\n\n点击这里 [HTML](https://developer.mozilla.org/zh-CN/docs/Web/HTML)、[SVG](https://developer.mozilla.org/zh-CN/docs/Web/SVG) 学习更多。\n\n## CSS\n\nCSS(Cascading Style Sheets)，层叠样式表，是网页的表现层，用来指定网页的样式。\n\nCSS 是由一个个选择器和对应的样式声明构成，基本语法如下。\n\n```css\nselector {\n    declaration1;\n    declaration2;\n    ...\n    declarationN;\n}\n```\n\n下面介绍三种最常见的选择器。\n\n```css\n/* 元素选择器 */\nelement {\n}\n\n/* 类选择器 */\n.class {\n}\n\n/* id 选择器 */\n#id {\n}\n```\n\n在 HTML 里面使用 CSS 的主要方式有三种。\n\n（1）外部样式表\n\n```html\n\u003chead\u003e\n  \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" /\u003e\n\u003c/head\u003e\n```\n\n```css\n/* index.css */\np {\n  color: sienna;\n  margin-left: 20px;\n}\n```\n\n（2）内部样式表\n\n```html\n\u003cstyle\u003e\n  p {\n    color: sienna;\n    margin-left: 20px;\n  }\n\u003c/style\u003e\n```\n\n（3）内联样式\n\n```html\n\u003cp style=\"color:sienna;margin-left:20px\"\u003e这是一个段落。\u003c/p\u003e\n```\n\n点击[这里](https://developer.mozilla.org/zh-CN/docs/Web/CSS)学习更多。\n\n## JavaScript\n\nJavaScript 是网页的行为层，可以决定如何和人交互。\n\nJavaScript 是一种运行在浏览器中的解释型的编程语言。\n\n为什么起名叫 JavaScript？原因是当时 Java 语言非常红火，所以网景公司希望借 Java 的名气来推广，但事实上 JavaScript 除了语法上有点像 Java，其他部分基本上没啥关系。\n\n### 声明变量\n\n这里只介绍两种，也是最常用的声明变量的方法。\n\n`let` 用于声明一个变量，`const` 用于声明一个只读的常量。一旦声明，常量的值就不能改变。\n\n```js\nlet a = 1;\nconst b = 1;\n\na++; // 2\nb++; // TypeError: Assignment to constant variable.\n```\n\n这特别说明一下：`const` 对于复合类型的变量，变量名不指向数据，而是指向数据所在的地址。const 命令只是保证变量名指向的地址不变，并不保证该地址的数据不变，所以将一个对象声明为常量必须非常小心。\n\n```js\nconst c = [];\nc.append(1); // [1]\n```\n\n### 基本数据类型\n\n（1）Number\n\n```js\nconst a = 1;\nconst b = 0.5;\nNaN; // not a number\nInfinity; // 最大的数\n```\n\n（2）String\n\n```js\n/* 基本使用 */\nconst a = \"hello world\";\nconst b = \"hello world\";\n\n/* 模版字符串 */\nconst name = \"Jim\",\n  age = 12;\nconst hello = `My name is ${name}, and my age is ${age}`; // My name is Jim, and my age is 12.\n```\n\n（3）Boolean\n\n```js\ntrue;\nfalse;\n```\n\n（4）Array\n\n```js\nconst a = [1, \"string\", false, [2]];\n\na.push(4); // [1, \"string\", false, [2], 4];\na.length; // 5\n```\n\n（5）Object\n\n```js\nconst student = {\n  name: \"Jim\",\n  age: 20,\n  hobbies: [\"basketball\", \"badminton\"],\n  hello: function () {\n    console.log(\"hello\");\n  },\n};\n\nstudent.sex = \"男\";\nstudent.age = 21;\nstudent.hello();\n```\n\n（6）null \u0026\u0026 undefined\n\n```js\nlet a; // undefined\nlet b = null; // null\n```\n\n### 运算符\n\n和 c 语言几乎一样，下面主要介绍一下比较运算符。\n\n```js\na === b; // good\na == b; // bad，不推荐使用\n\na !== b;\n```\n\n### 定义函数\n\n```js\nfunction add(x, y) {\n  return x + y;\n}\n\nconst add = function (x, y) {\n  return x + y;\n};\n\n/* 箭头函数 */\nconst add = (x, y) =\u003e x + y;\n\nconst add = (x, y) =\u003e {\n  return x + y;\n};\n\nadd(1, 1); // 2\n```\n\n### 判断和循环\n\n判断方法和 C 语言中类似。\n\n```js\nif (a === 1) {\n  // something\n} else if (a === 2) {\n  // do something\n} else {\n  // do something\n}\n```\n\n```js\nconst a = [1, 2, 3];\n\nfor (let i = 0; i \u003c a.length; i++) {\n  a[i] = a[i] * 2;\n} // [2, 4, 6]\n\nfor (let item of a) {\n  item = item * 2;\n} // [2, 4, 6]\n\na.forEach(function (item, index) {\n  item = item * 2;\n}); // [2, 4, 6]\n\nconst b = a.map((item, index) =\u003e item * 2);\n// a: [1, 2, 3]\n// b: [2, 4, 6]\n```\n\n### 操作 DOM\n\n我们可以通过 JavaScript 来对 DOM 进行操作。\n\n（1）获得浏览器元素\n\n```js\nconst element = document.querySelectorAll(\"selector\");\n```\n\n（2）获得属性\n\n```js\nelement.getAttribute(\"key\");\n```\n\n（3）设置属性\n\n```js\nelement.setAttribute(\"key\", \"value\");\n```\n\n### 使用方式\n\n这里介绍两种在 HTML 中使用脚本的方式。\n\n（1）外部脚本\n\n```html\n\u003cscript src=\"./app.js\"\u003e\u003c/script\u003e\n```\n\n```js\n// app.js\nconsole.log(\"hello world)\n```\n\n（2）内部脚本\n\n```html\n\u003cscript\u003e\n  console.log(\"hello world\");\n\u003c/script\u003e\n```\n\n点击[这里](https://www.liaoxuefeng.com/wiki/1022910821149312)学习更多。\n\n## 调试方法\n\n这里介绍最简单的调试方法，通过 console.log 打印感兴趣的数据到控制台。\n\n```js\nconst a = [1, 2, 3];\nconsol.log(a);\n```\n\n在浏览器中，这里以 chrome 浏览器为例：点击鼠标右键，选择检查。\n\n![QQ20200221-083410@2x.png](https://i.loli.net/2020/02/21/LlRXqoTYvGSwEDb.png)\n\n## D3\n\n[D3.js](https://d3js.org/) 是一个 JavaScript 库，用于基于数据操作文档。D3 可帮助您使用 HTML、SVG 和 CSS 使数据栩栩如生。D3 对 Web 标准的强调为您提供了现代浏览器的全部功能，而无需将自己与专有框架捆绑在一起，将强大的可视化组件和数据驱动的 DOM 操作方法相结合。\n\n### 为什么学习\n\nD3 是一个比较底层的工具，只有知道了原理，才能更加随性所欲的可视化。\n\n### 介绍\n\n在我看来，我们在通过网页实现数据可视化的时候，就是在数据和 DOM 间建立映射关系（绑定），并且将数据的特征通过 DOM 对应属性（颜色、大小）来进行展示。\n\nD3 在整个流程中都给我提供了工具。下面是安装的方式：\n\n```html\n\u003cscript src=\"https://d3js.org/d3.v5.min.js\"\u003e\u003c/script\u003e\n```\n\n在学习的过程中，希望同学多读[API](https://github.com/d3/d3/blob/master/API.md)和查看[案例](https://observablehq.com/@d3/gallery)。\n\n### 读取和预处理数据\n\n在开发过程中，学要在本地开启服务器才能正常读取数据。下面演示通过 python3 开启一个简单的服务器。\n\n```bash\npython3 -m http.server 8000\n```\n\n这里只演示读取 CSV 格式的数据。\n\n```csv\nname,age\nA,10\nB,20\nC,30\n```\n\n```js\nd3.csv(\"1.csv\", d3.autoType).then(data =\u003e {\n    console.log(data)\n})\n/*\n[\n    {name: \"A\", age: 10},\n    {name: \"B\", age: 20},\n    {name: \"C\", age: 30},\n]\n * /\n```\n\n### 获得 DOM\n\n这里要提到一个 selections 的概念，也就是返回的 DOM 元素。\n\n```js\nconst rectlist = d3.selectAll(\"rect\"); //获得所有的 p 元素\nconst rect = d3.select(\"rect\"); // 获得第一个 p 元素\n```\n\n### 数据和 DOM 绑定\n\n当我们有了数据和 DOM 之后，就可以对它们进行绑定了。\n\n```js\nconst data = [\n  /*... */\n];\nconst selections = d3.selectAll(\"selector\");\n```\n\n我们通过 data 方法对数据进行绑定，并且将绑定好数据的 selections 分为 3 个部分。\n\n![845855-20161020140040467-439041801.png](https://i.loli.net/2020/02/21/2HnOZR1gVBuG9hP.png)\n\n```js\nconst upate = selections.data(data).attr(/***/);\n\nconst enter = update.enter().append(\"rect\");\n\nconst exit = update.exit().remove();\n```\n\n### 将数据的特征映射为 DOM 的属性\n\n到了现在就需要使用到比例尺了，D3 给我们提供了丰富的比例尺，这里只介绍其中两个。\n\n比例尺本质上一个是一个函数。\n\n（1）首先是线性比例尺\n\n![2019042510530490.png](https://i.loli.net/2020/02/21/QmEv3cSRIj4GfBl.png)\n\n```js\nconst y = d3.scaleLinear().domin([1, 5]).range([0, 100]);\n\ny(1); // 0\ny(4); // 75\ny(5); // 100\n```\n\n（2）然后是序数比例尺。\n\n![20190425105335723.png](https://i.loli.net/2020/02/21/k3cRH4LbnwTavNh.png)\n\n```js\nconst x = d3.scaleBand().domain([1, 2, 3, 4]).range([0, 100]);\n\nx(1); // 0\nx(2); // 25\nx(3); // 50\nx(4); // 75\n```\n\n### 设置属性\n\n用了比例尺就可以设置 selections 的属性了。\n\n```js\nenter\n  .attr(\"x\", (d) =\u003e x(d.name))\n  .attr(\"y\", (d) =\u003e y(d.value))\n  .style(\"cursor\", \"pointer\");\n```\n\n### 绑定事件\n\n通过 `on` 方法来绑定事件，注意这里传入的函数不能使用箭头函数。\n\n```js\n// 正确\nenter.on(\"click\", function (d) {\n  // 其中 d 是数据，this 是当前的 DOM\n  console.log(d, this);\n});\n\n// 错误\nenter.on(\"click\", (d) =\u003e {\n  // 这里的 this 是全局对象\n  console.log(this);\n});\n```\n\n### 绘制坐标轴\n\n最后可以添加一些辅助信息，比如坐标轴这些。d3 也给我提供了坐标轴的生成器。\n\n```js\n// 定义坐标生成器\nconst xAxis = (g) =\u003e g.call(d3.axisBottom(x).tickSizeOuter(0));\n\nsvg.append(\"g\").call(xAxis);\n\n// 等同于\nxAxis(svg.append(\"g\"));\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpearmini%2Flearning-d3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpearmini%2Flearning-d3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpearmini%2Flearning-d3/lists"}