Skip to content

入门

🌐 Getting started

D3 可在任何 JavaScript 环境中运行。

🌐 D3 works in any JavaScript environment.

在线试用 D3

🌐 Try D3 online

开始使用 D3(并获得帮助)最快的方法是在 Observable 上!D3 在注意本中默认可用,作为 Observable 标准库的一部分。要使用 D3 创建内容,请从单元格中返回生成的 DOM 元素。下面是一个空白图表,供你开始使用:

🌐 The fastest way to get started (and get help) with D3 is on Observable! D3 is available by default in notebooks as part of Observable’s standard library. To create something with D3, return the generated DOM element from a cell. Here is a blank chart to get you started:

js
{
  // Declare the chart dimensions and margins.
  const width = 640;
  const height = 400;
  const marginTop = 20;
  const marginRight = 20;
  const marginBottom = 30;
  const marginLeft = 40;

  // Declare the x (horizontal position) scale.
  const x = d3.scaleUtc()
      .domain([new Date("2023-01-01"), new Date("2024-01-01")])
      .range([marginLeft, width - marginRight]);

  // Declare the y (vertical position) scale.
  const y = d3.scaleLinear()
      .domain([0, 100])
      .range([height - marginBottom, marginTop]);

  // Create the SVG container.
  const svg = d3.create("svg")
      .attr("width", width)
      .attr("height", height);

  // Add the x-axis.
  svg.append("g")
      .attr("transform", `translate(0,${height - marginBottom})`)
      .call(d3.axisBottom(x));

  // Add the y-axis.
  svg.append("g")
      .attr("transform", `translate(${marginLeft},0)`)
      .call(d3.axisLeft(y));

  // Return the SVG element.
  return svg.node();
}

作为一个更完整的示例,请尝试以下入门模板之一:

🌐 As a more complete example, try one of these starter templates:

查看 D3 图库 了解更多可分支的示例。

🌐 See the D3 gallery for more forkable examples.

当你点击 + 添加单元格时,Observable 包含一些 D3 片段(当单元格菜单打开时输入“d3”以过滤),以及方便的 示例数据集 用于尝试 D3 功能。你也可以上传 CSV 或 JSON 文件开始操作你的数据。你还可以从我们发布的 数百个注意本 中任意分支以快速入门。

🌐 Observable includes a few D3 snippets when you click + to add a cell (type “d3” when the cell menu is open to filter), as well as convenient sample datasets to try out D3 features. Or upload a CSV or JSON file to start playing with your data. You can also fork any of the hundreds of notebooks we’ve published for a head start.

Observable 对公众免费开放。注册一个 Pro 账户 可连接到私有数据库,在私有注意本上协作等。

🌐 Observable is free for public use. Sign up for a Pro account to connect to private databases, collaborate on private notebooks, and more.

原生 HTML 中的 D3

🌐 D3 in vanilla HTML

在原生 HTML 中,你可以从 CDN(如 jsDelivr)加载 D3,或将其下载到本地。我们推荐使用 CDN 托管的 ES 模块包。但对于有需要的人,我们也提供一个 UMD 包,在作为普通脚本加载时会导出 d3 全局变量。

🌐 In vanilla HTML, you can load D3 from a CDN such as jsDelivr or you can download it locally. We recommend using the CDN-hosted ES module bundle. But for those who need it, we also provide a UMD bundle that exports the d3 global when loaded as a plain script.

html
<!DOCTYPE html>
<div id="container"></div>
<script type="module">

import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";

// Declare the chart dimensions and margins.
const width = 640;
const height = 400;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 30;
const marginLeft = 40;

// Declare the x (horizontal position) scale.
const x = d3.scaleUtc()
    .domain([new Date("2023-01-01"), new Date("2024-01-01")])
    .range([marginLeft, width - marginRight]);

// Declare the y (vertical position) scale.
const y = d3.scaleLinear()
    .domain([0, 100])
    .range([height - marginBottom, marginTop]);

// Create the SVG container.
const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height);

// Add the x-axis.
svg.append("g")
    .attr("transform", `translate(0,${height - marginBottom})`)
    .call(d3.axisBottom(x));

// Add the y-axis.
svg.append("g")
    .attr("transform", `translate(${marginLeft},0)`)
    .call(d3.axisLeft(y));

// Append the SVG element.
container.append(svg.node());

</script>
html
<!DOCTYPE html>
<div id="container"></div>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script type="module">

// Declare the chart dimensions and margins.
const width = 640;
const height = 400;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 30;
const marginLeft = 40;

// Declare the x (horizontal position) scale.
const x = d3.scaleUtc()
    .domain([new Date("2023-01-01"), new Date("2024-01-01")])
    .range([marginLeft, width - marginRight]);

// Declare the y (vertical position) scale.
const y = d3.scaleLinear()
    .domain([0, 100])
    .range([height - marginBottom, marginTop]);

// Create the SVG container.
const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height);

// Add the x-axis.
svg.append("g")
    .attr("transform", `translate(0,${height - marginBottom})`)
    .call(d3.axisBottom(x));

// Add the y-axis.
svg.append("g")
    .attr("transform", `translate(${marginLeft},0)`)
    .call(d3.axisLeft(y));

// Append the SVG element.
container.append(svg.node());

</script>
html
<!DOCTYPE html>
<div id="container"></div>
<script src="d3.js"></script>
<script type="module">

// Declare the chart dimensions and margins.
const width = 640;
const height = 400;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 30;
const marginLeft = 40;

// Declare the x (horizontal position) scale.
const x = d3.scaleUtc()
    .domain([new Date("2023-01-01"), new Date("2024-01-01")])
    .range([marginLeft, width - marginRight]);

// Declare the y (vertical position) scale.
const y = d3.scaleLinear()
    .domain([0, 100])
    .range([height - marginBottom, marginTop]);

// Create the SVG container.
const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height);

// Add the x-axis.
svg.append("g")
    .attr("transform", `translate(0,${height - marginBottom})`)
    .call(d3.axisBottom(x));

// Add the y-axis.
svg.append("g")
    .attr("transform", `translate(${marginLeft},0)`)
    .call(d3.axisLeft(y));

// Append the SVG element.
container.append(svg.node());

</script>

你还可以像这样导入和解构单个 D3 模块:

🌐 You can also import and destructure individual D3 modules like so:

html
<script type="module">

import {forceSimulation, forceCollide, forceX} from "https://cdn.jsdelivr.net/npm/d3-force@3/+esm";

const nodes = [{}, {}];
const simulation = forceSimulation(nodes)
    .force("x", forceX())
    .force("collide", forceCollide(5))
    .on("tick", () => console.log(nodes[0].x));

</script>

如果你希望在本地(或离线)运行 D3,你可以在此处下载 D3 的 UMD 软件包:

🌐 If you’d prefer to run D3 locally (or offline), you can download the UMD bundles of D3 here:

然后,如上所示在 UMD + 本地 标签中创建一个 index.html 文件。调试时使用未压缩的包,生产中为更快的性能使用压缩包。

🌐 Then, create an index.html file as shown above in the UMD + local tab. Use the non-minified bundle for debugging, and the minified bundle for faster performance in production.

从 npm 安装

🌐 Installing from npm

如果你正在使用 Node 开发 Web 应用,你可以通过 yarn、npm、pnpm 或你喜欢的包管理器安装 D3。

🌐 If you’re developing a web application using Node, you can install D3 via yarn, npm, pnpm, or your preferred package manager.

bash
yarn add d3
bash
npm install d3
bash
pnpm add d3

然后,你可以将 D3 加载到你的应用中:

🌐 You can then load D3 into your app as:

js
import * as d3 from "d3";

如果你愿意,也可以导入特定的符号:

🌐 You can instead import specific symbols if you prefer:

js
import {select, selectAll} from "d3";

或者,你可以安装并导入 D3 子模块:

🌐 Alternatively you can install and import from D3 submodules:

js
import {mean, median} from "d3-array";

TypeScript 声明可通过 DefinitelyTyped 获取。

🌐 TypeScript declarations are available via DefinitelyTyped.

React 中的 D3

🌐 D3 in React

大多数 D3 模块(包括 d3-scaled3-arrayd3-interpolated3-format)不与 DOM 交互,因此在 React 中使用它们没有区别。你可以在 JSX 中将它们用于纯声明式的可视化,例如下面的折线图。

🌐 Most D3 modules (including d3-scale, d3-array, d3-interpolate, and d3-format) don’t interact with the DOM, so there is no difference when using them in React. You can use them in JSX for purely declarative visualization, such as the line plot below.

jsx
import * as d3 from "d3";

export default function LinePlot({
  data,
  width = 640,
  height = 400,
  marginTop = 20,
  marginRight = 20,
  marginBottom = 20,
  marginLeft = 20
}) {
  const x = d3.scaleLinear([0, data.length - 1], [marginLeft, width - marginRight]);
  const y = d3.scaleLinear(d3.extent(data), [height - marginBottom, marginTop]);
  const line = d3.line((d, i) => x(i), y);
  return (
    <svg width={width} height={height}>
      <path fill="none" stroke="currentColor" strokeWidth="1.5" d={line(data)} />
      <g fill="white" stroke="currentColor" strokeWidth="1.5">
        {data.map((d, i) => (<circle key={i} cx={x(i)} cy={y(d)} r="2.5" />))}
      </g>
    </svg>
  );
}

沙盒 ↗︎

selections 进行操作的 D3 模块(包括 d3-selectiond3-transitiond3-axis)确实会操作 DOM,这会与 React 的虚拟 DOM 产生竞争。在这些情况下,你可以将 ref 附加到一个元素上,并在 useEffect 钩子中将其传递给 D3。

🌐 D3 modules that operate on selections (including d3-selection, d3-transition, and d3-axis) do manipulate the DOM, which competes with React’s virtual DOM. In those cases, you can attach a ref to an element and pass it to D3 in a useEffect hook.

jsx
import * as d3 from "d3";
import {useRef, useEffect} from "react";

export default function LinePlot({
  data,
  width = 640,
  height = 400,
  marginTop = 20,
  marginRight = 20,
  marginBottom = 30,
  marginLeft = 40
}) {
  const gx = useRef();
  const gy = useRef();
  const x = d3.scaleLinear([0, data.length - 1], [marginLeft, width - marginRight]);
  const y = d3.scaleLinear(d3.extent(data), [height - marginBottom, marginTop]);
  const line = d3.line((d, i) => x(i), y);
  useEffect(() => void d3.select(gx.current).call(d3.axisBottom(x)), [gx, x]);
  useEffect(() => void d3.select(gy.current).call(d3.axisLeft(y)), [gy, y]);
  return (
    <svg width={width} height={height}>
      <g ref={gx} transform={`translate(0,${height - marginBottom})`} />
      <g ref={gy} transform={`translate(${marginLeft},0)`} />
      <path fill="none" stroke="currentColor" strokeWidth="1.5" d={line(data)} />
      <g fill="white" stroke="currentColor" strokeWidth="1.5">
        {data.map((d, i) => (<circle key={i} cx={x(i)} cy={y(d)} r="2.5" />))}
      </g>
    </svg>
  );
}

沙盒 ↗︎

有关在 React 中使用 D3 的更多指南,请参阅 Amelia Wattenberger 的文章

🌐 For more guidance using D3 in React, see Amelia Wattenberger’s post.

Svelte 中的 D3

🌐 D3 in Svelte

React 一样,如果你愿意,你可以只使用 Svelte 进行渲染,并且只使用不会操作 DOM 的 D3 模块。这里是一个数字数组的折线图,它使用了 d3-shaped3-scale

🌐 As with React, you can use Svelte exclusively for rendering if you like, and only use D3 modules that don’t manipulate the DOM. Here is a line plot of an array of numbers that uses d3-shape and d3-scale.

svelte
<script>
  import * as d3 from 'd3';

  export let data;
  export let width = 640;
  export let height = 400;
  export let marginTop = 20;
  export let marginRight = 20;
  export let marginBottom = 20;
  export let marginLeft = 20;

  $: x = d3.scaleLinear([0, data.length - 1], [marginLeft, width - marginRight]);
  $: y = d3.scaleLinear(d3.extent(data), [height - marginBottom, marginTop]);
  $: line = d3.line((d, i) => x(i), y);
</script>
<svg width={width} height={height}>
  <path fill="none" stroke="currentColor" stroke-width="1.5" d={line(data)} />
  <g fill="white" stroke="currentColor" stroke-width="1.5">
    {#each data as d, i}
      <circle key={i} cx={x(i)} cy={y(d)} r="2.5" />
    {/each}
  </g>
</svg>

REPL ↗︎

Svelte 的响应式语句($:)与 D3 数据绑定 很好地配合,用于高效更新。下面,我们使用它们在数据变化时渲染动态轴。

🌐 Svelte’s reactive statements ($:) pair nicely with D3 data joins for efficient updates. Below, we use them to render dynamic axes as the data changes.

svelte
<script>
  import * as d3 from 'd3';

  export let data;
  export let width = 640;
  export let height = 400;
  export let marginTop = 20;
  export let marginRight = 20;
  export let marginBottom = 30;
  export let marginLeft = 40;

  let gx;
  let gy;

  $: x = d3.scaleLinear([0, data.length - 1], [marginLeft, width - marginRight]);
  $: y = d3.scaleLinear(d3.extent(data), [height - marginBottom, marginTop]);
  $: line = d3.line((d, i) => x(i), y);
  $: d3.select(gy).call(d3.axisLeft(y));
  $: d3.select(gx).call(d3.axisBottom(x));
</script>
<svg width={width} height={height}>
  <g bind:this={gx} transform="translate(0,{height - marginBottom})" />
  <g bind:this={gy} transform="translate({marginLeft},0)" />
  <path fill="none" stroke="currentColor" stroke-width="1.5" d={line(data)} />
  <g fill="white" stroke="currentColor" stroke-width="1.5">
    {#each data as d, i}
      <circle key={i} cx={x(i)} cy={y(d)} r="2.5" />
    {/each}
  </g>
</svg>

REPL ↗︎