ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

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

G6 连续色板(Continuous Palette)完全指南:基于数值字段的映射取色 G6 连续色板Continuous Palette完全指南基于数值字段的映射取色【免费下载链接】G6♾ A Graph Visualization Framework in JavaScript.项目地址: https://gitcode.com/gh_mirrors/g6/G6G6 的色板Palette机制用于为节点、边等元素自动分配颜色。其中连续色板type: value与离散色板type: group相对应它不再按分组取色而是根据元素的数值型字段如吞吐量、温度、风险评分在[0, 1]区间上归一化后映射为颜色从而形成类似热力图的渐变视觉。读完本文你将掌握连续色板的配置写法、color函数入参语义、内置色板的使用方式以及它在 G6 渲染管线中的底层实现原理可直接用于构建数值越大颜色越深/越红一类的数据可视化场景。一、理解两种取色模式分组group与数值valueG6 的色板配置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红色通道也随之变强——节点的红度直观表达了数值高低。各配置项含义如下配置项类型说明typevalue声明为连续取色模式按字段值映射fieldstring \| ((datum) string)取值字段名指向datum.data上的数值属性如value也支持传入函数color(ratio: number) string颜色映射函数接收归一化后的比例值返回任意合法颜色字符串invertboolean是否倒序取色默认false三、color函数接收的到底是什么——归一化原理这是连续色板最容易被误解的地方color函数收到的不是原始字段值而是归一化到[0, 1]区间的比例值。在类型定义中连续色板的签名被明确描述为见 packages/g6/src/palettes/types.tsexport 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]), ); }从源码可以提炼出连续取色的完整流程遍历所有元素读取field指定的字段值字段可来自datum.data即parseField对字符串字段名取datum.data[field]求出全局最小值min与最大值max计算区间宽度range max - min对每个元素计算归一化比例ratio (value - min) / range该值恒落在[0, 1]内将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.tspalette: { 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)); } }); }要点如下色板可以配置在主题theme上作为全局默认元素级配置node.palette等通过Object.assign覆盖主题色板遵循元素级 主题级的优先级只有配置了field才会触发取色——field是色板生效的开关缺省时色板不参与颜色计算计算结果按元素id缓存在paletteStyle字典中同组元素共享同一颜色最终取色通过getPaletteStyle应用到样式上见 packages/g6/src/runtime/element.ts节点/组合用fill边用stroke且该颜色与themeStyle、dataStyle、stateStyle等按序合并见 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),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进