入門
D3 可在任何 JavaScript 環境中運作。
線上試用 D3
在 Observable 上入門 D3(並取得協助)的最快方法!D3 預設在筆記本中提供,作為 Observable 標準函式庫的一部分。若要使用 D3 建立項目,請從儲存格傳回產生的 DOM 元素。以下是空白的圖表,供您入門
{
// 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();
}
若要取得更完整的範例,請嘗試以下其中一個入門範本
請參閱 D3 範例庫 以取得更多可分岔的範例。
當您按一下 + 新增儲存格時,Observable 會包含一些 D3 片段(儲存格選單開啟時輸入「d3」進行篩選),以及方便的 範例資料集,供您試用 D3 功能。或者,上傳 CSV 或 JSON 檔案,開始使用您的資料。您也可以分岔我們發布的 數百個筆記本 中的任何一個,以取得領先優勢。
Observable 可免費公開使用。註冊 專業帳戶,以連線至私人資料庫、在私人筆記本中協作等等。
在原生 HTML 中使用 D3
在原生 HTML 中,您可以從 CDN(例如 jsDelivr)載入 D3,或者在本地下載。我們建議使用 CDN 托管的 ES 模組套件。但對於有需要的人,我們也提供 UMD 套件,在載入為純文字指令碼時,會匯出 d3
全域變數。
<!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>
<!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>
<!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 模組
<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 捆綁
然後,在UMD + 本機標籤中,建立一個如上所示的 index.html
檔案。使用未壓縮的捆綁進行除錯,並在生產環境中使用壓縮的捆綁以獲得更快的效能。
從 npm 安裝
如果您使用 Node 開發網路應用程式,您可以透過 yarn、npm、pnpm 或您偏好的套件管理員安裝 D3。
yarn add d3
npm install d3
pnpm add d3
然後,您可以將 D3 載入您的應用程式,如下所示
import * as d3 from "d3";
如果您偏好,您可以匯入特定符號
import {select, selectAll} from "d3";
或者,您可以從 D3 子模組安裝並匯入
import {mean, median} from "d3-array";
TypeScript 宣告可透過 DefinitelyTyped 取得。
React 中的 D3
大部分的 D3 模組(包括 d3-scale、d3-array、d3-interpolate 和 d3-format)不會與 DOM 互動,因此在 React 中使用它們時沒有差別。您可以在 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>
);
}
操作 選取 的 D3 模組(包括 d3-selection、d3-transition 和 d3-axis)會操作 DOM,這與 React 的虛擬 DOM 競爭。在這些情況下,您可以將參考附加到元素,並在 useEffect 鉤子中將它傳遞給 D3。
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 的文章。
Svelte 中的 D3
與 React 一樣,如果你喜歡,你可以只使用 Svelte 來進行渲染,並只使用不會操作 DOM 的 D3 模組。以下是使用 d3-shape 和 d3-scale 的數字陣列線性圖。
<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>
Svelte 的反應式陳述式 ($:
) 與 D3 資料結合 搭配得很好,可以有效率地更新。以下我們使用它們來在資料變更時渲染動態軸線。
<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>