D3 样例图系列简介

d3
Created 9/13/2022
Updated 5/19/2023

D3 样例图系列简介

D3 Chart Example 这个系列的文章主要是学习 D3 在 Observable 中的官方样例,逐行 line-by-line 解读样例代码。

主要参考资源
说明

由于 Observable 类似于 Jupyter Notebook,其代码是分为一个个 Cell,而且代码不仅仅包含 JavaScript(有一些方法并不是 D3 模块的 API,而是 Observable 平台内置方法,例如导入文件的方法,并不是使用 d3-fetch 模块)还有一些类似于 HTML 的模板语法,而且存在跨页面导入函数,以及引用其他来源的数据(可能是以附件的方式或引用外部源的方式),因此在 Observable 上的官方样例代码一般与与平台深度耦合,代码不能直接复制搬运应用到项目中。

在解读样例的同时,会基于原始的代码进行修改,以最小化的配置(不依赖 Observable 平台,仅在一般的前端 js 环境)复现这些图表,这样代码就更易于复用,复现的代码会存放在 d3-learning 这个 Github 仓库中。

此外在对原始例子的代码解读后,可能进行适度的简化,让实现代码更精简和通用;也可能对样例进行拓展,例如对于静态图表可能会尝试添加交互功能。

前置准备

首先最基本的一个操作是要在项目中引入 D3

页面缩放

此外在 Observable 中提供了一个标准库 standard library,便于实现一些基础功能。

其中一个常用的功能是监听页面的大小调整,同步更新图表的宽度,这是实现响应式图表的基础,参考其源码写出一个类似的方法:

完整代码和在线交互可以查看这个 Codepen

js
// 获取页面宽度
let width = document.documentElement.clientWidth;
// console.log("init width: ", width);
// 为了优化性能,在核心代码外包了一层防抖函数
// 默认延迟时间是 500 毫秒
let timer = null;
function debounce(delay = 500) {
  if (timer) {
    // (如果倒计时的时间未到,而再次触发 debounce 函数)阻止计时器执行回调函数
    clearTimeout(timer);
  }
  // 重新设置计时器,倒计时重新计算
  timer = setTimeout(function () {
    // 经过延迟后,执行核心代码
    // 获取页面的宽度
    // 也可以是 SVG 元素的宽度,可以将该元素的宽度设置为 width: 100%,让它随页面缩放而变换
    const w = document.documentElement.clientWidth;
    // 修改变量 width(存储当前页面的宽度信息)
    if (w !== width) width = w;
    // console.log(width);
    // 执行完核心代码后,清空计时器 timer
    timer = null;
  }, delay);
}
function resized() {
  // 实际使用防抖函数时,可以设置延迟时间
  // 这里设置为延迟 1000 毫秒
  debounce(1000);
}
// 监听页面调整大小时分发的 resize 事件
function setListener() {
  window.addEventListener("resize", resized);
  // 返回一个函数,其作用是注销监听器
  return function removeListener() {
    window.removeEventListener("resize", resized);
  };
}
const removeListener = setListener();
// 当需要时调用方法注销监听器(例如移除图表时)
// removeListener()

数据托管

另外在进行数据可视化前,需要准备数据,该系列文章的参考样例都是来自 Observable 上的,数据一般会在对应的 Notebook 页面的附件里。

对于小型的数据文件,我一般会从 Observable 下载下来后,再上传到 Github Gist 进行托管,而不是直接将数据内嵌到 JS 脚本中。因为这样可以更好地模拟真实的开发环境,实际项目中一般使用 d3-fetch 模块来读取服务器的数据,让代码更通用。

注意

由于 Github Gist 的限制,对于较大的数据文件(大于 10Mb)可能会采取其他方式导入项目中,会在笔记和源码中另外说明。


Copyright © 2024 Ben

Theme BlogiNote

Icons from Icônes