fix(harmony): 补齐窗格切换动画(transition 挂在会换的那棵子树上)
用户(2026-09-17):「一方面一点动画都没有」。
★ 第一版写错了,这里记下来 —— 它的错法很典型,下次还会踩:
只在 onClick 里把 `currentIndex = ...` 包了一层 `getUIContext().animateTo(...)`,
并把 `.transition(...)` 挂在**内容容器(稳定父节点)**上。
编译过、判据(当时只钉"有 animateTo")全绿,**但动画是静默失效的**:
`animateTo` 只负责开一个动画窗口,被换掉的子树自己不声明 transition 就什么都不会动;
而挂 transition 的那个 Column 在新旧两种状态下**都是同一个节点**,永远不会触发。
实测取证:把时长临时改成 20s,6 秒后截图仍是硬切(收件箱整版清晰、没有叠影)。
修法(对齐 WebUI `.pane-rise` / `.rise-in`,`index.css:1208`):
· `Theme.paneRiseIn()` —— 4vp 上浮 + 淡入;`riseInOffset = 4` 与
`@keyframes rise-in { from { opacity:0; transform: translateY(4px) } }` 逐字一致。
· 挂到**if/else 各自的子树根**上(CommPage / ContactsTab / SettingsPane,
以及常驻+visibility 的日历那一支)—— 这才是会被插入/移除的节点。
· `TransitionEffect.asymmetric`:入场 180ms(durBase)、出场 120ms(durFast)。
出场更快是刻意的:同长会让新旧两层半透明地叠着,看起来像"闪一下",
而用户对"闪"敏感(09-14 否掉过整屏淡入)。
· 续用令牌 `durFast=120` / `durBase=180` / `easeOutSoft=cubic-bezier(0.22,1,0.36,1)`。
判据(219 passed / 0 failed):
· 新增「窗格切换有真的过场动画」6 条:令牌数值逐个钉死(120 / 180 /
cubic-bezier(0.22,1,0.36,1));`transition` 必须挂在 if/else 分支根(≥2 处,
含日历那一支);必须 asymmetric。
· **变异自检**:删掉那 4 处 `.transition(...)` ⇒ 该条立刻变红;还原 ⇒ 全绿。
留给以后的坑(写进 Theme 注释):`snapshot_display` 单次往返约 1s,
180ms 的过渡**抓不到**(连拍三帧像素级一致,会得出"动画没做"的错误结论)。
要取证就得把时长临时调到 20s 再取样,验完还原。本文件注释里留了这条与那次实测值。
未验:真机手感(模拟器已确认过渡链路生效);出场动画与详情 push 的叠加观感。
This commit is contained in:
@ -289,4 +289,42 @@ export class Theme {
|
||||
* 枚举是系统预设的**另一根**曲线,观感与 WebUI 对不上(而“对齐 WebUI”正是本项要求)。
|
||||
*/
|
||||
static readonly easeOutSoft: ICurve = curves.cubicBezierCurve(0.22, 1, 0.36, 1);
|
||||
|
||||
/**
|
||||
* 窗格入场时的上浮量(vp)。
|
||||
*
|
||||
* 4 —— **与 WebUI `@keyframes rise-in` 逐字一致**(`index.css:1208`):
|
||||
* `from { opacity: 0; transform: translateY(4px); }`
|
||||
* 只上浮 4vp,是"轻轻落位"而不是"整块飞进来"。用户对"闪/跳"敏感
|
||||
* (09-14 否掉过整屏淡入),所以这个数**不许**随手调大。
|
||||
*/
|
||||
static readonly riseInOffset: number = 4;
|
||||
|
||||
/**
|
||||
* 窗格入场过渡:4vp 上浮 + 淡入(对齐 WebUI `@keyframes rise-in`)。
|
||||
*
|
||||
* 做成方法而不是常量,是因为 `TransitionEffect` 是**有状态的构建器**
|
||||
* (`combine`/`animation` 会就地改自身),多处共用同一个实例会互相干扰;
|
||||
* 每处调用各拿一个新的。
|
||||
*
|
||||
* ★ 两边时长**不对称**:出场(120ms)比入场(180ms)快。
|
||||
* 同长会让新旧两层半透明地叠着,看起来像"闪一下"——
|
||||
* 用户对"闪"敏感(09-14 否掉过整屏淡入)。
|
||||
*
|
||||
* # 实测如何验证它真的生效
|
||||
*
|
||||
* `snapshot_display` 有 ~1s 往返,180ms 的过渡**抓不到**(连拍三帧全一样,
|
||||
* 会得出"动画没做"的错误结论)。做法:临时把 `durBase`/`durFast` 改成 20000,
|
||||
* 再过 6s 截图 —— 正常应看到新旧两层**同时半透明**地叠着
|
||||
* (实测已确认:收件箱与日历交叉淡入,样例点 (628,1450) 是混合值 164,165,167)。
|
||||
* 验完把时长还原成 120/180。
|
||||
*/
|
||||
static paneRiseIn(): TransitionEffect {
|
||||
return TransitionEffect.asymmetric(
|
||||
TransitionEffect.opacity(0).combine(
|
||||
TransitionEffect.translate({ y: Theme.riseInOffset })
|
||||
).animation({ duration: Theme.durBase, curve: Theme.easeOutSoft }),
|
||||
TransitionEffect.opacity(0).animation({ duration: Theme.durFast, curve: Theme.easeOutSoft })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user