跨端: 鸿蒙动画补齐 —— 并且发现原来的「逐字一致」是假的(令牌存在 ≠ 动画用了它)
用户:「A,同时把鸿蒙app的动画补齐」。 ## 先纠一条错的前提(这是本轮最有价值的发现) `Theme.ets` 的注释与 `harmony-nav` 的判据**都**写着:「三个数与 WebUI **逐字一致**: `--ease-out-soft: cubic-bezier(0.22,1,0.36,1)`、`--dur-fast: 120ms`、`--dur-base: 180ms`」, `paneRiseIn()` 就按 `durBase(180)` + `easeOutSoft` 做。 三个令牌**确实存在**(`index.css:310-312`)—— 但这句话把「令牌存在」当成了「动画用了它」: | WebUI 里 | 真实用途 | |---|---| | `--dur-base: 180ms` | **只**用在壁纸淡入(`:747`) | | `--ease-out-soft (0.22,1,0.36,1)` | **只**用在 transition(壁纸、控件变色) | | **所有 @keyframes 动画** | 硬编码 **150ms / 200ms** + `cubic-bezier(0.22, 0.61, 0.36, 1)` | 全仓 `(0.22,0.61,0.36,1)` 出现 **5 次**(rise-in×3 / cal-in×2),`(0.22,1,0.36,1)` 只出现 **1 次**(令牌定义处)。**是两根不同的曲线** —— 旧代码的面板入场比 WebUI 慢 30ms 且曲线偏软。 所以令牌拆成两组,各对齐各的:控件类 `durFast + easeOutSoft`;动画类 `durRise(150)/durMenu(140)/durCal(200) + easeRise(0.22,0.61,0.36,1)`。 ## 补的动画(对齐 WebUI 三个 @keyframes) - `menuIn()` —— 弹层:下移 4vp + 缩到 0.985 + 淡入(`@keyframes menu-in`)。 ★ 适用范围照搬 WebUI 注释那条窄口径(「只给真正是弹层的东西」):那条规则曾挂着 `glass-control`,于是每次切视图**所有按钮与输入框一起淡入位移**,09-15 被摘掉。 挂到写邮件页的账号候选列表上。 - `calendarSlide(forward)` —— 日历翻月:从 ±12% 横向滑入(`cal-in-next/prev`)。 方向由新增 `@State slideForward` 带进 `animateTo` 闭包;网格键加 `monthKey()` 前缀 保证月份一变所有键全变(否则"跨年同名月"那类边角会静默不播)。 - 写信页整页 `rise-in`、回复框 `rise-in`(WebUI 挂在回复框本身,不是外层遮罩 —— 挂遮罩上会让整个屏幕一起位移,看起来是"页面在动"而不是"框弹出来")。 **实测确认真的会播**(不是"编译过了"):按本仓记录的手法把 `durCal` 临时改成 8000 做慢动作,连拍三帧 —— 截图硬证**两张月历同时在屏**(九月淡出、十月从右侧 12% 滑入), 验完还原成 200ms。 ## 判据:从「令牌存在」改成「动画真的用了那个令牌」 `harmony-nav` 那条判据原文锚在令牌上,所以它对上面那个 bug **一辈子全绿**。 重写为: - 从 WebUI `index.css` **读出** `rise-in` 的真实时长与曲线(`150ms` + 那条 bezier), 再断言鸿蒙的 `durRise` 与曲线字面量与之逐字一致 —— 而不是"仓库里有没有 180 这个数"; - ★ 把 `paneRiseIn()` 的**函数体抠出来**单独断言它引的是 `durRise/easeRise`, 且**不得出现** `durBase/easeOutSoft`。 **这一步不能省 —— 我第一版就漏了它**:断言了令牌存在、也断言了曲线字面量存在, 但没断言函数用了它们;于是把函数体换回旧的错值后判据**仍然全绿**。 变异自检抓住了这一点,补上函数体断言后同一个变异 ⇒ 判红 ✓。 与今天修的另一处同源:**判据要锚在"这个东西被用在哪",不是"它存在"**。
This commit is contained in:
@ -2189,17 +2189,20 @@ struct MainPage {
|
||||
* ★ 换窗格要**真的**有过渡:`animateTo` 只开了一个动画窗口,
|
||||
* 被换掉的那棵子树自己不声明 `.transition(...)` 的话什么都不会动
|
||||
* (实测:只包 `animateTo` 和硬切看不出差别)。
|
||||
* 过场动画挂在**内容容器**上(见 build 里 `Column().transition(...)`),
|
||||
* 过场动画挂在**内容容器**上(见 build 里各分支的 `.transition(Theme.paneRiseIn())`),
|
||||
* 这里只负责把 index 变掉;系统在动画窗口内跑那条 transition。
|
||||
*
|
||||
* 时长/曲线用令牌:`durFast`(120) —— WebUI 对应物是
|
||||
* `.rise-in { animation: rise-in 150ms cubic-bezier(0.22,0.61,0.36,1) }`,
|
||||
* 同一档(百毫秒级、不拖)。曲线用令牌里那条 `easeOutSoft`,
|
||||
* 与 WebUI 的 `.pane-rise` 同一根尺子。
|
||||
* ★★ 2026-09-18 更正:这里原先用 `durBase(180)` + `easeOutSoft(0.22,1,0.36,1)`,
|
||||
* 并写着"与 WebUI 的 .pane-rise 同一根尺子" —— **那两个数都不是动画值**。
|
||||
* 实测 WebUI:`.rise-in`/`.pane-rise` 都是 **150ms + cubic-bezier(0.22, 0.61, 0.36, 1)**;
|
||||
* 180ms 与 `(0.22,1,0.36,1)` 只用在**壁纸淡入**与**控件变色 transition** 上。
|
||||
* 所以旧代码的窗格入场比 WebUI 慢 30ms 且曲线偏软。
|
||||
* 现在两边都用 `durRise` + `easeRise`,与 `paneRiseIn()` 内那份保持一致
|
||||
* (同一场过场被两个地方描述,数值必须同源 —— 所以都引令牌,不写数)。
|
||||
*/
|
||||
this.getUIContext().animateTo({
|
||||
duration: Theme.durBase,
|
||||
curve: Theme.easeOutSoft
|
||||
duration: Theme.durRise,
|
||||
curve: Theme.easeRise
|
||||
}, () => {
|
||||
this.currentIndex = target;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user