GeoLibre 属性表深度解析:浏览、筛选、编辑、分析与导出地理数据属性的完整工作流
【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre
属性表(Attribute table)是 GeoLibre 中查看和管理矢量图层记录的中央工作台:打开它从Layer actions → Open attribute table,或从状态栏的Attribute table按钮展开后再到图层面板选择目标图层。本文围绕 GeoLibre 属性表的完整功能面展开——工具栏各按钮的分工、与地图选区的双向联动、列探查器、字段统计、内置图表、内联编辑的类型推断机制、DuckDB 查询结果层的特殊行为,以及五种导出格式——并逐一对应到apps/geolibre-desktop/src下的源码实现,帮助你在阅读官方说明之外,进一步理解这些功能的边界条件与底层原理。
打开方式与整体布局
属性表以底部停靠面板(docked panel)的形式展示所选矢量或 DuckDB 图层的记录,两种入口等价:
- 在图层面板中对图层执行Layer actions → Open attribute table(对应 LayerPanel.tsx 中
layers.openAttributeTable菜单项); - 点击状态栏上的Attribute table按钮展开面板,再在 Layers panel 中选择一个图层。
面板底部有一条状态栏,实时报告当前图层的记录总数与当前选中的记录数。面板高度本身也是可交互的:拖动其顶边可以调整高度,处理长表之前先把面板拉高是文档明确建议的操作。从源码看,这个拖拽逻辑把高度限制在 96–520 px 之间,且不超过视口高度减去 180 px 的可用空间(见 AttributeTable.tsx 中startTableResize的实现,以及MIN_TABLE_HEIGHT/MAX_TABLE_HEIGHT常量)。
工具栏:九个按钮的完整分工
属性表顶部工具栏是全部功能的入口,各按钮职责如下(完整继承自官方文档,并结合源码补充说明):
| 按钮 | 功能 |
|---|---|
| Edit/Save | 开启内联编辑,随后把改动写回图层。详见下文编辑属性值。 |
| Explore | 打开列探查器(Column explorer)。 |
| Statistics | 对单个字段做汇总统计,见字段统计。 |
| Charts | 不离开表格直接对一两个字段绘图,见图表。 |
| Dashboard | 以当前图层预选中状态打开 Dashboard,构建可持久化的图表面板。 |
| Export | 把当前正在查看的记录写入文件,见导出。 |
| Search attributes… | 按输入文本跨所有字段过滤行。 |
| Zoom to selection | 在选区变化时,让地图持续聚焦于选中的要素。 |
| Show All Features / Show Selected | 显示全部记录,或只显示被选中的记录;计数随选区更新。 |
其中两个值得展开的交互细节:
- Search attributes…的过滤实现是对每行做
JSON.stringify(properties).toLowerCase()后做子串匹配,同时也会匹配 feature id 本身(AttributeTable.tsx)。也就是说它不是按“某个字段”搜索,而是把整行属性摊平成字符串做全文匹配,适合快速定位某个记录而不记得它属于哪一列。 - Show All / Show Selected切换的是表格的数据视图而非地图选区。源码中有一个贴心处理:当选区被清空时自动回落到显示全部,避免“只看选中”模式下出现一张空表(
useEffect监听selectedFeatureIds.length === 0时重置视图)。
阅读与导航:排序、列宽、虚拟滚动
官方文档给出三个基本操作,结合源码可以看到它们的实现约束:
- 排序(Sort):点击列头升序/降序排列。排序比较器
compareAttributeValues对 null 值恒排在最前,数字直接相减,非数字先尝试按数值解析(如"12"与8可正确比较),最后退化为带numeric: true的localeCompare(AttributeTable.tsx)。 - 列宽(Resize columns):拖动列边界调整宽度,字段很多时可横向滚动。列宽有硬边界——feature id 列 48–180 px,普通属性列 72–520 px,默认 160 px;在 RTL 布局下拖拽方向会取反以保证行为一致(
startColumnResize)。 - 面板高度:拖动顶边调整,适合在处理长表前一次性完成。
支撑这些操作能流畅工作的关键设计是行级虚拟滚动:表格使用@tanstack/react-virtual,只挂载视口附近(外加 8 行 overscan 缓冲)的行,因此打开一个数万要素的图层不会一次性构建等量的 DOM 节点;排序和过滤仍然作用于完整数据模型,虚拟器只管渲染。当在地图上点选某个要素时,如果对应行尚未挂载,面板会自动scrollToIndex把它滚进视野。
与地图的双向联动
属性表与地图共享同一份选区状态,始终保持同步:
- 选中表格中的一行,地图上对应要素会高亮;
- Zoom to selection让地图在选区变化时持续框住所选要素;
- 选区支持多要素,同一份选区同时驱动Edit → Export Selected Features as Layer以及各图层操作中的选择工具。
行点击的选区语义在纯函数computeRowSelection中定义(可单测):普通点击单选,Ctrl/⌘ 点击切换单个成员,Shift 点击做范围选择,Shift+Ctrl 做范围合并。此外表格中的行选区与地图点选共用同一个selectedFeatureIds状态,这也是“表格选中即地图选中”的底层原因。相关行为由 attribute-selection.test.ts 覆盖。
列探查器(Column Explorer)
点击Explore会对图层中每一个字段做一次性画像:字段类型、非空记录数、空值数、去重值数量,以及分布形态——文本字段给出高频值的排名条形图,数值字段给出带 min / mean / max 标注的直方图。字段很多时可按名称过滤字段列表。
官方文档把它定位为回答“这份数据里到底有什么”的最快路径:一个 90% 为空的字段,或一个“数值”字段里混入的非数值离群值,都会立刻暴露出来,让你在做符号化或过滤之前先摸清数据质量。组件实现在 ColumnExplorerDialog.tsx。
字段统计(Field Statistics)
Statistics对单个字段做汇总,所有字段都报告Count、Nulls、Unique三项;数值字段额外给出Min、Max、Mean、Median、Std dev、Sum;文本字段则列出出现频次最高的值及其计数。Copy按钮把整份摘要复制到剪贴板,便于粘贴进报告或协作渠道(对话框见 AttributeStatsDialog.tsx)。
源码中有个容易被忽略但很实用的细节:统计对话框打开时,如果源数据把测量值存成文本(例如 CSV 导入的"12.5"),会用coerceNumericStringRows把分析行临时适配成数值,但表格显示和源数据保持不变(attribute-charts.ts)。这个适配是按列而非按值决策的:只有当一列中“看起来是数值”的字符串同时满足“至少 2 个、且达到非空行数一半”时才整列转换;带前导零的整数(如邮编"00501")和惯用标识符列名(id / fid / code / fips / zip 等)始终保留为文本,避免把标识符当成数字统计。这保证了“所有 / 过滤后 / 选中”三种统计范围下,同一字段的数值/文本判定保持一致。
图表(Charts)
Charts直接对当前图层绘图,不向工程中添加任何东西:选择图表类型(histogram、scatter、bar、line、box plot 或 pie,共六种,见 attribute-charts.ts 的ChartType)、选择要绘制的字段、再配置类型相关选项(如直方图的 bin 数),Download即可把图表保存为图片。
源码中的几个约束值得了解,它们解释了为什么某些字段在图表选择器里“不可选”:
- 直方图 bin 数取值 1–50,默认 10(
MIN_HISTOGRAM_BINS/MAX_HISTOGRAM_BINS/DEFAULT_HISTOGRAM_BINS); - 柱状图只接受去重值不超过 50的分类字段(高基数的 id/文本列被排除),且最多渲染 20 个类别;
- 饼图最多渲染 8 片,其余合并为 "(other)";
- 只有能解析为有限数字的值才进入图表:空串、布尔、NaN、Infinity 都被拒绝,数值型字符串(
"42"、" 3.5 ")会被接受。
文档同时明确了边界:属性表里的图表是“即用即弃”的视图;如果需要随工程保存、且图表之间能交叉过滤(cross-filter),应到 Dashboard 中构建。纯数据层的行为由 attribute-charts.test.ts 等测试覆盖。
编辑属性值
对可编辑图层(包括 GeoJSON 图层与物化的 DuckDB 图层),点击Edit进入内联编辑模式,直接修改单元格,再点Save提交。配合 GeoEditor 插件可以同时编辑几何与属性,图层管理细节见 Managing Layers。
从 AttributeTable.tsx 的实现看,这个“看似简单”的内联编辑器有一套完整的类型与校验机制:
- 草稿态(drafts)而非直接改写:编辑期间所有改动只存在于内存中的
drafts结构(featureId → 列名 → 文本),Save时才通过applyDraftsToFeatures统一写回 feature;取消编辑即丢弃全部草稿。 - 保存时的类型推断:
parseAttributeDraft依据“该列其他行的类型”把文本回填为正确类型——前值是 number 就Number(),是 boolean 就识别true/false,是 object 就尝试JSON.parse。若某列所有行此前都是空值,则退回依据整列推断出的类型(inferColumnTypes)。解析失败(如给数值列填了非数字文本)时保留原文本而不是损坏数据。 - Attribute Form 校验:如果图层配置了 Attribute Form,保存前会用
validateAttributeFormValues校验,但只报告本次编辑引入或继续保留的违规——未触碰字段上的历史违规不会阻塞无关编辑,且校验只遍历被改的行而不是全表,避免每次按键全表扫描。 - 编辑器跟踪(editor tracking):如果图层开启了编辑跟踪,保存时会对被编辑的要素打上 “update” 跟踪戳(
stampFeaturePropertiesEditorTracking),但仅在真正保存时打戳,导出预览走同样的转换函数却不会记录一次从未发生的编辑。
DuckDB 图层
由 SQL Workspace 生成、或从 DuckDB 数据源 添加的图层,在属性表中与矢量图层行为一致:完整的 identify、选择、属性表支持,且可以同时打开多个 DuckDB 查询结果图层。
实现上有专门的读写通道:表格行来自getDuckDBLayerRows(layer.id),编辑提交走updateDuckDBLayerRows(layer.id, updates)(两者均来自@geolibre/plugins,见 AttributeTable.tsx 与第 969 行附近的保存逻辑)。类型推断逻辑与 GeoJSON 路径完全相同(applyDraftsToDuckDBRows复用同一列级inferColumnTypes),只是把草稿转换成“行 → 更新属性”的映射交给 DuckDB 层持久化,而不是重写 GeoJSON。注意一个边界:列管理(新增/重命名/删除字段)只对存储型 GeoJSON 图层开放——DuckDB 查询结果与 Add Vector Layer 图层因其 geojson 不持久化,不提供列管理菜单(canManageColumns判定)。
导出(Exporting)
工具栏Export可以导出当前正在查看的记录(即受 Search 过滤与 Show All/Show Selected 影响的视图),支持的格式为:
- GeoJSON
- GeoParquet
- GeoPackage
- 打包的 Shapefile(zip)
- CSV(仅属性,无几何)
导出格式由 vector-export.ts 统一描述:文本格式(geojson/csv/kml/polyline)直接生成字符串,二进制格式(geoparquet/geopackage/shapefile)经exportBinaryVectorLayer写出,MIME 类型如 GeoPackage 使用application/geopackage+sqlite3。
两个实用提醒:
- 图层面板中Layer actions → Export子菜单提供同样的格式集,并额外支持 KML 和 KMZ——需要 KML 时从那里进入(见 Layers panel)。
- 导出到 Shapefile 时,若字段名超过该格式10 个字符的限制,会弹出警告(
shapefileFieldWarnings);SQL Workspace 还可把查询结果导出为 CSV 或 GeoParquet,转换工具则负责写出云原生格式。
延伸阅读:源码入口与测试
属性表相关的核心实现与测试文件,可作为进一步阅读入口:
| 主题 | 文件 |
|---|---|
| 表格主体(渲染、排序、虚拟滚动、编辑、选区、导出入口) | AttributeTable.tsx |
列设置持久化与列增删改(存于layer.metadata.columnSettings) | attribute-columns.ts |
| 字段计算器表达式引擎 | attribute-expression.ts |
| 图表数据准备(数值判定、直方图分箱、散点提取) | attribute-charts.ts |
| 字段统计 / 图表 / 列探查对话框 | AttributeStatsDialog.tsx、AttributeChartDialog.tsx、ColumnExplorerDialog.tsx |
| 矢量导出(格式定义、Shapefile 字段警告、KML 错误处理) | vector-export.ts |
| 关键行为测试 | attribute-selection.test.ts、attribute-columns.test.ts、attribute-charts.test.ts、attribute-calculator.test.ts、attribute-stats.test.ts |
从源码结构看,列设置(隐藏列、列顺序)是“视图级”状态,持久化在layer.metadata.columnSettings下,保存/重新加载工程后依然生效;而重命名和删除字段属于破坏性操作,会直接重写底层 GeoJSON 的 properties,并同步更新引用该属性名的样式字段(vectorStyleProperty、extrusionHeightProperty)。这一层能力位于官方文档未展开的列头菜单中,是属性表在“查看/分析”之外的第三重角色——轻量的属性结构管理。
【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考