ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

如何用单个SVG文件生成可交互科学图表:kuva内嵌JavaScript完整指南

如何用单个SVG文件生成可交互科学图表:kuva内嵌JavaScript完整指南

【免费下载链接】kuva

A scientific plotting library in Rust

项目地址:https://gitcode.com/gh_mirrors/ku/kuva
点击查看免费下载

kuva 是一个用 Rust 编写的科学绘图库(README.md),支持 60 余种图表类型。它的--interactive特性可以把浏览器交互能力直接写进输出的 SVG 文件里:悬停提示、点击固定、搜索过滤、图例开关全部可用,而且不需要服务器、不需要 CDN、不依赖任何外部资源——一个.svg文件就是完整交付物。

为什么把 JavaScript 写进 SVG?

传统做法是把图表做成静态图片,再配一个前端框架(如 D3、Plotly)做交互——这意味着你要部署网页、引入依赖、维护两套代码。

kuva 的做法不同:渲染 SVG 时,它直接把一小段 JavaScript(src/backend/interactive_js.rs 中约 220 行的JS常量)连同 CSS 一起注入到<script>标签里。文件发出去之后,任何人用浏览器打开就能交互,断网环境、邮件附件、静态站点都适用。

生成可交互 SVG 的两个入口

CLI:加一个--interactive参数

每个子命令都接受--interactive,例如:

kuva scatter examples/data/scatter.tsv --x x --y y --color-by group --legend --interactive -o plot.svg kuva volcano examples/data/volcano.tsv --gene gene --log2fc log2fc --pvalue pvalue --legend --interactive -o volcano.svg

用浏览器打开plot.svg,交互即生效。示例数据可以直接使用仓库里的 examples/data/scatter.tsv 和 examples/data/volcano.tsv。

Rust 库:一行with_interactive()

作为库使用时,只要在布局上开启开关(src/render/layout.rs):

let layout = Layout::auto_from_plots(&plots).with_interactive();

之后SvgBackend::new().render_scene(&scene)输出的 SVG 就自带交互。多面板Figure也会逐面板继承该开关,行为见 tests/interactive_svg.rs。

原理:单个 SVG 文件里藏着什么?

打开一个交互版 SVG,会发现三处"额外内容",这也是全部秘密所在:

1. SVG 根节点上的data-*坐标系元数据

SVG 后端 在<svg>标签上写入data-xmin、data-xmax、data-ymin、data-ymax、绘图区四边坐标(data-plot-left/top/right/bottom)以及data-log-x、data-log-y对数轴标记。JavaScript 靠这些数字把鼠标像素位置换算回数据坐标——这就是"坐标读数"功能的来源。

2. 数据点被包进带属性的<g class="tt">

交互模式下,每个散点/条形不再是裸元素,而是被包进带data-group、data-x、data-y属性的<g>组,并附上原生<title>提示文本(tooltip 机制见 tests/tooltip_svg.rs)。搜索和图例开关都是基于这些属性做的 DOM 过滤。

3.<foreignObject>搜索框 +<script>注入

渲染收尾阶段,后端在</svg>前依次写入:底部 UI 条(HTML 搜索输入框、save 按钮、ⓘ 帮助图标)、坐标读数文本、以及 CDATA 包裹的 JavaScript。CSS 高亮/暗化规则(.pinned、.dim、.muted)则放在<defs>内的<style>中。

6 个开箱即用的交互功能

功能使用方式
悬停提示光标移到数据点上,显示标签与数值
点击固定点击数据点保持高亮、其余变暗;再点一次或按Escape清除
搜索过滤在搜索框输入基因名/组名,不匹配的点自动淡出
坐标读数光标在绘图区内移动时,实时显示数据空间的 x/y 值
图例开关点击图例条目显示/隐藏对应系列
保存 SVG右上角 save 按钮序列化当前 DOM 状态(下载功能尚未完善)

火山图还有彩蛋:显著性阈值线可以直接拖拽,点的颜色会随阈值实时重算(交互脚本第 190–222 行)。

本版本完整接入了scatter、line、bar、strip、volcano五类图;其他子命令也接受--interactive,会加载搜索框和坐标读数 UI,逐点悬停/搜索将在后续版本补齐(详见 docs/src/cli/index.md)。

这些场景下会自动"降级"

--interactive是纯增量开关,关闭时输出字节级不变;以下情况它会静默失效,得到普通静态 SVG:

  • 输出为 PNG(--features png)或 PDF(--features pdf)
  • 终端渲染(--terminal)
  • 在 Inkscape / Illustrator 中打开(脚本标签会被剥离)

所以放心把--interactive加进流水线,不会对现有静态产物产生任何影响。

延伸阅读

  • 官方交互文档(含可在线体验的火山图示例):docs/src/reference/interactive.md
  • 注入的完整 JavaScript 源码:src/backend/interactive_js.rs
  • 交互 UI 与脚本注入逻辑:src/backend/svg.rs
  • 端到端测试(断言data-*属性、<script>、CSS 类均存在):tests/interactive_svg.rs
  • strip 图叠加图例开关的用法示例:docs/src/cli/strip.md

小结:kuva 用"元数据属性 + 内嵌脚本 + foreignObject UI"三板斧,把交互能力折叠进单个 SVG 文件。一个 flag 的成本,换来可以离线分发的可交互科学图表——这就是它最讨巧的设计。

【免费下载链接】kuva

A scientific plotting library in Rust

项目地址:https://gitcode.com/gh_mirrors/ku/kuva
点击查看免费下载

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

RELATED READING

延伸阅读

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