
如何在 Svelte 中结合 D3 构建响应式折线图【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3在 Svelte 项目里用 D3 画折线图并且让图表随数据变化自动更新是 D3 官方文档明确支持的一种集成方式。docs/getting-started.md 的 “D3 in Svelte” 章节给出了两个完整的LinePlot.svelte组件示例第一个只使用不操作 DOM 的 D3 模块d3-shape、d3-scale由 Svelte 全权负责渲染第二个在此基础上用 Svelte 的$:响应式语句驱动 d3-axis让坐标轴随数据变化重绘。前提是你已有一个 Svelte 项目并通过包管理器安装了 D3。官方文档给出的两条集成路线D3 文档在 docs/what-is-d3.md 中把模块按是否触碰 DOM 做了区分selections 类模块d3-selection、d3-transition 等直接修改 DOM而 scales、shapes 类模块“only operate on data”。Svelte 章节沿用了同样的边界原文以 React 为参照说明 Svelte 可“exclusively for rendering”只使用不操作 DOM 的 D3 模块因此组合方式只有两种纯声明式D3 只做比例尺和形状生成SVG 全部写在 Svelte 模板里不引入任何 DOM 操作响应式混合对 d3-axis 这类必须操作 DOM 的模块用bind:this把元素交给 D3并用$:语句保证数据变化时重新执行。折线图恰好需要两者d3-scale d3-shape 计算折线路径d3-axis 绘制坐标轴。准备 D3 依赖在项目根目录用包管理器安装 D3docs/getting-started.md 给出了三种方式npm install d3yarn add d3pnpm add d3组件内导入import * as d3 from d3;第一步纯渲染的折线图组件官方第一个示例是“a line plot of an array of numbers”只依赖 d3.line 和 d3.scaleLinear。比例尺和折线生成器都写成$:响应式语句依赖data以及宽高、边距 props!-- LinePlot.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 fillnone strokecurrentColor stroke-width1.5 d{line(data)} / g fillwhite strokecurrentColor stroke-width1.5 {#each data as d, i} circle key{i} cx{x(i)} cy{y(d)} r2.5 / {/each} /g /svg这个组件的关键点line(data)返回 path data 字符串直接赋给d属性不需要手动创建或修改 SVG 节点{#each}负责数据点的增删cx/cy由比例尺计算因为x、y、line都是$:语句data或width/height等 prop 变化时会重新计算路径与数据点随之更新——这就是“响应式”的实现机制不需要任何手动刷新逻辑。组件对外只需一个数字数组data宽高和边距都有默认值文档描述它即“an array of numbers”的折线图。第二步用响应式语句加入动态坐标轴第一个示例没有坐标轴。官方第二个示例引入 d3-axis用bind:this拿到两个g的 DOM 引用把d3.select(...).call(...)写进$:语句数据变化导致比例尺重算时轴也会被重新渲染!-- LinePlot.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} transformtranslate(0,{height - marginBottom}) / g bind:this{gy} transformtranslate({marginLeft},0) / path fillnone strokecurrentColor stroke-width1.5 d{line(data)} / g fillwhite strokecurrentColor stroke-width1.5 {#each data as d, i} circle key{i} cx{x(i)} cy{y(d)} r2.5 / {/each} /g /svg注意上面两个g的transform属性是 docs/getting-started.md 原文示例的写法本文保持原样。按 Svelte 语法双引号属性是普通字符串其中的{height - marginBottom}、{marginLeft}不会被插值实际平移不会生效。若要在本地跑起来需改成单引号属性并对表达式加花括号例如g bind:this{gx} transformtranslate(0,{height - marginBottom}) / g bind:this{gy} transformtranslate({marginLeft},0) /文档对第二个示例的定位是“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 在线 REPL / Playground 入口见 docs/getting-started.md Svelte 章节代码块后的 “REPL ↗︎” 链接可直接粘贴运行。本地验证时的判断依据第一个示例SVG 中出现一条path和与data等量的circle数据点位置与比例尺一致第二个示例修改data或宽高、边距 props后坐标轴随之重绘。文档将这一行为表述为 “render dynamic axes as the data changes”这是第二个示例应当观察到的现象。边界与下一步纯声明式路线只覆盖折线和数据点。需要坐标轴时必须引入 d3-axisDOM 操作类模块改用第二步的bind:this交接方式文档同时指出D3 输出的是标准 SVG可以用外部样式表调整图表外观包括配合 media queries 做响应式布局见 docs/what-is-d3.md因此容器级响应式可交给 CSS 处理如果数据变化时需要更精细的 enter/update/exit 控制继续阅读 data joins 章节selection.data/selection.join允许你通过 key 函数自行决定数据与元素的匹配策略从而“minimize changes to the DOM to optimize performance”。【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考