Skip to content

fix(table): use rowHeightsMap directly in scrollToCell to fix position with dynamic row heights#5051

Merged
fangsmile merged 1 commit intoVisActor:fix/5020-scrollToRow-dynamic-row-heightfrom
william-xue:fix/5020-scrollToRow-dynamic-row-height
Mar 17, 2026
Merged

fix(table): use rowHeightsMap directly in scrollToCell to fix position with dynamic row heights#5051
fangsmile merged 1 commit intoVisActor:fix/5020-scrollToRow-dynamic-row-heightfrom
william-xue:fix/5020-scrollToRow-dynamic-row-height

Conversation

@william-xue
Copy link

变更说明

scrollToRow / scrollToCell 在使用动态行高(如 autoWrapText: true)时,滚动位置不准确,特别是在最后一两屏时偏差明显。

根因分析

scrollToCell 调用 getRowsHeight(0, row-1) 计算目标行的像素位置。该函数存在一个 fast path:当 heightMode === 'standard'_heightResizedRowMap.size === 0 时,对 body rows 直接用 defaultRowHeight × count 计算,完全忽略 rowHeightsMap 中存储的实际行高。

autoWrapText 渲染时通过 _setRowHeight 将实际行高写入 rowHeightsMap,但不会写入 _heightResizedRowMap,因此 fast path 的条件始终成立,导致已计算的实际行高被忽略。

结果:目标滚动位置(top)和最大滚动上限(getAllRowsHeight() - drawHeight)均基于 defaultRowHeight 估算,与实际像素偏移不符。

修复:在 scrollToCell 中直接使用 rowHeightsMap.getSumInRange 计算行高偏移,绕过 fast path。对于未渲染的行,getSumInRange 内部同样回落到 getRowHeight(i)defaultRowHeight),故未渲染行的行为不变。

-const top = this.getRowsHeight(0, cellAddr.row - 1);
-this.scrollTop = Math.min(top - frozenHeight, this.getAllRowsHeight() - drawRange.height);
+const top = this.rowHeightsMap.getSumInRange(0, cellAddr.row - 1);
+this.scrollTop = Math.min(top - frozenHeight, this.rowHeightsMap.getSumInRange(0, this.rowCount - 1) - drawRange.height);

关联 Issue

Closes #5020

测试

  • autoWrapText: true + 10000 条数据,调用 scrollToRow(9990),确认滚动位置正确(目标行出现在视口内)
  • autoWrapText 的普通表格 scrollToRow 行为不变
  • 用户手动拖拽调整行高后 scrollToRow 位置正确

…n with dynamic row heights

getRowsHeight() has a fast path that multiplies defaultRowHeight by the row count for
body rows when heightMode is 'standard', completely ignoring rowHeightsMap. This means
rows with computed heights (e.g. from autoWrapText) are not reflected in the scroll
position calculation, causing scrollToRow to land at the wrong position.

Fix: use rowHeightsMap.getSumInRange directly in scrollToCell so that actual
computed row heights are used for both the target position and the max-scroll cap.
For unrendered rows, getSumInRange already falls back to getRowHeight (defaultRowHeight),
so behavior is unchanged when no rows have been dynamically sized.

Closes VisActor#5020
// This ensures dynamically-computed row heights (e.g. autoWrapText) are reflected
// in the scroll position calculation.
const top = this.rowHeightsMap.getSumInRange(0, cellAddr.row - 1);
this.scrollTop = Math.min(top - frozenHeight, this.rowHeightsMap.getSumInRange(0, this.rowCount - 1) - drawRange.height);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里也有使用getSumInRange。你的case不是走的这个逻辑吗?

Image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

autoWrapText 走 _setRowHeight(只写 rowHeightsMap,不写 _heightResizedRowMap),所以 _heightResizedRowMap.size === 0 始终成立,fast path 始终命中,else 分支永远走不到

@fangsmile fangsmile changed the base branch from develop to fix/5020-scrollToRow-dynamic-row-height March 17, 2026 07:59
@fangsmile fangsmile merged commit c972502 into VisActor:fix/5020-scrollToRow-dynamic-row-height Mar 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 动态行高下,调用scrollToRow ,滚动到的位置不对

2 participants