「所属网格」菜单:标题固定 + 10 行上限 + 滚动条;网格滚动联动改为动态过渡
1) 菜单滚动时最上方的「所属网格」标题不再跟着滚走
- 根因:上一轮只实现了“尾部固定区”(最后一个分隔线 + 「新建网格」钉在底部),
而滚动区是从条目 0 开始的,于是标题也被一起滚掉。
- 修法:BuildLayout 新增 m_scrollFirst(= 前导 HEADER / HEADER_ACTION 的个数),
滚动区收敛为半开区间 [m_scrollFirst, m_pinnedIndex):
· 前导标题从菜单顶向下固定排(不参与滚动);
· 滚动区条目受 m_scrollOffset 影响;
· 尾部固定区从菜单底向上对齐。
- 配套:Paint 的裁剪与“跳过不可见条目”范围、ItemAtPoint 的“必须落在滚动视口内”判定、
EnsureItemVisible 的下界全部改用该区间;新增 ScrollRegion(first, last) 供查询/测试。
2) 菜单长度上限改为「最多 10 条网格」并加滚动条
- MenuLayoutConstraint 新增 maxScrollRows(滚动区最多显示的标准行数;与 maxHeight
同时给出时取更严格者);OpenLaneMenu 传 10(kLaneMenuVisibleRows),
另保留 maxHeight = max(180, 客户区高 × 0.8) 作为矮窗口的硬上限。
- 新增滚动条:轨道贴滚动条目区右内侧(不盖住标题与底部固定项),滑块高度按视口/内容比
(下限 22 逻辑像素);滚动区条目宽度让出 kScrollBarWidth + kScrollBarGap,
文本与对勾不会压在滑块上。
- 滚动条可拖拽:按下滑块 → 拖动(只改偏移、不更新悬停);点击轨道空白 → 滑块中心移过去;
松开结束拖拽且不下发命令、菜单保持打开。新增 ScrollOffsetForThumbTop 反算偏移。
- ⚠️ BuildLayout 绝不能复位 m_scrollBarDragging:拖拽时每帧都会 RebuildLayout(),
在那里清零会让拖拽“拖一下就脱手”(该状态只在 Open / Close 里复位)。
3) 网格滚动联动改为动态过渡(旧实现直接把视界瞬移过去,过于僵硬)
- PlotView::ScrollLaneIntoView 只负责启动平滑动画:与信号列表的“滚动到目标信号”同源
(ease-out cubic;时长 clamp(距离×0.35ms, 130, 300)),新增
m_laneScrollAnimActive/From/To/StartMs/DurationMs。
- 宿主 16ms 定时器(kScrollTimerId)调用 AdvanceLaneScrollAnimation() 逐帧推进,
与信号面板动画共用同一条定时器;Render 的“需要保持定时重绘”判定加入
LaneScrollAnimationActive()。
- 每帧 ClampLaneScroll() + BuildLaneVisuals()(网格滚动量参与场景/图层指纹与各网格 rect);
结束时精确落到目标。已完整可见的网格仍然不启动动画。
- ⚠️ 用户自己滚动网格(滚轮 / 拖滚动条)会 CancelLaneScrollAnimation(),避免与动画抢滚动位置。
验证(全部离屏执行:窗口 SW_HIDE + 只注入合成消息 + 进程与线程 BELOW_NORMAL,
不移动真实光标、不抢焦点、不截屏):
- .preflight/check 扩到 95 项,95/95 通过;新增断言:
· 菜单顶部标题在滚动时不动(Y 坐标不变)、滚动视口高度恰为 10 × 行高;
· 滚动条轨道/滑块存在、随滚动移动、按住滑块拖到底(菜单不关、不下发命令、末条目入视口)、
滚轮回到顶部;
· ScrollLaneIntoView 不瞬移(刚触发时几乎未动)、中间帧单调递进、收尾精确到位、
已可见时不启动动画、滚轮/手动滚动会取消动画。
- A/B:回退三处(标题固定 / 10 行上限 / 滚动动画)⇒ 10 项如实失败;恢复后 95/95。
- make release / make debug 零警告。
文档:Documents/agent_mem.md 新增 §9.39、§11.2 第 104–107 条与变更日志一行。
This commit is contained in:
1 parent
2904699eae
commit
82b5ebe4f9
10 files changed
+496
-78
No files matched your search
@@ -2390,6 +2390,63 @@ Components/Shared/Src/UiControls.cpp
|
||||
|
||||
---
|
||||
|
||||
### 9.39 「所属网格」菜单:标题固定 + 10 行上限 + 滚动条,以及网格滚动联动改为动态过渡(本轮,起源设备)
|
||||
|
||||
> 用户 2026-10-16 第五轮(起源设备)。
|
||||
> 离屏验证:`.preflight/check` **95/95 通过**;**A/B**(回退顶部固定 + 回退 10 行上限 + 回退滚动动画)
|
||||
> ⇒ **10 项如实失败**;恢复后 **95/95**;`make release` / `make debug` **零警告**。
|
||||
|
||||
#### 一、菜单滚动时标题不再跟着滚(用户报告)
|
||||
|
||||
- **现象**:网格数很多时,滚动「所属网格」菜单的条目区,最上方的“所属网格”**标题也一起被滚走**。
|
||||
- **根因**:上一轮只实现了“**尾部**固定区”(最后一个分隔线 + 「新建网格」钉底),
|
||||
滚动区是从**条目 0** 开始的 —— 标题自然跟着滚。
|
||||
- **修法**:`BuildLayout` 新增 **`m_scrollFirst`**(= 前导 `HEADER` / `HEADER_ACTION` 的个数),
|
||||
滚动区变为半开区间 **`[m_scrollFirst, m_pinnedIndex)`**:标题从菜单顶向下固定排(`headCursorY`),
|
||||
滚动区条目才受 `m_scrollOffset` 影响,尾部固定区从菜单底向上对齐。
|
||||
- 配套更新:`Paint` 的裁剪/跳过范围、`ItemAtPoint` 的“必须落在滚动视口内”判定、
|
||||
`EnsureItemVisible` 的下界,都改用 `[m_scrollFirst, m_pinnedIndex)`。新增 `ScrollRegion(first, last)` 供查询/测试。
|
||||
|
||||
#### 二、菜单长度上限改为「鬃 10 条网格」+ 滚动条(用户要求)
|
||||
|
||||
- `MenuLayoutConstraint` 新增 **`int maxScrollRows`**(滚动区最多显示的标准行数)——
|
||||
比 `maxHeight` 更直观(“保留 10 条网格的上限”)。两个约束同时给出时**取更严格者**:
|
||||
`viewportLimit = min(maxHeight 换算的可用高, maxScrollRows × 标准行高)`。
|
||||
- `SignalPanel::OpenLaneMenu` 现在传 `maxScrollRows = kLaneMenuVisibleRows(=10)`
|
||||
(另外保留 `maxHeight = max(180, 客户区高 × 0.8)` 作为矮窗口的硬上限)。
|
||||
- **新增滚动条**(用户要求):轨道 `m_scrollBarRect` 贴在**滚动条目区**的右内侧(不盖住标题与底部固定项),
|
||||
滑块 `ScrollBarThumbRect()`(高度按视口/内容比,下限 `kScrollBarMinThumb=22`);
|
||||
滚动区的条目宽度**让出** `kScrollBarWidth + kScrollBarGap`,文本与对勾不会压在滑块上。
|
||||
- **滚动条可拖拽**:`OnLButtonDown` 命中滑块 → 开始拖拽(`m_scrollBarDragging`);
|
||||
命中轨道空白 → 把滑块中心移过去;`OnMouseMove` 拖拽中只调整偏移、**不更新悬停**;
|
||||
`OnLButtonUp` 结束拖拽且**不下发命令、菜单保持打开**。新增 `ScrollOffsetForThumbTop()` 反算偏移。
|
||||
- ⚠️⚠️ **`BuildLayout` 绝不能复位 `m_scrollBarDragging`**:拖拽时每帧都会 `RebuildLayout()`,
|
||||
在那里清零会把拖拽态**当场吃掉**(症状:按住滑块只能拖一下、随后就“脱手”)。
|
||||
|
||||
#### 三、网格滚动联动改为**动态过渡**(用户要求:旧实现“瞬移”太僵硬)
|
||||
|
||||
- **旧行为**:`PlotView::ScrollLaneIntoView` 直接 `Tab().LaneScroll() = desired` —— 视界瞬移过去。
|
||||
- **现行**:与信号列表的“滚动到目标信号”**同源**的平滑过渡:
|
||||
* `m_laneScrollAnimActive/From/To/StartMs/DurationMs`;
|
||||
* 时长 = `clamp(距离 × 0.35ms, 130, 300)`,进度再过 **ease-out cubic**;
|
||||
* 宿主 16ms 定时器(`kScrollTimerId`)调用 `AdvanceLaneScrollAnimation()`,与面板动画同一条定时器;
|
||||
* `Render` 的“需要保持定时重绘”判定加入 `m_plot.LaneScrollAnimationActive()`;
|
||||
* 每帧 `ClampLaneScroll()` + `BuildLaneVisuals()`(网格滚动量参与场景/图层指纹与各网格 rect)。
|
||||
- ⚠️ **用户自己滚动网格(滚轮 / 拖滚动条)必须 `CancelLaneScrollAnimation()`**,
|
||||
否则动画会与手动滚动抢滚动位置;`ScrollLaneIntoView` 对已完整可见的网格仍直接返回 false(不启动动画)。
|
||||
- 实测:154 个网格、距离 12091px 时动画 **20~21 帧**完成(≈300ms),中间帧滚动量单调递增、
|
||||
结束时**精确落到目标**且目标网格上下边界都在绘图区内。
|
||||
|
||||
#### 四、验证
|
||||
|
||||
- `.preflight/check` 新增断言:菜单**顶部标题在滚动时不动**、滚动视口高度恰为 **10 × 行高**、
|
||||
滚动条轨道/滑块存在且随滚动移动、**按住滑块拖到底**(菜单不关、不下发命令、末条目入视口)、
|
||||
滚轮回到顶部;`ScrollLaneIntoView` **不瞬移**(刚点击时几乎没动)、递进若干帧后精确到位、
|
||||
已可见时**不启动动画**、滚轮/手动滚动会取消动画。
|
||||
- **A/B**:回退三处(标题固定 / 10 行上限 / 滚动动画)⇒ **10 项如实失败**;恢复后 95/95。
|
||||
|
||||
---
|
||||
|
||||
## 10. 变更日志(本文件维护记录)
|
||||
|
||||
| 日期 | 设备/模型 | 摘要 |
|
||||
@@ -2442,6 +2499,7 @@ Components/Shared/Src/UiControls.cpp
|
||||
| 2026-10-16 | DeepSeek-V4.1-Flash(**另一台设备**) | **分组折起热区与改名输入框修正 + 数据模型去冗余(单一名称)+ 新增 `Components/Shared` 组件 + 过时注释/命名大清理 + 二进制瘦身 24.6% 并完成多文件拆分(详见 §9.37 与本轮报告 `Documents/refactor_report_2026-10-16.md`)**。① **折起热区**(用户要求):点分组**名称**不再折起,只有**折叠三角**或**「组X」标签**(新增 `RowPart::GROUP_TITLE`)才折起。② **分组改名输入框不再吞掉「N 项」**:`RowNameRect` 右边界改为项数左缘;新增 `GroupLabelText`/`GroupStatsText` 作为文本与宽度的唯一来源。③ **`SignalData`/`SignalGroup` 只留一个名称字段**:删除 `displayName` 与 `Title()`(31 处改用 `name`),`SetSignalDisplayName`/`SetGroupDisplayName` → **`RenameSignal`/`RenameGroup`**(空名一律拒绝);删除死成员 `Application::m_loadingBytes`。④ **新增 `Components/Shared`**(用户要求):从 `PaintUtil` 迁出全部**控件**(图标/复选框/滑块/内联输入框/颜色样块/取值胶囊配色)到 `UiControls.hpp/.cpp`,`PaintUtil` 只留低层原语;依赖方向固定 `Components/* → Components/Shared → Utilities`。⑤ **过时注释/命名**:`文件下标`→`分组下标`、`文件分组`→`分组` 等一批;形参名 `file`→`axis`/`group`;`PaintFileRow`→`PaintGroupRow`、`FileCloseRect`→`GroupCloseRect`、`OpenFileMenu`→`OpenGroupMenu`、`FileGroupLabelWidth`→`GroupLabelWidth`、`StyleEditField::FILE_NAME`→`GROUP_TITLE`;修复 `DataModel.hpp` 两处被压扁的注释块与 `NewTab` 重复文档块。⑥ **多文件拆分(本轮完成)**:`PlotView.cpp`(13 695 行)+ `SignalPanel.cpp` + `Application.cpp` + `DataModel.cpp` 四个大文件全部按功能拆成多个协作文件(私有内部头 + 具名命名空间 + 全 `inline` + 按名字分桶),最大单文件 544 KB → 276 KB。⑦ **二进制瘦身**:真因是 **ICO 里 256×256 未压缩 BMP 条目(270 KB,占整包 27%)**,改为 **PNG 存储**(观感零变化)⇒ `Target.exe` **1 013 248 → 764 416 B(−24.6%)**;实测“拆分不会减小机器码,反而 +1.4%”、`--gc-sections` 反而 +9 KB(已回退)。验证:`panelanim` **156/156**、`verify` **49/49**、`datacheck` **69/69**、`edgecheck` **46/46**;**A/B** 回退两处 UI 修复 **10 项如实失败**;`make release`/`make debug` 零警告。⚠️ 该提交当时的待办(`PlotView.cpp` 等大文件多文件化拆分、`LanePanelState` 抽取、模态提示解耦)**已全部在紧随其后的两个提交里完成**:拆分 → 提交 **`e6b7bf6`**(详见 §9.37 第七节),`LanePanelState` + 模态解耦 → 提交 **`d2e6fdd`**(详见 §9.37 第八节)。**本行不再表示任何未完成项。** |
|
||||
| 2026-10-16 | DeepSeek-V4.1-Flash(**另一台设备**) | **收尾:`LanePanelState` 抽取 + 错误提示非模态化(把上一行的「未完成」清零,详见 §9.37 第八节与报告 `Documents/refactor_report_2026-10-16.md` §九)**。① **`Lane` 的 12 个平铺面板字段**(`edgePanelOpen/X/Y` × 4 类实验性功能)→ **4 个 `LanePanelState`**(`struct LanePanelState { bool open=true; double x=-1; double y=-1; }`),访问点全部改为 `lane.edgePanel.open` 形式;`RebuildLanes` 的 `LaneCarry` 同步收敛为 4 个 `LanePanelState`(逐字段赋值 → 整体赋值)。⚠️ 教训:**批量改名脚本不能对「声明」与「使用」跑同一组替换对**(会生成 `bool edgePanel.open = true;` 非法声明),声明处须单独重写。② **错误提示与模态阻塞解耦**:新增 `Application::SetModalErrorsEnabled(bool)`/`ModalErrorsEnabled()`(成员默认 `true`),`Initialize` **最先**执行 `SetModalErrorsEnabled(showCommand != SW_HIDE)`(隐藏窗口弹模态框 = 进程被钉死);`SetStatusMessage(err,true)` 允许模态时原样 `MessageBoxW`,否则走 `m_plot.ShowPersistentHint(text)`(绘图区底部非模态浮层);`PlotView` 新增公开 `ShowPersistentHint`。普通提示/空文本仍被忽略 ⇒ **交互行为不变**。③ **顺带修掉真实缺陷**:`PlotView::Paint` 在 `m_lanes.empty()` 时提前 `return`,提示浮层在其后绘制 ⇒ **未勾选任何信号时错误永远不可见**(正是"加载失败"场景),该分支补一次 `PaintHint(g)`。④ **新增探针 `.preflight/perf/errcheck` 19/19**:默认值/隐藏降级/宿主开关、**工作线程 + 5s 超时**判"不阻塞"(旧行为会永久阻塞 ⇒ 判失败并 `ExitProcess`,探针不挂)、`EnumWindows` 数本进程 `#32770` 顶层窗口数不变、提示文本/粘滞/需重绘/起始时刻、**像素级**"有/无提示"差异 3781 且全帧差异同为 3781。验证:`make release`/`make debug` 零警告,`Target.exe` **764 416 B**;`verify` 49/49、`datacheck` 69/69、`edgecheck` 46/46、`panelanim` 156/156。⑤ **新增结构检查** `Tools/structcheck.ps1` + `make structcheck`(**93/93**):[1] 四个巨型文件已按职责拆分(`PlotView.cpp` 13 695 行 → 705 行,`nm`:绘制符号只在 `PlotViewPaint.o`);[2] `Components/Shared` 16 个控件全部由 `UiControls.o` 定义、69 处调用跨 ≥3 个组件 + 分层方向;[3] 本轮三项用户要求的源码级断言(折起热区、改名框不吞项数、`SignalData` 单一 `name` 字段 + 注释核验)。**判别力 A/B**:回退两处 UI 修复 ⇒ `panelanim` 147/156(9 项如实失败,文案点名“group rename box stops before the item counter”“clicking the group name does not collapse the group”)、`structcheck` 90/93;恢复后 156/156 与 93/93。 |
|
||||
| 2026-10-16 | DeepSeek-V4.1-Flash(**起源设备**) | **五项交互修复:折起后滚动条 / 单点信号样式 / 线宽实时生效 / 网格菜单限高滚动 / 点选信号滚动绘图区(详见 §9.38)**。① **分组折起后再展开滚动条消失**:`AdvanceGroupAnimations` 只在折起结束时重建行集合,而展开结束那一帧 `m_contentHeight` 跳回展开态却无人重算滚动条可见性 ⇒ 滚动条停在“隐藏”。修法:任一方向结束都 `m_rowsDirty = true` + `BuildRows()`,并**每帧** `RefreshScrollBar(false)`(动画期间不夹取滚动偏移,避免打断 `scrollSynced`)。② **单点信号默认绘制方式改「散点」**(原「点线」),且信号面板「样式」行的「线段」「点线」对它**置灰且不可点**(新增 `ModeOptionEnabled`,也不参与悬停高亮);`UpdateAutoScatterStyles` 跳过单点信号,避免“自动点线”与置灰状态自相矛盾。③ **拖动线宽滑块完全不生效**(用户报告:拖动时不变、松手瞬间变了、再移动鼠标又变回去)——根因两个:**`AcquirePolyline` 的缓存键漏了 `lineWidth`**(而 `BuildPolyline` 把线宽烘进包络带几何:逐列上下包络各外扩半个线宽,「梳状」判定也依赖它),以及**样式补丁没有同步宽基底图层**(下一帧宽基底快路径把新样式覆盖回旧像素)。修法:`PolylineCacheEntry` 新增 `lineWidth` 并进比较;样式补丁后 `QueueLaneRebuild(patchLanes) + RenderPendingLaneRebuilds(1)`。实测常量信号列厚 `0.5px→1px / 5.3px→7px / 10px→12px` 且松手与移动鼠标后**保持 12px**。④ **「目标」行的 GX 标签复用「所属网格」菜单**(与列表行徽标同一份),并先给 `PopupMenu` 加**限高 + 条目区滚动 + 尾部固定项**(`MenuLayoutConstraint::maxHeight`;固定区 = 最后一个分隔线及其后的「新建网格」;滚轮滚动、键盘移动自动滚入可视区;滚动区文本用 `UiTextClipped` 并跳过不可见条目;`ItemAtPoint` 增加滚动视口判定)——顺手解决“上百个网格时菜单超长且交互卡顿”;GX 标签点击**不参与**联动滚动,悬停联动保留。⑤ **点选信号名 ⇒ 绘图区自动把目标网格滚到可视区内**(`RequestPlotLaneScroll` / `ApplyPendingPlotLaneScroll` / `PlotView::ScrollLaneIntoView`):在上方就上滚、在下方就下滚、已可见则不动;**悬停不滚动**。验证:新增离屏 `.preflight/check`(`SW_HIDE` + 合成消息 + `BELOW_NORMAL`)**68/68**;**A/B** 五处修复全回退 ⇒ **17 项如实失败**(A 组需逐帧重绘驱动,单独回退 ⇒ 5 项);`make release` / `make debug` 零警告。⑥ 按要求**删除 `Tools/`(`structcheck`)并移除 `make structcheck` 目标**(§9.37/§11.2 第 96 条的“可复跑”描述自此失效,仅作历史证据)。 |
|
||||
| 2026-10-16 | DeepSeek-V4.1-Flash(**起源设备**) | **「所属网格」菜单标题固定 + 10 行上限 + 滚动条;网格滚动联动改为动态过渡(详见 §9.39)**。① **滚动时标题跟着滚掉**:上一轮只实现了尾部固定区(分隔线 + 「新建网格」钉底),滚动区从**条目 0** 开始 ⇒ 标题被一起滚走;修法:新增 `m_scrollFirst`(前导 `HEADER`/`HEADER_ACTION` 个数),滚动区变为 `[m_scrollFirst, m_pinnedIndex)`,标题从菜单顶向下固定排;`Paint` 裁剪/跳过、`ItemAtPoint` 视口判定、`EnsureItemVisible` 下界全部改用该区间,并新增 `ScrollRegion(first,last)` 查询。② **长度上限太大**:`MenuLayoutConstraint` 新增 `maxScrollRows`(**取 10 行**,与 `maxHeight` 取更严格者)⇒ 视口高恒为 10×行高;**新增滚动条**(轨道贴滚动区右内侧、滑块按视口比例、滚动区条目宽度让出滚动条宽度),且**可拖拽**(按下滑块/点击轨道开始拖、拖动只改偏移不改悬停、抬起结束且不下发命令、菜单保持打开),新增 `ScrollOffsetForThumbTop`。⚠️⚠️ 教训:**`BuildLayout` 绝不能复位 `m_scrollBarDragging`**(拖拽时每帧都 `RebuildLayout()`,清零会让拖拽“拖一下就脱手”)。③ **网格滚动联动旧实现是“瞬移”**:`ScrollLaneIntoView` 现在只**启动平滑动画**(`m_laneScrollAnimActive/From/To/StartMs/DurationMs`;时长 `clamp(距离×0.35ms,130,300)` + ease-out cubic,与信号列表同源),由宿主 16ms 定时器调用 `AdvanceLaneScrollAnimation()` 逐帧推进(`Render` 的定时器判定加入 `LaneScrollAnimationActive()`);用户滚轮/拖滚动条会 `CancelLaneScrollAnimation()`。实测 154 网格、距离 12091px 的动画约 20 帧完成并精确落位。验证:`.preflight/check` **95/95**;**A/B** 回退三处 ⇒ **10 项如实失败**;`make release`/`make debug` 零警告。 |
|
||||
|
||||
---
|
||||
|
||||
@@ -2942,6 +3000,25 @@ Components/Shared/Src/UiControls.cpp
|
||||
103. ⚠️ **交互类缺陷的离屏探针必须“每帧重绘”驱动**(动画 / 分帧推进 / 自持帧):
|
||||
面板 `Paint` → `EnsureRows()`、绘图区 `Paint` → 预算推进,都会在重绘时**顺手修复**一部分
|
||||
中间态;只在动作结束后才重绘会把“完成帧”的缺陷掩盖掉(本轮滚动条缺陷就因此假绿过一次)。
|
||||
104. ⚠️ **可滚动菜单的固定区是“两端”**:`[0, m_scrollFirst)` = 前导标题(`HEADER` / `HEADER_ACTION`,
|
||||
如「所属网格」)**钉在顶部不随滚动移动**;`[m_pinnedIndex, end)` = 最后一个分隔线及其之后的条目
|
||||
(如「新建网格」)钉在底部;只有中间 `[m_scrollFirst, m_pinnedIndex)` 是滚动区。
|
||||
裁剪(`Paint`)、命中(`ItemAtPoint` 要求条目同时落在滚动视口内)与 `EnsureItemVisible` 的边界
|
||||
都必须用这个区间,否则标题会被滚走(用户 2026-10-16 报告)。
|
||||
105. ⚠️ **菜单长度优先用「行数上限」表达**:`MenuLayoutConstraint::maxScrollRows`
|
||||
(滚动区最多显示 N 个标准行;与 `maxHeight` 同时给出时取更严格者)。
|
||||
当前「所属网格」菜单 = **10 行**(`kLaneMenuVisibleRows`)+ 右侧滚动条。
|
||||
滚动条必须**可拖拽**(按下滑块/轨道开始拖、`OnMouseMove` 只改偏移不改悬停、抬起结束且不下发命令)。
|
||||
⚠️⚠️ **`BuildLayout` 绝不能复位 `m_scrollBarDragging`**:拖拽时每帧都会 `RebuildLayout()`,
|
||||
在那里清零会让拖拽“拖一下就脱手”。
|
||||
106. ⚠️ **绘图区的“网格滚动到可视区”必须是平滑动画**(与信号列表同源:ease-out cubic、
|
||||
时长 `clamp(距离×0.35ms, 130, 300)`、宿主 16ms 定时器驱动):
|
||||
`ScrollLaneIntoView` 只负责**启动**动画(`m_laneScrollAnimActive`),`AdvanceLaneScrollAnimation`
|
||||
逐帧推进,`Render` 的定时器判定要带上 `LaneScrollAnimationActive()`。
|
||||
⚠️ 用户自己滚动网格(滚轮 / 拖滚动条 / 键盘)时必须 `CancelLaneScrollAnimation()`,否则两者抢滚动位置。
|
||||
107. ⚠️ **判断“动画是否真的在动态过渡”必须看**刚触发时**的状态**:只断言“最终把目标滚进可视区”
|
||||
对“瞬移”同样成立、毫无判别力。要断言:触发后立即仍几乎未动、中间帧单调递进、
|
||||
收尾精确到位(本轮 A/B 就是靠这三条排除了“直接赋值”的实现)。
|
||||
|
||||
### 11.3 离屏验证方法学(本机偏好,强烈建议沿用)
|
||||
|
||||
|
||||
Reference in new issue
Block a user