Vega 堆叠条形图实战基于 stacked-bar-chart 示例解析 stack 变换与矩形标记编码【免费下载链接】vegaA visualization grammar.项目地址: https://gitcode.com/gh_mirrors/ve/vega堆叠条形图Stacked Bar Chart通过分层矩形展示多个定量序列的总和同时保留对单个序列的观察能力是 Vega 中最具代表性的基础图表之一。本文以仓库中 stacked-bar-chart.vg.json 示例为骨架完整拆解其数据、变换、比例尺与标记编码结构并结合 stack 变换文档 与 Stack 算子源码 讲透堆叠的底层原理。读完本文你将能够独立编写、修改并扩展 Vega 堆叠条形图并掌握三种堆叠基准zero / center / normalize的适用场景。示例概述一个最小可运行的堆叠条形图仓库中的 stacked-bar-chart.md 对该示例给出了精炼定义堆叠条形图用分层条形描绘多个定量序列的加总同时仍允许检视每个独立序列。配套的 stacked-bar-chart.vg.json 是一个自包含inline data的 Vega v6 规范无需任何外部数据文件即可直接渲染非常适合作为学习堆叠布局的起点。整个规范的顶层结构如下width: 500、height: 200、padding: 5画布尺寸与内边距data一张名为table的内联数据表共 20 条记录字段为x类别位置0–9、y堆叠高度值、c分组类别0 或 1并在数据层直接应用stack变换scalesxband 比例尺、ylinear 比例尺、colorordinal 比例尺三把比例尺axes底部x轴与左侧y轴marks单个rect标记通过y0/y1定位矩形的上下边界。该示例的关键设计是堆叠计算发生在数据变换阶段而非标记编码阶段。stack变换为每条数据追加y0堆叠起点与y1堆叠终点两个字段后续比例尺与标记编码只需直接消费这两个字段。stack 变换堆叠布局的核心示例在数据定义内使用了stack变换{ type: stack, groupby: [x], sort: {field: c}, field: y }按照 stack 变换文档stack通过对值分组执行堆叠布局最常见的用途就是生成堆叠条形图与流图stream graph。它向每条数据写入两个属性分别表示堆叠的起始值与结束值。该变换支持五个参数属性类型说明fieldField决定堆叠高度的数据字段groupbyField[]用于将数据划分为独立堆叠栈的字段数组sortCompare每个栈内部值的排序条件offsetString基线偏移取zero默认、center或normalize。zero从 0 开始堆叠center将堆叠居中normalize计算每个栈点的百分比值输出范围在 [0, 1]asString[]计算得到的堆叠起止字段名默认为[y0, y1]对照 Stack.js 源码 的Stack.Definition可以看到这五个参数正是算子的参数化定义field为 field 类型、groupby为 field 数组、sort为 compare 类型、offset为枚举类型默认zero、as为长度 2 的字符串数组默认[y0, y1]。分组与排序语义在本示例中groupby: [x]意味着按x字段的每个唯一值0–9各建立一个独立的堆叠栈sort: {field: c}则保证每个栈内按类别c排序使同类别矩形在视觉上保持一致的相对顺序field: y指明用y字段的数值决定每个矩形的高度。结果默认写入y0、y1字段即每个矩形下沿与上沿所对应的累加值。Stack.js 源码 中的partition函数揭示了底层分组机制当未指定groupby时全部数据被当作一个栈否则通过JSON.stringify(groupby.map(...))构造分组键因此null、、0、false等键会被区分对待见 stack-test.js 中 stacks null and empty string groups separately 与 stacks zero and false groups separately 两个测试用例同时计算每个组的绝对值之和g.sum以及全局最大值groups.max供center与normalize偏移使用并在排序条件存在时对组内元素排序。三种堆叠基准的实现stack的offset参数在源码中对应三个内部函数Stack.jsstackZero默认zero从 0 开始堆叠。特别注意它按正负值分开累加——负值向下堆叠lastNeg正值向上堆叠lastPos这与测试用例 Stack stacks negative values 中-1与2被分别堆到 0 线两侧的断言完全一致stack-test.jsstackCentercenter先计算(max - group.sum) / 2作为偏移起点使整个栈以全局最大栈为中心居中适合制作流图stackNormalizenormalize以1 / group.sum为缩放系数将每个栈的起止值归一化到 [0, 1]即百分比堆叠。另外源码 Stack.js 使用stableCompare(_.sort)包装排序比较器保证排序是稳定的即使多条数据的排序键相同也不会意外交换顺序。field未指定时默认使用one常量函数即每个值视为 1字符串数值会被field(t)强转为数字测试用例 Stack stacks coerced string values 验证了这一点。比例尺配置band 定位与线性映射示例定义了如下三把比例尺{ name: x, type: band, range: width, domain: {data: table, field: x} }, { name: y, type: linear, range: height, nice: true, zero: true, domain: {data: table, field: y1} }, { name: color, type: ordinal, range: category, domain: {data: table, field: c} }三个关键点值得注意x使用band比例尺堆叠条形图按离散类别排列矩形band比例尺将x的 10 个取值均匀映射到width范围内并天然提供band宽度用于矩形的width编码y的 domain 取自y1字段domain: {data: table, field: y1}意味着比例尺输入域由堆叠变换产出的累加上界决定这样整组堆叠的总高度恰好对应比例尺的顶值配合zero: true确保从 0 开始、nice: true让坐标轴刻度取整color使用ordinal比例尺与category配色c的取值 0、1 映射到 Vega 默认分类色板中的前两个颜色用于区分堆叠的两个序列。标记编码用 y0 / y1 绘制堆叠矩形marks中只定义了一个rect标记其编码逻辑是堆叠条形图的精髓{ type: rect, from: {data: table}, encode: { enter: { x: {scale: x, field: x}, width: {scale: x, band: 1, offset: -1}, y: {scale: y, field: y0}, y2: {scale: y, field: y1}, fill: {scale: color, field: c} }, update: { fillOpacity: {value: 1} }, hover: { fillOpacity: {value: 0.5} } } }水平定位x取数据字段x经 band 比例尺映射后的位置width使用band: 1表示占满整个 band 带宽再以offset: -1收窄 1 像素避免相邻条形粘连垂直定位这是堆叠的关键——y与y2分别绑定堆叠变换产出的y0与y1字段。y定义矩形的顶部位置、y2定义底部位置Vega 中矩形以y为顶端、y2为底端两者经y线性比例尺映射后恰好构成一段从上一序列上沿到本序列上沿的色块实现层叠效果颜色fill绑定color比例尺按c字段区分序列交互状态编码按enter/update/hover三阶段组织鼠标悬停时fillOpacity从 1 降为 0.5用于高亮当前矩形这也是 Vega 场景图中标记状态vega-scenegraph的标准用法。与普通条形图的差异对照仓库中非堆叠的 bar-chart.vg.json 可以发现普通条形图的y直接绑定原始值字段、y2绑定零点或基准值而堆叠条形图则把起点信息完全交给stack变换生成的y0字段标记编码本身无需理解堆叠逻辑。这种变换计算布局、编码消费结果的分层设计贯穿整个 Vega 架构。运行与渲染方式该示例是自包含 JSON 规范可通过以下方式查看运行效果浏览器渲染仓库 docs 目录 下提供了预构建的 vega.js 与压缩版 vega.min.js。在 HTML 页面中引入后调用vega.parse(spec)解析规范、new vega.View(parser)创建视图并绑定 DOM 容器即可渲染命令行渲染使用 vega-cli 包可执行vg2png stacked-bar-chart.vg.json或vg2svg直接输出静态图片示例页该示例与全部示例图片如 stacked-bar-chart.png配套收录在 examples 目录 中specs-valid 测试集 也包含同源规范用于回归验证可参考 vega 包测试 的构建流程。进阶扩展从堆叠条形到堆叠面积图堆叠布局并不局限于条形图。仓库中的 stacked-area-chart.vg.json 使用了完全相同的数据与stack变换groupby: [x]、sort: {field: c}、field: y差别仅在于x比例尺类型由band改为point面积图按连续位置连接标记由单个rect改为group分面按c分面为series内嵌的area标记并使用interpolate: monotone平滑插值y/y2同样消费y0/y1。这充分说明stack变换产出的y0/y1是与可视化编码解耦的通用布局结果同一份堆叠数据可以驱动条形、面积乃至流图offset: center等多种图形形态。若需百分比堆叠只需将offset改为normalize若数据包含负值stackZero会自动将负值堆叠到基线以下无需额外处理。小结通过 stacked-bar-chart.vg.json 这个最小示例我们完整走通了 Vega 堆叠可视化的标准流程数据声明 →stack变换产出y0/y1→band/linear/ordinal三把比例尺 →rect标记以y/y2消费堆叠字段。对照 Stack.js 源码 与 stack-test.js 可以确认分组基于键值哈希、正负值分开累加、center/normalize依赖组和与全局最大值、排序稳定——这些实现细节共同保证了堆叠布局的正确性与可预测性。以此为模板你可以轻松扩展到百分比堆叠、负值堆叠、流图乃至堆叠面积图。【免费下载链接】vegaA visualization grammar.项目地址: https://gitcode.com/gh_mirrors/ve/vega创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考