Timer — auto-playing animation
用
timer声明一个自动跳变的数值变量——按固定 step 间隔自动从 min 走到 max,然后 loop / pingpong / 停下。 是 Interact controls 的 "时间维度" 兄弟——slider 是手动拖、timer 是自动走。配合 Vega chart / SVG scenes 做动画。
When to use
- ✅ 演示动画(让正弦波流动 / 让弹簧振动 / 让圆点绕圈)
- ✅ 数据回放(一帧一帧走时间序列)
- ✅ algorithm 自动 step-through(替代用户手动点 Next)
- ✅ 倒计时 / 计数器 / 番茄钟
- ❌ 离散点击触发(用
button而不是 timer) - ❌ 超长持续时间(
step太小或max-min太大 → 浏览器渲染压力大)
Basic syntax
\```interact
timer t 0 10 0.1 loop
template stl:
[当前时间] -> [{t:.1f}s]
\```
timer <name> <min> <max> <step> <mode> 声明一个 timer 变量。
| 参数 | 说明 |
|---|---|
name |
变量名 |
min |
起始值 |
max |
结束值 |
step |
每帧增量(约每 50ms 一帧) |
mode |
loop / pause / once / pingpong |
渲染:自动从 0 走到 10,每 50ms 加 0.1,到 10 后回到 0 重新开始(loop 模式)。template 实时显示 t 当前值。
Modes
| Mode | 行为 |
|---|---|
loop |
到 max 跳回 min 重新开始(最常用) |
pause |
默认暂停;用户点击播放按钮启动 |
once |
播放到 max 停止 |
pingpong |
min → max → min → max ... 来回往返 |
典型 frame rate: ~20 Hz(每 50ms 一步)。具体由 reader 实现。
Examples
Example 1:流动的正弦波
\```interact
timer t 0 6.28 0.05 loop
template vega-lite:
{
"width": 500,
"height": 200,
"data": {"sequence": {"start": 0, "stop": 6.28, "step": 0.05, "as": "x"}},
"transform": [
{"calculate": "sin(datum.x + {t})", "as": "y"}
],
"mark": "line",
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative", "scale": {"domain": [-1.5, 1.5]}}
}
}
\```
渲染:正弦波从右往左持续流动,像示波器。t 不停增长,sin(x + t) 让整条曲线相位移动。
Example 2:弹簧振子(位置 + 速度同时画)
\```interact
timer t 0 10 0.05 loop
template svg:
<svg viewBox="0 0 200 100">
<line x1="20" y1="50" x2="180" y2="50" stroke="#ddd" stroke-dasharray="2"/>
<circle cx="{100 + 60*sin(2*pi*t/2):.1f}" cy="50" r="6" fill="red"/>
</svg>
\```
渲染:红圆点在水平线上做简谐运动(左右往复),周期 2 秒。SVG cx 由 t 实时驱动。
Example 3:pause 模式 + 手动滑块当 scrubber
\```interact
timer t 0 60 0.1 pause
template vega-lite:
{
"data": {"sequence": {"start": 0, "stop": {t}, "step": 0.5, "as": "x"}},
"transform": [{"calculate": "{t}", "as": "y"}],
"mark": "line",
"encoding": {
"x": {"field": "x"},
"y": {"field": "y", "type": "quantitative"}
}
}
\```
渲染:默认暂停;用户点 Play 启动,再点 Pause 停。可拖底部 scrubber 跳到任意时刻。pause 模式给读者完全控制。
Example 4:pingpong(来回往返)
\```interact
timer angle 0 360 1 pingpong
template svg:
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="none" stroke="#ddd"/>
<line x1="50" y1="50"
x2="{50 + 40*cos(angle*pi/180):.2f}"
y2="{50 + 40*sin(angle*pi/180):.2f}"
stroke="red" stroke-width="2"/>
</svg>
\```
渲染:红线从 0° 转到 360°(顺时针绕一圈),到 360° 后反向绕回 0°,再正向……来回往复。比 loop 突跳回 min 平滑。
Plain-text fallback behavior
\```interact
timer t 0 10 0.1 loop
template stl:
[当前时间] -> [{t:.1f}s]
\```
→ 不支持的 reader 显示为代码块——读者看到 timer t 0 10 0.1 loop 声明 + template,理解原文档想 animate。
| Reader | 渲染效果 |
|---|---|
| Rho | 完整动画 + Play/Pause 控件 |
| GitHub web | 代码块(timer 声明可见) |
| Obsidian | 同上 |
| VS Code 默认预览 | 同上 |
| cat / less | plain text |
Common pitfalls
1. step 太小 → 浏览器卡
timer t 0 100 0.0001 loop ← ❌ 1,000,000 帧,浏览器死亡
timer t 0 100 0.5 loop ← ✅ 200 帧,30 秒一轮
经验值:(max - min) / step ≈ 100-1000 帧最舒服。
2. 多个 timer 同步问题
\```interact
timer t1 0 10 0.1 loop
timer t2 0 10 0.1 loop
\```
→ t1 和 t2 是独立的——可能 phase 不同步(看 reader 实现)。需要严格同步用一个 timer + computed 派生:
timer t 0 10 0.1 loop
computed t1 = t
computed t2 = (t + 5) % 10 ← 错相 5 秒
3. timer 被用作"计数器"(其实想要 button)
timer counter 0 1000 1 loop ← ❌ 自动一直涨,用户想点击 +1
→ 用 button + computed self-reference 做手动计数。
4. mode 拼写错
timer t 0 10 0.1 looping ← ❌ 不识别
timer t 0 10 0.1 LOOP ← ⚠️ 大小写敏感
timer t 0 10 0.1 loop ← ✅
只有 4 个合法 mode:loop / pause / once / pingpong。
5. timer 跟 slider 同名
\```interact
slider t 0 10 5 1
timer t 0 10 0.1 loop ← ❌ 重复声明
\```
→ 不能同名。timer 名跟 slider/input/computed 都不能撞。
6. once 模式停在 max 后无法重启
timer t 0 10 0.1 once
→ once 走到 max 就停,没有 reset 按钮。要"再播一次"加 button:
\```interact
timer t 0 10 0.1 once
button replay "再播一次" 0
template ...
\```
但实现上 button 触发 timer 重播的支持因 reader 而异——最可靠:用 loop 配 pause 让用户手动控。
7. timer 配 chart 但 transform.calculate 没用 timer 变量
\```interact
timer t 0 10 0.1 loop
template vega-lite:
{
...
"transform": [{"calculate": "sin(datum.x)", "as": "y"}] ← ❌ 没用 {t}
}
\```
→ 曲线永远不动,因为 calculate 不依赖 timer。记得在 vega 表达式里引用 {t}:"sin(datum.x + {t})"。
See also
- Interact controls — 手动控件(slider / button / 等)
- Interact + Vega-Lite chart — chart 配 timer 做动画
- SVG scenes — SVG 配 timer 做物理仿真
- Computed — 派生值(多 timer 同步用)
- Shared state (namespace)
- Plain-text fallback principle