Rerun BarChartView 视图完全指南:柱状图蓝图的属性、数据流与源码实现解析
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
导读
BarChartView是 Rerun 可视化框架中用于展示一维数据(向量 / 1D 张量)柱状图的蓝图视图类型。本文以官方参考文档 bar_chart_view.md 为核心骨架,完整讲解该视图的两大属性组(plot_legend与background)、可可视化的数据源(BarChart与 1DTensor),并结合本仓库的 Python 示例片段、Rust 实现与测试用例,从"如何配置"到"底层如何渲染"进行纵深剖析。读完本文,你将掌握如何在 Python 蓝图中创建和定制BarChartView,并理解其背后的组件描述符(ComponentDescriptor)与可视化器(Visualizer)工作机制。
1. BarChartView 是什么
BarChartView是 Rerun 蓝图(Blueprint)中的一种视图(View)类型,专门用于渲染单个柱状图。在 blueprint/views/bar_chart_view.rs 中,它被定义为由两个属性子结构组成的视图类:
plot_legend:图例(legend)的配置;background:绘图背景的配置。
需要特别注意的是,参考文档与源码都明确标注了这一点:
⚠️此类型目前处于unstable状态,未来可能以不向后兼容数据的方式发生重大变化。
这意味着在编写依赖该视图的持久化蓝图时,应关注后续版本对视图定义的可能调整。
在 Rust 侧,该视图的渲染入口位于 view_class.rs 中的BarChartView结构体,其display_name()返回"Bar chart",图标使用re_ui::icons::VIEW_HISTOGRAM(直方图语义图标),布局优先级为LayoutPriority::Low,即视图中没有数据时一般不会主动抢占布局空间。整个 crate 的职责在 crates/views/re_view_bar_chart/README.md 中概括为一句:A View that shows a single bar chart。
2. 视图属性详解
参考文档列出了BarChartView的完整属性,它们都由独立的蓝图 archetype 承载,且默认值由 Rust 侧的 fallback provider 注册(见下文 2.3 节)。
2.1plot_legend:图例配置
属性类型为PlotLegend,包含两个字段:
| 字段 | 类型 | 含义 | 默认值 |
|---|---|---|---|
corner | Corner2D | 图例对齐到哪个角落 | 右下角(RightBottom,源码注释明确写 "Defaults to the right bottom corner") |
visible | Visible | 是否显示图例 | 默认 true("True by default") |
不过,在view_class.rs的on_register中注册的 fallback 是Corner2D::RightTop(右上角),而非右下角:
system_registry.register_fallback_provider::<Corner2D>( PlotLegend::descriptor_corner().component, |_| Corner2D::RightTop, );两者看似矛盾,实际含义不同:plot_legend.rs中corner字段的 doc 注释描述的是PlotLegendarchetype 自身的文档化默认值,而view_class.rs中注册的是BarChartView实际运行时使用的 fallback。在解释最终渲染行为时,应以视图类注册的 fallback 为准(右上角)。这一细节也印证了阅读文档时需结合源码校验的重要性。
在渲染端,当legend_visible为真时,view_class.rs 会使用re_plot::legend::LegendWidget以legend_corner指定的位置叠加绘制图例;每个图例条目对应一个 data result(实体路径),并携带该实体图表对应的颜色;用户点击图例条目可切换实体的可见性,点击结果通过save_visible持久化到查询树(tree)中。
2.2background:绘图背景配置
属性类型为PlotBackground,包含两个字段:
| 字段 | 类型 | 含义 |
|---|---|---|
color | Color(RGBA) | 绘图区背景颜色 |
show_grid | Enabled | 是否绘制网格 |
渲染端在ui()方法中通过ViewProperty::from_archetype::<PlotBackground>读取这两个属性:
background_color被直接设置到 egui 的visuals.extreme_bg_color,即整个绘图区的背景色;show_grid控制Plot::new("bar_chart_plot").show_grid(...)是否绘制网格,网格颜色与淡出效果来自re_ui::design_tokens_of_visuals设计令牌(tokens.plot_grid_color/tokens.plot_grid_fade),并启用clamp_grid(true)防止网格无限延伸。
值得一提的是柱体颜色与背景的适配逻辑:渲染时若背景亮度低于 0.5,柱体填充色会采用 additive 混合模式(egui_color.gamma_multiply(0.75).additive()),否则用普通 gamma 乘法,以保证深色背景下柱体依然醒目(view_class.rs)。
2.3 属性是如何被解析的
属性 archetype(如PlotBackground、PlotLegend)同样遵循 Rerun 的组件描述符机制。以PlotBackground为例,其show_grid字段对应的组件是rerun.blueprint.components.Enabled(plot_background.rs);PlotLegend的corner对应Corner2D、visible对应Visible(plot_legend.rs)。视图类在渲染时用component_or_fallback获取最终值——即:用户未显式设置时,使用 fallback provider 返回的默认值。
3. 可视化数据源:BarChart 与 1D Tensor
参考文档"Visualized archetypes"一节明确列出了该视图支持的两类数据:
BarChartTensor(仅限 1D 张量)
3.1 BarChart archetype 的字段
BarChart在 archetypes/bar_chart.rs 中定义,包含 4 个组件:1 个必需 + 3 个可选:
| 字段 | 组件类型 | 必需? | 含义 |
|---|---|---|---|
values | TensorData | ✅ 必需 | 柱高数值,必须是一维张量(向量) |
color | Color | 可选 | 柱体颜色 |
abscissa | TensorData | 可选 | 每个值对应的横坐标(一维张量,长度须与 values 相同) |
widths | Length | 可选 | 每个柱的宽度(x 轴单位,默认 1,长度须与 values 相同) |
其组件描述符(ComponentDescriptor)如下:
values→BarChart:values,类型rerun.components.TensorDatacolor→BarChart:color,类型rerun.components.Colorabscissa→BarChart:abscissa,类型rerun.components.TensorDatawidths→BarChart:widths,类型rerun.components.Length
3.2 可视化器的查询与校验
在 visualizer_system.rs 中,BarChartVisualizerSystem以BarChart:values作为唯一必需组件(VisualizerQueryInfo::single_required_component)。执行查询时:
- 对每个 data result 取
LatestAt时间点上的TensorData; - 只有当该张量
is_vector()(即一维向量)时才继续处理; - 分别读取
abscissa(带 fallback)、color(带 fallback)、widths(可选切片); widths若未提供,则通过typed_fallback_for::<Length>得到默认宽度数组,并用clamped_vec_or_else将长度对齐到 values 的长度;- 最终把每个实体路径映射为一份
BarChartData { abscissa, widths, values, color },交给视图类渲染。
这也解释了为什么 1DTensor也能被柱状图视图展示:只要它是向量,其TensorData就能匹配上BarChart:values的组件描述符。
4. 实战示例:用蓝图创建 BarChartView
参考文档引用的是views/bar_chart示例片段,其完整源码位于 docs/snippets/all/views/bar_chart.py:
"""Use a blueprint to show a bar chart.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_bar_chart", spawn=True) rr.log("bar_chart", rr.BarChart([8, 4, 0, 9, 1, 4, 1, 6, 9, 0])) # Create a bar chart view to display the chart. blueprint = rrb.Blueprint( rrb.BarChartView( origin="bar_chart", name="Bar Chart", background=rrb.archetypes.PlotBackground( color=[50, 0, 50, 255], show_grid=False ), ), collapse_panels=True, ) rr.send_blueprint(blueprint)要点拆解:
- 数据记录:
rr.log("bar_chart", rr.BarChart([...]))把一个 1D 数值列表记录到实体bar_chart; - 视图创建:
rrb.BarChartView(origin="bar_chart", name="Bar Chart", ...)创建一个以bar_chart实体为原点(origin)的柱状图视图; - 背景定制:
background=rrb.archetypes.PlotBackground(color=[50, 0, 50, 255], show_grid=False)演示了文档中background属性的两个字段——深紫半透明背景 + 关闭网格; - 发送蓝图:
rr.send_blueprint(blueprint)将蓝图应用到当前会话,并配合collapse_panels=True折叠侧边面板,让柱状图独占视野。
4.1 进阶:自定义横坐标与柱宽
Rust 版示例 与 Python 版 archetype 示例 展示了abscissa与widths的用法:
import rerun as rr rr.init("rerun_example_bar_chart", spawn=True) rr.log("bar_chart", rr.BarChart([8, 4, 0, 9, 1, 4, 1, 6, 9, 0])) rr.log( "bar_chart_custom_abscissa", rr.BarChart([8, 4, 0, 9, 1, 4], abscissa=[0, 1, 3, 4, 7, 11]), ) rr.log( "bar_chart_custom_abscissa_and_widths", rr.BarChart( [8, 4, 0, 9, 1, 4], abscissa=[0, 1, 3, 4, 7, 11], widths=[1, 2, 1, 3, 4, 1], ), )abscissa=[0, 1, 3, 4, 7, 11]:横坐标不必等距,可表达非均匀采样的 x 轴刻度;widths=[1, 2, 1, 3, 4, 1]:每个柱的宽度独立控制,在 x 轴单位下取值,默认 1。
需要再次强调:abscissa与widths的长度必须与values相同(源码 doc 注释明确要求 same length as values),否则会通过clamped_vec_or_else截断或按 fallback 补齐。
4.2 测试用例佐证
crates/views/re_view_bar_chart/tests/bar_chart_test.rs 中的test_bar_chart完整模拟了"数据 + 蓝图 + 渲染"链路:
- 用
archetypes::BarChart::new(x())记录 100 个点的数据(x()生成 0~100 均匀分布); - 通过
ViewBlueprint::new_with_root_wildcard(BarChartView::identifier())建立视图蓝图; - 以 400×300 画布渲染并保存快照
bar_chart_1d(对应 bar_chart_1d.png)。
这验证了:只要实体上有BarChart数据且视图中注册了BarChartVisualizerSystem,BarChartView即可直接渲染出柱状图,无需手动添加指示器(indicator)。
5. 渲染管线与交互(源码级原理)
5.1 柱体布局:以柱中心定位
view_class.rs 中的核心转换逻辑:对每个实体的BarChartData,先将其abscissa(横坐标)与values(柱高)分别从TensorBuffer的任意数值类型(U8/I8/U16/I16/U32/I32/U64/I64/F16/F32/F64)统一转为f64浮点;随后计算每个柱:
center_x = index + 0.5 * width即每个柱的中心横坐标为"横坐标值 + 半个柱宽",柱体由egui_plot::Bar::new(center_x, value).width(width)构建,同一实体的所有柱聚合成一个egui_plot::BarChart,并以实体路径命名、以实体颜色着色、以entity_path.hash()作为绘图项 ID,用于后续的 hover/点击命中。
5.2 悬停检测与 tooltip
悬停检测不依赖 egui_plot 内建机制,而是基于上一帧的PlotTransform自行实现(find_nearest_bar,view_class.rs):
- 光标距柱顶点的屏幕距离 ≤ 16px(
TOOLTIP_INTERACT_RADIUS)视为命中候选; - 若光标落在某个柱的矩形范围内(按 transform 将柱的左/右/顶/底换算为屏幕坐标),则直接判定命中该柱;
- 命中后显示 tooltip(内容为
#索引、实体路径与格式化后的数值),并把悬停/点击事件映射为Item::DataResult交给 viewer 的选择系统,从而与选中面板、实体树联动; - 鼠标悬停在图例上时不触发柱体 hover,避免遮挡图例交互。
5.3 交互控制
BarChartView::help()中登记了完整的鼠标/滚轮交互(view_class.rs):
| 操作 | 触发方式 |
|---|---|
| Pan(平移) | 左键拖拽 |
| Horizontal pan | 横向滚动 |
| Zoom(缩放) | 滚动(配合修饰键) |
| Zoom X-axis | 修饰键 + 横向滚动 |
| Zoom Y-axis | 修饰键 + 纵向滚动 |
| Zoom to selection | SELECTION_RECT_ZOOM_BUTTON+ 拖拽框选 |
| Reset view | 双击左键 |
注:具体修饰键(如 Ctrl/⌘)取决于操作系统,视图内部使用 egui 默认输入选项,未开放自定义。
6. 稳定性与兼容性提示
BarChartView及其属性 archetype(PlotLegend、PlotBackground)均标注为unstable,官方文档与生成代码都提示"数据可能不再向后兼容";- 本文描述的字段结构、默认值与组件描述符均以当前仓库 rerun 的源码为准:视图定义见 bar_chart_view.rs,渲染实现见 view_class.rs,数据查询见 visualizer_system.rs;
- 若需在代码中直接使用,可在 Python 侧通过
rerun.blueprint.views.BarChartView创建,在 Rust 侧通过re_view_bar_chart::BarChartView(实现ViewClasstrait)注册使用。
结语
BarChartView虽然结构简单(一个图例属性 + 一个背景属性),但其背后是一套完整、严谨的可视化数据流:蓝图属性通过 ComponentDescriptor 与 fallback 机制解析、可视化器按BarChart:values必需组件匹配一维数据、渲染层将任意数值类型张量统一转换为 f64 柱体坐标,并实现了图例联动、柱体 hover、框选缩放等交互。希望本文能帮助你快速上手 Rerun 的柱状图视图,并为阅读 bar_chart.rs 等底层实现提供清晰的索引。
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考