模式 · 30
状态机
State machine · state-machine把开关过程写成明确的状态和允许的事件,重复点击也有确定结果。
详情面板不只有开与关,还有打开中、关闭中。只用一个布尔值,关闭动画还没结束时再次点开,容易生成两个面板或让回调写坏当前状态。状态机只接受当前状态允许的事件;其余输入当场忽略,并把原因显示出来。
公式
idle + OPEN → opening opening + DONE → open open + CLOSE → closing closing + DONE → idle any undefined transition → ignore
参数
| 本页默认 | 成熟实现 | |
|---|---|---|
| states | idle / opening / open / closing | — |
| events | OPEN / CLOSE / DONE | — |
| transition | 只接受表中允许的项 | — |
怎样做好
- 用过渡态保护动画的起点和终点。
cardwall的详情代码就用closed/open/closing阻止不合时机的开关。www-motion/rewrite/cardwall/detail.js:4–7 - 把允许的事件写成表;未列出的事件直接返回失败,不悄悄切换布尔值。www-motion/rewrite/cardwall/detail.js:4–7
- 完成回调也应作为事件,只在对应的过渡态里推进,避免旧动画覆盖新状态。www-motion/rewrite/cardwall/detail.js:4–7
在我们的案例里
59 个案例有显式状态控制。cardwall 的详情面板用 phase 守住开关入口;dimension 还把漩涡、爆发、链式画廊分成阶段,让同一个滚轮输入在不同阶段有不同含义。
出现在 59 个案例
01Momentum Slider02Drag Gallery03Formation04Cardwall05Riffle07Rotunda08Iris10Frieze11Aperture13Cinema Reel14Stream Showcase15Hardback16Picasso Ecommerce17Assembly19Emulsion20Portfolio Photographer21Reverie22Boutique
+41 更多
23Nova25Shape Trail27Liquid Type28Filament29Pixels30Cipher31Console32Cutout33Crema34Aster35Spring36Benchmark37Amour38Fluid Gallery39Marathon40Atelier41Desk 9542Isle43Pantheon44Atlas45Aurora46Rooster Rush47Overworld48Moments49Burst50Dimension51Morph54Lumen55Serene56Fleur59Helix60Crate61Prism62Flashlight63Viewfinder64Sand65Arrange66Tunnel67Reel68Type69Loupe
参考实现 · basics.js
/** Explicit states and allowed transitions: events not listed for the current state are ignored. */
export function createMachine({ initial, states }, onChange = () => {}) {
let state = initial;
return {
get state() { return state; },
can: event => !!states[state]?.on?.[event],
send(event) {
const next = states[state]?.on?.[event];
if (!next) return false;
states[state].exit?.(); const prev = state; state = next; states[state].enter?.();
onChange(state, prev, event);
return true;
},
};
}