d3.linkRadial 径向连线生成器:在 d3-shape 中绘制以原点为中心的极坐标平滑链接
【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3
本篇基于本仓库 docs/d3-shape/radial-link.md 与 docs/d3-shape/link.md 两篇官方文档,系统讲解 d3-shape 的径向链接(radial link)生成器d3.linkRadial():它的角度/半径访问器约定、与笛卡尔链接生成器的逐项对应关系,以及如何继承link的 source/target/context/digits 等完整配置能力。读完后你将能在环形图、辐射树等以原点为中心的场景中,直接生成可用的 SVG path 或 Canvas 绘制指令。
一、径向链接是什么:笛卡尔链接的极坐标版本
D3 的 link 形状用于生成从 source 点到 target 点的平滑三次贝塞尔曲线(cubic Bézier),曲线在起点与终点的切线可以是垂直或水平方向,适合描绘层级树中的父子连线。
而 径向链接生成器就是它的极坐标版本。原文档给出的定义是:
A radial link generator is like the Cartesian link generator except the
xandyaccessors are replaced withangleandradiusaccessors.
也就是说,两者的差异仅在于坐标约定:笛卡尔链接用x/y访问器描述点的水平、垂直坐标;径向链接则把这两个访问器替换为angle(角度)与radius(半径)访问器,点的位置改由"相对于原点的角度 + 到原点的距离"确定。docs/d3-shape.md 在形状生成器总览中也将三者并列为:Links(笛卡尔)、Radial lines(极坐标线)、Radial links(极坐标链接),并注明 Radial links "like link, but in polar coordinates"。
这一对应关系可以整理为下表:
笛卡尔链接d3.link | 径向链接d3.linkRadial | 语义 |
|---|---|---|
*link*.x(x) | *linkRadial*.angle(angle) | 访问器返回点的角度,单位为弧度 |
*link*.y(y) | *linkRadial*.radius(radius) | 访问器返回点到原点的距离 |
文档同时强调了一条关键布局事实:径向链接是相对原点(origin)定位的,若要移动原点,应使用 SVG transform 属性,而不是改写访问器数值。这一点决定了在<g transform="translate(cx, cy)">分组内绘制径向链接时,曲线始终以该分组变换后的原点为中心向外展开——这正是环形/辐射状图表所需要的行为。
二、创建径向链接生成器:linkRadial()
2.1 基本用法
linkRadial()返回一个带径向切线(radial tangents)的新 link generator。官方文档给出的示例,是把它用于"根节点位于显示区域中心"的树形图中:
const link = d3.linkRadial() .angle((d) => d.x) .radius((d) => d.y);这里值得注意的映射约定是:层级布局结果中的x字段传入angle,y字段传入radius。这与 docs/d3-shape/link.md 中为顶部根树给出的笛卡尔示例形成对照——后者用.x((d) => d.x).y((d) => d.y)把同一对坐标当水平/垂直分量使用。同一个层级布局对象,只是按不同坐标系解释,即可在"上侧根树"与"中心根辐射树"两种形态间切换。
2.2 默认的 source/target 约定
*link*调用时若不提供自定义访问器,默认约定输入对象具有source与target属性(见 docs/d3-shape/link.md 中*link*(...arguments*)一节)。由于linkRadial()返回的同样是一个 link generator,且文档明确angle/radius分别"等价于"link.x/link.y,可以推断linkRadial()同样接受{source, target}形式的链接对象。结合 hierarchy 布局产出的链接数据(每个 link 持有source/target节点),典型的渲染写法是:
const link = d3.linkRadial() .angle((d) => d.x) .radius((d) => d.y); // links: [{ source: node, target: node }, ...] d3.select("svg").selectAll("path.link") .data(links) .join("path") .attr("d", link);attr("d", link)会把链接对象作为参数传入生成器,返回一条 path data 字符串;每个 link 对象上的source/target节点携带的x/y分别被解读为角度与半径。
三、*linkRadial*.angle(angle):角度访问器
*linkRadial*.angle(*angle*)等价于*link*.x,区别在于访问器返回值是以弧度(radians)为单位的角度。文档同时给出了角度零点的约定:
0 at -y(12 o'clock)
即角度 0 指向负y方向——屏幕坐标系的正上方("12 点钟"方向),角度按常规顺时针/逆时针约定从该基准测量。与笛卡尔版本一致,angle访问器既可设置为函数也可设置为数值;调用linkRadial.angle()不带参数时返回当前访问器。因此当角度需要经过比例尺映射时(例如把归一化的层级角域映射到 0–2π),写法与link.x完全同构:
const link = d3.linkRadial() .angle((d) => angle(d.x)); // angle: 角度比例尺 .radius((d) => d.y);四、*linkRadial*.radius(radius):半径访问器
*linkRadial*.radius(*radius*)等价于*link*.y,访问器返回半径:点到原点的距离(the distance from the origin)。半径通常由层级深度直接给出或经比例尺缩放;半径越大,点离中心越远,这与环形图中"越深的节点离圆心越远"的直观布局一致:
const link = d3.linkRadial() .angle((d) => d.x) .radius((d) => rScale(d.y)); // rScale: 半径比例尺,可选angle与radius两个访问器组合起来,就完整确定了 source 与 target 两个点在极坐标系中的位置,生成器据此计算径向切线并输出三次贝塞尔曲线。
五、继承自 link 的其余 API:source、target、context、digits
由于linkRadial()返回的是一个 link generator,且angle/radius分别"等价于"x/y访问器,从文档表述可以推断:docs/d3-shape/link.md 中描述的其余访问器在径向链接上同样可用,语义保持一致。
*linkRadial*.source(*source*)/*linkRadial*.target(*target*):设置 source/target 访问器。默认访问器分别为function source(d) { return d.source; }与function target(d) { return d.target; };若输入不是{source, target}结构,可用link.source((d) => d[0]).target((d) => d[1])这类自定义访问器改取字段。*linkRadial*.context(*context*):设置渲染上下文。默认为null,此时调用生成器返回path data 字符串;若传入 Canvas 2D context,则生成的链接通过一串 path 方法调用 直接绘制到该上下文。用法与link.context相同:
const context = canvas.getContext("2d"); const link = d3.linkRadial().context(context);*linkRadial*.digits(*digits*):设置小数点后的最大位数,默认 3。该选项仅在context为null(即生成 path data 字符串)时生效:
const link = d3.linkRadial().digits(3); // 等价于默认值 link.digits(); // 3六、移动原点:用 transform 而非改坐标
文档明确提示:径向链接相对原点定位,改变原点应使用 SVG 的 transform。实践中通常把生成器产出的路径放进一个已平移到画布中心的分组中:
const g = d3.select("svg").append("g") .attr("transform", `translate(${width / 2}, ${height / 2})`); g.selectAll("path.link") .data(links) .join("path") .attr("d", link) // link 为上面配置的 d3.linkRadial() .attr("fill", "none") .attr("stroke", "#999");这样angle = 0(12 点钟方向)与radius都以(width / 2, height / 2)为圆心展开,无需在访问器里做任何坐标偏移计算。
七、在 d3 7.9.0 仓库中的位置与出处
本仓库是 D3 的聚合发布包:package.json 声明版本 7.9.0,依赖d3-shape: ^3.2.0;src/index.js 以export * from "d3-shape";的形式将径向链接等全部形状生成器重新导出,因此d3.linkRadial在整包d3命名空间下直接可用。相关文档入口有三处可互相印证:
- docs/d3-shape/radial-link.md:本篇正文依据,定义
linkRadial()、*linkRadial*.angle、*linkRadial*.radius三个 API; - docs/d3-shape/link.md:笛卡尔链接生成器完整参考(curve 参数、
linkVertical()/linkHorizontal()、source/target/x/y/context/digits 访问器),是理解径向链接"等价于"表述的配套文档; - docs/api.md:API 总索引中列出
d3.linkRadial、*linkRadial*.angle、*linkRadial*.radius三条条目,分别指回上述锚点。
此外,test/docs-test.js 会在mocha测试中校验全部文档内部链接与锚点的有效性,说明 docs/d3-shape/radial-link.md 中#linkRadial、#linkRadial_angle、#linkRadial_radius等锚点与跨文档引用(如link.md#link_x)是被仓库测试持续保证的。
八、要点回顾
d3.linkRadial()是笛卡尔d3.link的极坐标版本:x/y访问器被替换为angle(弧度,0 指向 12 点钟方向)与radius(到原点的距离)两个访问器;- 层级布局结果按
.angle((d) => d.x).radius((d) => d.y)映射,即可为中心根辐射树生成平滑三次贝塞尔链接; linkRadial沿用link的 source/target 默认约定,并继承context()(Canvas 渲染或 path data 字符串)与digits()(默认 3 位小数)等配置;- 移动圆心请使用 SVG transform,而非修改角度/半径数值;
- 出处以当前仓库 v7.9.0 的 docs/d3-shape/radial-link.md 与 docs/d3-shape/link.md 为准。
【免费下载链接】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),仅供参考