Interact + Vega-Lite — live chart
用
template vega-lite:把 Interact controls 接到 Vega-Lite chart——拖滑块 / 切 toggle,chart 实时重绘。Observable / Streamlit 级的体验,但全声明、零 JS。
When to use
- ✅ 参数驱动的曲线 / 分布图(拖 slider 改函数参数看曲线变形)
- ✅ 数据探索(toggle 切维度 / 切聚合 / 切色彩编码)
- ✅ 教学可视化(三角函数 / 概率密度 / 物理仿真)
- ✅ 财务 / 工程 / 数据科学(任何需要 "改参数 → 立刻看趋势" 的)
- ❌ 极简结果展示(用 text template 即可)
- ❌ 静态图表(直接
```vega-lite不需 interact 包装) - ❌ 需要复杂 D3 自定义 → vega-lite 表达力有上限,超过用 SVG scenes
Basic syntax
\```interact
slider freq 1 10 3 0.1
template vega-lite:
{
"data": {"sequence": {"start": 0, "stop": 6.28, "step": 0.05, "as": "t"}},
"transform": [{"calculate": "sin({freq} * datum.t)", "as": "y"}],
"mark": "line",
"encoding": {
"x": {"field": "t", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
}
\```
template vega-lite: 后是 Vega-Lite JSON spec——Rho 用控件值替换 {var},再喂给 vega-embed 渲染。
渲染:滑块 + chart。拖 freq → sin({freq} * t) 重算 → 曲线变形。
依赖:要看 chart 渲染,project 需要
vega-embed:npm install vega-embed。
占位符在 vega-lite spec 里的位置
{var} 可以出现在 JSON 字符串值里,跟其他地方一样实时替换:
{
"transform": [
{"calculate": "{amplitude} * sin({frequency} * datum.t)", "as": "y"}
],
"encoding": {
"y": {"field": "y", "type": "quantitative", "scale": {"domain": [-{maxY}, {maxY}]}}
}
}
替换发生在 JSON 解析之前,所以 {var} 可在数字字段(域、轴范围、scale 上下界)或字符串字段(color hex / 标题)里用。
⚠️ 数字字段用
{var}(不带引号)—— 替换后是裸数字。 字符串字段用"{var}"(带引号)—— 替换后是字符串。
Examples
Example 1:正弦波 + 频率 / 振幅
\```interact
slider freq 0.5 5 1 0.1
slider amp 0.1 2 1 0.1
template vega-lite:
{
"width": 400,
"height": 200,
"data": {"sequence": {"start": 0, "stop": 6.28, "step": 0.05, "as": "t"}},
"transform": [
{"calculate": "{amp} * sin({freq} * datum.t)", "as": "y"}
],
"mark": "line",
"encoding": {
"x": {"field": "t", "type": "quantitative", "title": "时间 t"},
"y": {"field": "y", "type": "quantitative", "title": "振幅", "scale": {"domain": [-2, 2]}}
}
}
\```
渲染:两个滑块 + 正弦波 chart。改 amp 看振幅伸缩,改 freq 看波密度变。{amp} {freq} 在 calculate 里被替换。
Example 2:复利增长曲线
\```interact
slider principal 1000 100000 10000 1000
slider rate 0 0.15 0.05 0.01
slider years 5 50 20 1
template vega-lite:
{
"width": 500,
"height": 250,
"data": {"sequence": {"start": 0, "stop": {years}, "step": 1, "as": "year"}},
"transform": [
{"calculate": "{principal} * pow(1+{rate}, datum.year)", "as": "value"}
],
"mark": {"type": "line", "point": true},
"encoding": {
"x": {"field": "year", "type": "quantitative", "title": "年"},
"y": {"field": "value", "type": "quantitative", "title": "金额 ($)"}
}
}
\```
渲染:3 滑块 + 复利曲线,{years} 在 sequence 的 stop 里被替换 → x 轴范围跟随 years 变。
Example 3:概率密度(正态分布)
\```interact
slider mean -5 5 0 0.1
slider stddev 0.1 3 1 0.1
template vega-lite:
{
"width": 500,
"height": 250,
"data": {"sequence": {"start": -10, "stop": 10, "step": 0.1, "as": "x"}},
"transform": [
{"calculate": "(1 / ({stddev} * sqrt(2 * 3.14159))) * exp(-pow(datum.x - {mean}, 2) / (2 * pow({stddev}, 2)))", "as": "p"}
],
"mark": "area",
"encoding": {
"x": {"field": "x", "type": "quantitative", "title": "x"},
"y": {"field": "p", "type": "quantitative", "title": "P(x)"}
}
}
\```
渲染:拖 mean 看曲线左右移,拖 stddev 看曲线宽窄变。
Example 4:toggle 切图表类型
\```interact
toggle showArea false
template vega-lite:
{
"data": {
"values": [
{"month": "Jan", "v": 100},
{"month": "Feb", "v": 130},
{"month": "Mar", "v": 95},
{"month": "Apr", "v": 180},
{"month": "May", "v": 220}
]
},
"mark": "{showArea ? "area" : "line"}",
"encoding": {
"x": {"field": "month", "type": "ordinal"},
"y": {"field": "v", "type": "quantitative"}
}
}
\```
渲染:toggle 切 line 和 area。"{showArea ? ... : ...}" 在字符串字段做条件替换。
Plain-text fallback behavior
```interact 含 template vega-lite: 在不支持 reader 里:
\```interact
slider freq 1 10 3 0.1
template vega-lite:
{
... full vega-lite spec ...
}
\```
→ 显示为代码块——读者看到 sliders + 完整 vega-lite spec(含 {var} 占位符)。有经验的读者能猜出原来是 chart;普通读者看到的是结构化数据。
具体各 reader:
| Reader | 渲染效果 |
|---|---|
| Rho(含 vega-embed) | 完整可交互 chart |
| Rho(缺 vega-embed) | "Chart needs vega-embed" 提示 |
| GitHub web | 代码块(spec 全文可见) |
| Obsidian | 同上 |
| VS Code 默认预览 | 同上 |
| cat / less | plain text |
Common pitfalls
1. JSON 语法错
template vega-lite:
{
"mark": "line"
"encoding": { ... } ← ❌ 缺逗号
}
→ vega-embed 抛 JSON parse error,chart 不渲染。vega-lite spec 是严格 JSON——双引号 key、value 间逗号、严格 quote。
推荐:在外部 JSON 编辑器(VS Code)写好再贴进来,或用 vega-lite Editor (https://vega.github.io/editor/) 验证。
2. 占位符用错位置
template vega-lite:
{
"mark": {freq}, ← ❌ {freq} 替换后变成数字 3,但这里要字符串 "line"
...
}
→ 替换后产生非法 JSON。根据上下文确定 {var} 是否要带引号。
3. 数字字段误带引号
template vega-lite:
{
"encoding": {
"y": {"scale": {"domain": [-"{maxY}", "{maxY}"]}} ← ❌ 替换后是字符串 "10",scale.domain 要数字
}
}
→ 改成 [-{maxY}, {maxY}](不带引号)。
4. transform.calculate 表达式 syntax 跟 mini DSL 不同
template vega-lite:
{
"transform": [
{"calculate": "if (datum.x > 0) datum.x else 0", "as": "y"} ← ❌ vega 不支持 if/else 语句
]
}
→ vega-lite 的 calculate 用 vega expression 语法(不是 mini DSL)。三元式 cond ? a : b 支持,函数 sin / cos / pow / sqrt 等支持。详见 vega expression 文档。
5. data.sequence 范围太大
"data": {"sequence": {"start": 0, "stop": 1000000, "step": 0.001, "as": "x"}}
→ 1 billion 个数据点 → 浏览器卡死。控制点数 < 5000。曲线 < 500 点已经看着平滑。
6. chart 跟其他 chart 共用 data
\```interact namespace finance
slider rate 0 0.15 0.05 0.01
\```
\```interact namespace finance
template vega-lite:
{ ... uses {rate} ... }
\```
\```interact namespace finance
template vega-lite:
{ ... uses {rate} ... }
\```
✅ 合法 + 推荐——多个 chart 共用同一组 sliders,详见 Shared state。
7. 没装 vega-embed
\```interact
template vega-lite:
{ ... }
\```
→ 项目没 install vega-embed 时 chart 不渲染(显示提示或空白)。用 chart 必装 npm install vega-embed。
Vega-Lite spec 常用片段速查
折线图
{
"data": {...},
"mark": "line",
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
}
柱状图
{
"data": {...},
"mark": "bar",
"encoding": {
"x": {"field": "category", "type": "ordinal"},
"y": {"field": "value", "type": "quantitative"}
}
}
散点图
{
"data": {...},
"mark": "circle",
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"},
"size": {"field": "z", "type": "quantitative"}
}
}
参数化曲线(最常用)
{
"data": {"sequence": {"start": 0, "stop": 10, "step": 0.1, "as": "x"}},
"transform": [{"calculate": "...{your_expr}...", "as": "y"}],
"mark": "line",
"encoding": {
"x": {"field": "x"},
"y": {"field": "y", "type": "quantitative"}
}
}
详见 Vega-Lite 完整文档。
See also
- Interact controls — slider / input / select / toggle / button
- Interact text template — text template
- Computed — chart 也能引用 computed
- Timer — 让 chart 自动播放(动画)
- SVG scenes — 比 chart 更自由的图形
- Shared state (namespace) — 多 chart 共用 sliders
- Plain-text fallback principle