D3.js 颜色插值完全指南:d3-interpolate 中 interpolateRgb、HSL、Lab、HCL、Cubehelix 与 Hue 插值器详解
2026/9/5 19:15:09 网站建设 项目流程

D3.js 颜色插值完全指南:d3-interpolate 中 interpolateRgb、HSL、Lab、HCL、Cubehelix 与 Hue 插值器详解

【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3

本文以 d3 v7 官方文档docs/d3-interpolate/color.md为核心,系统讲解 d3-interpolate 模块提供的全部颜色插值器:从基础的 RGB 双端插值、多色 B 样条插值,到 HSL/CIELAB/CIELChab/Cubehelix 等感知色彩空间插值与 gamma 校正。读完后你能够:为任意两种颜色构建平滑过渡函数、创建循环(cyclical)颜色比例尺、按需控制色相的最短/长路径,并结合 ColorRamp 渲染组件 的思路在 Canvas 上可视化验证任意插值器的输出。

1. 颜色插值器是什么

d3-interpolate 是一组"插值器工厂"(interpolator factory):你传入起始与结束颜色,它返回一个函数t ∈ [0, 1] → 颜色。这正是 d3 中所有颜色过渡的底层机制——比例尺(d3-scale)、过渡动画(d3-transition)、色板(d3-scale-chromatic)最终都依赖这些函数在两个或多个颜色之间取值。

从仓库结构看,src/index.js 中export * from "d3-interpolate"将本模块全部 API 汇入 d3 主命名空间,因此d3.interpolateRgb等函数在引入整个 d3 包后直接可用;本仓库 package.json 声明其依赖为d3-interpolate: ^3.0.1

所有双端插值器遵循统一约定:

  • 参数ab可以是任何 d3 可解析的颜色输入(字符串、数字色、已解析的颜色对象);
  • 返回的插值器在t = 0处给出颜色a,在t = 1处给出颜色b
  • 返回值统一为RGB 颜色字符串(如rgb(93, 98, 202)),可直接用于 SVG/Canvas/CSS。

下表汇总了docs/d3-interpolate/color.md中列出的全部颜色插值 API:

插值器色彩空间色相路径gamma 支持多色 B 样条变体
interpolateRgbRGBinterpolateRgbBasis/interpolateRgbBasisClosed
interpolateHsl/interpolateHslLongHSL最短 / 长路径
interpolateLabCIELAB
interpolateHcl/interpolateHclLongCIELChab最短 / 长路径
interpolateCubehelix/interpolateCubehelixLongCubehelix最短 / 长路径
interpolateHue色相角(0–360)最短路径

2. interpolateRgb(a, b):默认选择

d3.interpolateRgb("purple", "orange")

在 RGB 色彩空间中对两个颜色做线性插值,并支持可配置的 gamma(缺省为 1.0)。关键特性:

  • 输入不限于 RGBab可以是任何 d3 能解析的颜色(如"hsl(120, 50%, 40%)"、十六进制、d3.hcl(...)对象),内部会先经d3.rgb转换为 RGB 空间(参见 d3-color 文档);
  • 插值器返回 RGB 字符串。

RGB 插值计算简单、速度快,且interpolateRgbd3.interpolate在两个可解析颜色之间的默认实现之一。缺点是在色相差异大时(如紫到橙)可能经过"灰败"的中段,这正是下面各感知色彩空间插值器存在的意义。

3. 多色 B 样条插值:interpolateRgbBasis 与 interpolateRgbBasisClosed

标准插值器只在两个端点之间混合;spline 插值器则在t∈ [0,1] 上用分段多项式函数平滑地穿过多个输入值,目前 d3 仅支持三次均匀非有理 B 样条(cubic uniform nonrational B-spline,即 basis spline)。

3.1 interpolateRgbBasis(colors)

d3.interpolateRgbBasis(["purple", "green", "orange"])

返回一个穿过给定颜色数组的均匀非有理 B 样条插值器,颜色会被转换到 RGB 空间。其隐式控制点保证:

  • t = 0时返回colors[0]
  • t = 1时返回colors[colors.length - 1]

注意:透明度插值目前不受支持。该函数是通用版本 interpolateBasis 在颜色上的特化;d3-scale-chromatic 文档 中有大量基于它构建连续色板的实例(如d3.interpolateRdYlGn等顺序色板本质上都是interpolateRgbBasis对一组精心挑选颜色的封装)。

3.2 interpolateRgbBasisClosed(colors)

d3.interpolateRgbBasisClosed(["purple", "green", "orange"])

interpolateRgbBasis的区别在于控制点会被隐式重复,使样条在t绕 [0,1] 循环时具有C² 连续性——即t = 1t = 0处颜色及其一阶、二阶变化率都平滑衔接。这正是构建循环颜色比例尺(cyclical color scales,如风向、相位、一天中的时刻)的关键工具。透明度插值同样不受支持。其通用版本见 interpolateBasisClosed。

4. 感知色彩空间插值:HSL、Lab、HCL

RGB 是设备空间,人眼对其三个通道的变化并不敏感等权。下面三种插值器在感知均匀性更好的空间中进行过渡,输出仍为 RGB 字符串。

4.1 interpolateHsl(a, b) 与 interpolateHslLong

d3.interpolateHsl("purple", "orange") d3.interpolateHslLong("purple", "orange")

在 HSL 色彩空间插值。输入不限于 HSL,会先经d3.hsl转换(见 d3-color 文档)。行为要点:

  • NaN 通道回填:若某个颜色的色相(hue)或饱和度(saturation)为 NaN,则取对方颜色对应通道的值;
  • 最短色相路径interpolateHsl沿色相环上较短的一侧过渡;
  • interpolateHslLong与它相同,但使用最短路径——当两端色相需要"绕远路"经过互补色区域时(例如从 350° 到 10° 经过红、黄而不是直接跨过 0° 缝隙),使用 Long 变体。

4.2 interpolateLab(a, b)

d3.interpolateLab("purple", "orange")

在 CIELAB 色彩空间插值。CIELAB 设计目标是对人眼感知的均匀性,L通道表示亮度,ab表示色度,因此 Lab 插值通常在中间调上比 RGB 插值更鲜艳、更自然。输入会先经d3.lab转换(见 d3-color 文档)。

4.3 interpolateHcl(a, b) 与 interpolateHclLong

d3.interpolateHcl("purple", "orange") d3.interpolateHclLong("purple", "orange")

在 CIELChab(CIELAB 的柱状表示:亮度 L、色度 C、色相 h)空间插值。输入经d3.hcl转换(见 d3-color 文档)。NaN 处理与最短色相路径语义和 HSL 版本一致:色相或色度为 NaN 时取对方通道值;默认走最短路径,Long 变体不走最短路径。

4.4 如何选择

  • 需要精确控制"沿色相环走哪一边":选 HSL 或 HCL 及其 Long 变体;
  • 追求中间颜色饱满、视觉均匀:选 Lab 或 HCL;
  • 与 CSS/通用工具链兼容性最高、性能优先:选 RGB。

5. Cubehelix 插值与 gamma 校正

5.1 interpolateCubehelix / interpolateCubehelixLong

d3.interpolateCubehelix("purple", "orange") // 配置 gamma d3.interpolateCubehelix.gamma(3)("purple", "orange")

Cubehelix 是一个螺旋形的颜色空间:沿色相旋转的同时亮度单调变化,专为顺序数据(sequential data)设计,能在单色系中同时表达"色相变化 + 明暗层次"。输入会先经d3.cubehelix转换(见 d3-color 文档)。与 HSL/HCL 相同,NaN 通道取对方值、默认最短色相路径;interpolateCubehelixLong为不走最短路径的版本:

d3.interpolateCubehelixLong("purple", "orange") d3.interpolateCubehelixLong.gamma(3)("purple", "orange")

5.2 interpolateColor.gamma(gamma)

d3.interpolateRgb.gamma(2.2)("purple", "orange")

gamma 机制是 d3 颜色插值中最容易被忽视、但影响最大的一个参数。屏幕显示的亮度与存储的像素值之间是 gamma 幂律关系(典型值 2.2)。若在 gamma 校正后的"线性光"空间直接插值,中间颜色会比预期更暗或更亮;d3 的做法是:

  1. pow(γ)将通道值映射到线性空间;
  2. 在线性空间中线性插值;
  3. 再用pow(1/γ)映射回显示空间。

interpolateColor.gamma(γ)适用于三个插值器:interpolateRgb、interpolateCubehelix 和 interpolateCubehelixLong。调用gamma(γ)不修改原插值器,而是返回同类型、带指定 gamma 的新插值器工厂(无副作用的柯里化风格)。关于 gamma 校正的数学原理,可参考文档引用的 Eric Brasseur 的 "Gamma error in picture scaling" 一文。

缺省 gamma 为 1.0,即不做校正的普通线性插值。

6. interpolateHue(a, b):色相角插值

d3.interpolateHue(20, 340)(0.5) // 0

返回两个色相角之间的插值器:

  • 输入是数字(角度)而非颜色;
  • 若某个色相为 NaN,取对方的值;
  • 沿色相环最短路径过渡;
  • 返回值是[0, 360)区间内的数字。

上例中 20° 到 340° 的最短路径是向上跨过 0°:20° → 0°(=360°) → 340°,故t = 0.5时恰为 0。这个插值器常被嵌入自定义插值中,用来单独控制色相通道(例如保持亮度不变、只旋转色相),也是理解 HSL/HCL/Cubehelix 内部色相处理逻辑的参照。

7. 用 Canvas 验证插值器:ColorRamp 的渲染思路

官方文档中每个插值器下方都展示了一条由 组件绘制的渐变色带,其源码在 docs/components/ColorRamp.vue。该组件是一个极小的通用"插值器可视化器",值得学习其实现:

function render(canvas, color, n) { canvas.width = n; canvas.height = 1; const context = canvas.getContext("2d"); for (let i = 0; i < n; ++i) { context.fillStyle = color(i / (n - 1)); // 依次取 t = 0, 1/(n-1), ..., 1 context.fillRect(i, 0, 1, 1); } }
  • 它把插值器当作t → 颜色的纯函数,以n(默认 256)等距采样点铺满一条 1 像素高的画布;
  • 模板部分用image-rendering: pixelated将画布拉伸显示,使色带呈像素化条状,便于肉眼检查插值是否平滑、循环版本在首尾是否连续;
  • 组件接收color(Function)与n(Number)两个 props,任何t → 颜色的插值器都可以直接复用,例如interpolateRgbBasisClosed(['purple', 'green', 'orange'])验证其首尾衔接。

在你的项目里复刻这个模式只需 10 行 Canvas 代码,即可对任意插值器做可视化回归检查。

8. 与周边模块的协作

  • d3-scale-chromatic:全部顺序/发散/循环色板(如d3.interpolateTurbod3.schemeTableau10系列)都是在interpolateRgbBasis/interpolateRgbBasisClosed之上构建的,理解本文的 B 样条小节即可读懂色板源码。参见 d3-scale-chromatic 文档。
  • d3-color:所有"输入颜色不限于目标空间"的自动转换,依赖d3.rgbd3.hsld3.labd3.hcld3.cubehelix五个解析/转换入口。参见 d3-color 文档。
  • d3-transition:过渡动画中颜色属性的默认插值即经由d3.interpolate分发到上述颜色插值器,因此本文的 gamma、最短路径等语义同样作用于动画中间帧。
  • 通用插值器对照interpolateBasis/interpolateBasisClosed的数值版本语义与颜色版本一一对应,见 d3-interpolate 数值插值文档。

9. 实践要点小结

  1. 双端平滑变色默认interpolateRgb;中间色发灰时改用interpolateHsl/interpolateLab/interpolateHcl
  2. 需要"沿色相环走远路"时选用*Long变体(HSL、HCL、Cubehelix 均提供);
  3. 多颜色连续渐变用interpolateRgbBasis,首尾要无缝循环(方向图、时钟刻度)用interpolateRgbBasisClosed
  4. 对亮度一致性要求高的场景(如科学可视化中相邻数据不应有明暗跳变),为interpolateRgbinterpolateCubehelix配置gamma(2.2)
  5. 透明度(opacity)目前未被 B 样条颜色插值器支持,需要透明度过渡时应另行对 alpha 通道插值;
  6. 用 Canvas 等距采样(ColorRamp 思路)在实现后快速目检色带连续性,是低成本高收益的验证手段。

以上 API 以本仓库 d3 v7(d3-interpolate ^3.0.1)为准;interpolateHue的输出范围[0, 360)interpolateRgb缺省 gamma 1.0 等取值细节均可在 docs/d3-interpolate/color.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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询