G6 连续色板(Continuous Palette)完全指南:基于数值字段的映射取色
2026/9/23 15:23:14 网站建设 项目流程

G6 连续色板(Continuous Palette)完全指南:基于数值字段的映射取色

【免费下载链接】G6♾ A Graph Visualization Framework in JavaScript.项目地址: https://gitcode.com/gh_mirrors/g6/G6

G6 的色板(Palette)机制用于为节点、边等元素自动分配颜色。其中连续色板(type: 'value'与离散色板(type: 'group')相对应,它不再按"分组"取色,而是根据元素的数值型字段(如吞吐量、温度、风险评分)在[0, 1]区间上归一化后映射为颜色,从而形成类似热力图的渐变视觉。读完本文,你将掌握连续色板的配置写法、color函数入参语义、内置色板的使用方式,以及它在 G6 渲染管线中的底层实现原理,可直接用于构建"数值越大颜色越深/越红"一类的数据可视化场景。

一、理解两种取色模式:分组(group)与数值(value)

G6 的色板配置(node.palette/edge.palette/combo.palette)支持两种核心取色方式,它们的区别在于决定颜色的依据是什么

模式type取色依据典型场景
分类取色'group'按某个字段的值分组,每组分配一种颜色按类别/部门/状态着色
连续取色'value'按数值字段的大小线性映射颜色热度图、风险等级、数值排名

离散模式(group)的标准配置如下(见 标准配置示例),它把category字段值相同的节点归为一组,再从tableau色板中按组序取色:

import { Graph } from '@antv/g6'; const graph = new Graph({ container: 'container', width: 200, height: 50, data: { nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C'][i % 3] } })), }, layout: { type: 'grid', cols: 6 }, node: { palette: { type: 'group', field: 'category', color: 'tableau', }, }, }); graph.render();

而连续模式(value)则不关心"组",它只关注数值的大小关系,这正是本文的主角。

二、连续色板的标准配置(核心示例)

来自 continuous-palette.md 的官方示例,展示了连续色板最直接的用法——通过一个颜色函数把节点数值映射成颜色:

import { Graph } from '@antv/g6'; const graph = new Graph({ container: 'container', width: 200, height: 50, data: { nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i}`, data: { value: (i + 1) * 20 } })), }, layout: { type: 'grid', cols: 6 }, node: { palette: { type: 'value', field: 'value', color: (value) => `rgb(${value * 255}, 0, 0)`, }, }, }); graph.render();

示例中 6 个节点的data.value分别为20, 40, 60, 80, 100, 120,经过归一化后,color函数接收到的入参依次增大,最终输出的rgb红色通道也随之变强——节点的红度直观表达了数值高低。

各配置项含义如下:

配置项类型说明
type'value'声明为连续取色模式(按字段值映射)
fieldstring \| ((datum) => string)取值字段名,指向datum.data上的数值属性,如'value';也支持传入函数
color(ratio: number) => string颜色映射函数,接收归一化后的比例值,返回任意合法颜色字符串
invertboolean是否倒序取色,默认false

三、color函数接收的到底是什么?——归一化原理

这是连续色板最容易被误解的地方:color函数收到的不是原始字段值,而是归一化到[0, 1]区间的比例值

在类型定义中,连续色板的签名被明确描述为(见 packages/g6/src/palettes/types.ts):

export type ContinuousPalette = (ratio: number) => string;

归一化逻辑位于 packages/g6/src/utils/palette.ts 的assignColorByPalette函数中:

} else if (type === 'value') { const [min, max] = data.reduce( ([min, max], datum) => { const value = parseField(field, datum); if (typeof value !== 'number') throw new Error(format(`Palette field ${field} is not a number`)); return [Math.min(min, value), Math.max(max, value)]; }, [Infinity, -Infinity], ); const range = max - min; return assignColor( data.map((datum) => [datum.id, ((parseField(field, datum) as number) - min) / range]), ); }

从源码可以提炼出连续取色的完整流程:

  1. 遍历所有元素,读取field指定的字段值(字段可来自datum.data,即parseField对字符串字段名取datum.data[field]);
  2. 求出全局最小值min与最大值max,计算区间宽度range = max - min
  3. 对每个元素计算归一化比例ratio = (value - min) / range,该值恒落在[0, 1]内;
  4. ratio作为入参调用color函数(连续色板),得到该元素的最终颜色。

也就是说,示例中value = 20的节点归一化比例接近0,而value = 120的节点接近1,因此color函数在两端分别生成接近黑色与接近鲜红(rgb(255,0,0))的颜色。

同时注意两点细节:

  • 字段值必须是数字:源码在归一化前会校验类型,若字段值不是number,会抛出Palette field ... is not a number错误;
  • 支持倒序:当invert: true时,实际传给函数的是1 - ratio(见 packages/g6/src/utils/palette.ts),实现"数值越大颜色越浅"的反向映射。

四、连续色板同样支持内置色板与注册机制

color配置除了直接传函数,还可以传色板名称字符串颜色数组。G6 内置了 5 套开箱即用的色板(见 packages/g6/src/palettes/index.ts):

内置色板名颜色数视觉特征
spectral11冷到暖的彩虹渐变(青 → 黄 → 红)
tableau10Tableau 经典分类色
oranges9橙色系单色渐变
greens9绿色系单色渐变
blues9蓝色系单色渐变

这些色板在初始化时被注册进内置扩展注册表(见 packages/g6/src/registry/build-in.ts):

palette: { spectral, tableau, oranges, greens, blues, },

color传入字符串时,底层会通过getExtension('palette', colorPalette)从注册表解析出色板实体(见 packages/g6/src/utils/palette.ts)。这也意味着你可以在 packages/g6/src/registry/register.ts 中注册自定义色板,从而在任意图上复用。

简写形式:如果完全不写配置对象、只给色板名,比如默认配置示例(见 默认配置示例):

node: { palette: 'spectral', },

此时parsePalette会把它解析成"按id分组的离散色板"(见 packages/g6/src/utils/palette.ts)。因此,字符串/数组形式本质上服务于group离散取色;要进行连续取色,请使用type: 'value'+ 函数形式的color

五、类型定义速查:完整配置结构

色板配置的类型体系定义在 packages/g6/src/spec/element/palette.ts,摘录核心结构如下:

export type PaletteOptions = Palette | CategoricalPaletteOptions | ContinuousPaletteOptions; export type STDPaletteOptions = CategoricalPaletteOptions | ContinuousPaletteOptions; interface ContinuousPaletteOptions extends BasePaletteOptions { type?: 'value'; // 基于字段值取色 field?: string | ((datum: ElementDatum) => string); // 取值字段 } export interface BasePaletteOptions { color?: Palette; // 色板颜色:色板名 / 颜色数组 / 函数 invert?: boolean; // 倒序取色 }

其中Palette(见 packages/g6/src/palettes/types.ts)的完整联合类型为:

export type Palette = string | BuiltInPalette | CategoricalPalette | ContinuousPalette; export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues'; export type CategoricalPalette = string[]; export type ContinuousPalette = (ratio: number) => string;

注意类型定义中field的声明为string | ((datum) => string),但连续取色时字段值会被当作数字参与归一化——传入字符串形式的字段名时,必须确保datum.data上对应的值类型为数字

六、色板在渲染管线中的工作流程

色板并不是在元素绘制时才临时算色,而是在渲染前集中计算并缓存。从 packages/g6/src/runtime/element.ts 的实现可以看出完整链路:

private computePaletteStyle() { const { options } = this.context; this.paletteStyle = {}; this.forEachElementData((elementType, elementData) => { const palette = Object.assign( {}, parsePalette(this.getTheme(elementType)?.palette), // 1. 主题级色板 parsePalette(options[elementType]?.palette), // 2. 元素级配置覆盖 ); if (palette?.field) { Object.assign(this.paletteStyle, assignColorByPalette(elementData, palette)); } }); }

要点如下:

  1. 色板可以配置在主题(theme)上,作为全局默认;元素级配置(node.palette等)通过Object.assign覆盖主题色板,遵循"元素级 > 主题级"的优先级;
  2. 只有配置了field才会触发取色——field是色板生效的开关,缺省时色板不参与颜色计算;
  3. 计算结果按元素id缓存paletteStyle字典中,同组元素共享同一颜色;
  4. 最终取色通过getPaletteStyle应用到样式上(见 packages/g6/src/runtime/element.ts):节点/组合用fill,边用stroke,且该颜色与themeStyledataStylestateStyle等按序合并(见 packages/g6/src/runtime/element.ts),因此后续手动设置的样式、交互状态(hover/选中)仍可覆盖色板颜色。

七、实战建议与注意事项

  • 连续色板首选函数式color:由于value模式下传入的是归一化比例,用(ratio) => \rgb(...)`这类函数可以精确控制渐变端点;若必须使用内置色板名/数组,建议改用group` 模式搭配数值分箱(如按区间打标签),避免语义混乱。
  • 善用内置单色渐变oranges/greens/blues本身就是按由浅到深排列的渐变序列,可作为热力渐变的灵感来源。
  • 数值跨度悬殊时注意视觉区分度:归一化是线性的,若数据集中存在极端离群值,大部分节点会挤在ratio ≈ 0附近,此时可考虑先对字段做对数/开方变换,再喂给色板。
  • invert: true实现反向映射:例如"数值越小越红"的风险图,只需一行配置即可翻转。
  • field支持函数:当数值需要派生计算(如(d) => d.data.x * d.data.y)时,无需改写数据,直接在field中写函数即可。
  • 边也能用连续色板:色板同样适用于edge.palette,且边元素会以stroke应用颜色,可用于表达边的权重/流量强度。
  • 与分组配置对比:如果你的数据是类别而非连续值,请参考 标准配置示例 中的group模式;想快速上手默认取色,可查看 默认配置示例,并参阅 入门教程中的色板章节 查看其在力导向图上的完整实战代码。

【免费下载链接】G6♾ A Graph Visualization Framework in JavaScript.项目地址: https://gitcode.com/gh_mirrors/g6/G6

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询