From 7e1178fcb124c09ef7a0c37a6f23438a6da92e91 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Fri, 13 Nov 2026 22:30:17 +0800 Subject: [PATCH] =?UTF-8?q?docs(motion):=20M305=20r2=20=E2=80=94=E2=80=94?= =?UTF-8?q?=20=CE=B1=20=E5=8F=A3=E5=BE=84=E4=B8=8E=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=AF=B9=E9=BD=90=EF=BC=88=E5=94=AF=E4=B8=80=20=E2=86=92=20?= =?UTF-8?q?=E5=94=AF=E4=B8=80=E4=B8=80=E5=A4=84=E5=8A=A8=E7=94=BB=E4=B8=AD?= =?UTF-8?q?=E9=97=B4=E5=B8=A7=EF=BC=9B=E7=99=BB=E8=AE=B0=E4=B8=A4=E5=A4=84?= =?UTF-8?q?=E9=9D=99=E6=80=81=20=CE=B1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 只改 //! 文档行,零逻辑改动(git diff -U0 里没有一行非 //! 的增删): - motion/reveal.rs:「全仓唯一一处把 α 交给渲染器」→「唯一一处**动画中间帧**的 α」, 并指向 fade.rs 里登记的两处静态 α - motion/fade.rs:表里补两行静态例外 —— options/fade.rs::viewport_fade(常驻渐变, 12 条 1px 画布色块,α 从 (1/12)^1.6 到 1.0,不受 D27 约束的原因写清)与 ui.layer() 的 panel_alpha(CPU 强制 1.0;GPU 开背景图时才是真 α,属另一条线) --- crates/app-iced/src/components/motion/fade.rs | 18 +++++++++++++----- .../app-iced/src/components/motion/reveal.rs | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/app-iced/src/components/motion/fade.rs b/crates/app-iced/src/components/motion/fade.rs index 57add7d..00b4de4 100644 --- a/crates/app-iced/src/components/motion/fade.rs +++ b/crates/app-iced/src/components/motion/fade.rs @@ -10,12 +10,20 @@ //! 本模块的工具是 [`mix`]——两个**不透明**色之间按进度插值,用于「进度条到达 100% 时那一下 //! 强调收束」(`feedback/progress.rs::linear_with`)。它不改几何、不改厚度,所以**不引起重排**。 //! -//! ## 唯一的例外:子树淡出(口径写在这里,别处不许再有第二种说法) +//! ## 把 α 交给渲染器的地方(口径写在这里,别处不许再有第二种说法) //! -//! | 场景 | 做法 | 产物透明度 | -//! |---|---|---| -//! | 颜色插值(进度条收束、遮罩浓度、禁用层) | [`mix`] / `with_alpha(α).over(底)` | **恒 1.0** | -//! | **一整棵子树淡出**(列表行) | `motion/reveal.rs` 的收尾遮罩:与**画布同色**的 quad,α = 1 − 可见度,且**必须自成一层** | 动画期间 < 1,**静息帧严格不画** | +//! | 场景 | 做法 | 产物透明度 | 是不是动画 | +//! |---|---|---|---| +//! | 颜色插值(进度条收束、遮罩浓度、禁用层) | [`mix`] / `with_alpha(α).over(底)` | **恒 1.0** | 是 | +//! | **一整棵子树淡出**(列表行) | `motion/reveal.rs` 的收尾遮罩:与**画布同色**的 quad,α = 1 − 可见度,且**必须自成一层** | 动画期间 < 1,**静息帧严格不画** | 是(唯一一处**动画中间帧**的 α) | +//! | **滚动视口底部的淡出带**(M227) | `pages/download/options/fade.rs::viewport_fade`:12 条 1px 的**画布色**块,α 从 `(1/12)^1.6 ≈ 0.019` 递到 1.0,经 `frame::filled` 进 `container::Style` | 常驻 α∈(0,1] | **否**(静态渐变) | +//! | 面板层(Card / Overlay) | `theme.rs::layer` × `panel_alpha`(`MaterialLayer::allows_translucency`) | CPU 档被强制 **1.0**;GPU 档开背景图时可 < 1 | 否(静态) | +//! +//! 两处**静态** α 为什么不归 D27 管(也**不在**本文「`mix` 恒不透明」那条口径内): +//! ①`viewport_fade` 是**常驻**的发现性提示——iced 0.14 没有渐变原语,12 条 1px 实色块是它的替代品, +//! 而且它的颜色恒等于它盖住的画布色(`ui.layer(Canvas)`),浅色/深色都不新增颜色; +//! ②`panel_alpha` 是「GPU 档开背景图」那条线自己的决定(`elevation.rs` 的 `allows_translucency`), +//! CPU 档由 `app` 侧强制 1.0,与动效无关。这一支属**另一条线**,本文不覆盖。 //! //! 为什么子树淡出做不到「预合成」:预合成要求先知道被盖住的像素(`content.with_alpha(α).over(底)`), //! 而「一行的内容」在 `Element` 里是黑盒;唯一可行的替代是把整份 `Scheme` 预合成后换一个 `Ui` diff --git a/crates/app-iced/src/components/motion/reveal.rs b/crates/app-iced/src/components/motion/reveal.rs index 2e5c806..b37a015 100644 --- a/crates/app-iced/src/components/motion/reveal.rs +++ b/crates/app-iced/src/components/motion/reveal.rs @@ -27,7 +27,7 @@ //! | 为什么不用预合成(`with_alpha(α).over(底)`,D27 的正统口径) | 预合成要先知道被盖住的像素,而「一行的内容」在 `Element` 里是黑盒;替代方案(把整份 `Scheme` 预合成后传一个 `Ui` 下去)要求那个 `Ui` 活得比 `Element<'a>` 久——视图函数里造不出来,泄漏成 `'static` 则是每帧每行泄漏一份 49 色方案 | //! | 为什么必须 `with_layer` | tiny-skia 的绘制按「四边形 → 三角 → 图 → 文字」分批(`iced_tiny_skia/src/lib.rs::present`),同层里文字永远排在四边形之后。第一版把遮罩塞进当前层:红色 α=0.3 的遮罩实测**一个文字像素都没盖住**(整图 0 个偏红像素);改成子层后同一实验 422 个偏红像素、正好落在动的那两行(y 262..307) | //! | 静息帧 | `veil = None` ⇒ **一个 quad 都不画**,与改造前逐像素相同(出图基线与 M305 之前同源) | -//! | 口径归属 | 这是全仓**唯一**一处「把 α 交给渲染器」的地方,规则的真源写在 `motion/fade.rs` 的模块文档。`interaction/mod.rs` 的 α 守卫只扫状态层取色、**扫不到**这里(不经过任何 `Style`)——盲区已登记在 `fade.rs` | +//! | 口径归属 | 这是全仓**唯一一处「动画中间帧」的 α**:只有退场/入场那 150~200ms 里出现,静息帧严格不画。规则的真源写在 `motion/fade.rs` 的模块文档,那里同时登记了两处**静态**的 α(不在本文口径内):`options/fade.rs::viewport_fade` 的常驻渐变、`ui.layer()` 的 `panel_alpha`(GPU 档开背景图时)。`interaction/mod.rs` 的 α 守卫只扫状态层取色、**扫不到**这里(不经过任何 `Style`)——盲区已登记在 `fade.rs` | //! //! ## 与 `clip.rs` 的区别(为什么不再写一个通用件) //!