-
-
Couldn't load subscription status.
- Fork 2.4k
Improve automatic scrolling when dragging items in the outline #15846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -31,6 +31,9 @@ export class Outline extends Model { | |||||
| public blockId: string; | ||||||
| public isPreview: boolean; | ||||||
| private preFilterExpandIds: string[] | null = null; | ||||||
| private scrollAnimationId: number | null = null; | ||||||
| private scrollLastFrameTime: number = 0; | ||||||
| private scrollCurrentFPS: number = 60; | ||||||
|
|
||||||
| constructor(options: { | ||||||
| app: App, | ||||||
|
|
@@ -380,11 +383,68 @@ export class Outline extends Model { | |||||
| }); | ||||||
| return; | ||||||
| } | ||||||
| // 检查是否在滚动边界区域 | ||||||
| if (moveEvent.clientY < contentRect.top + Constants.SIZE_SCROLL_TB || moveEvent.clientY > contentRect.bottom - Constants.SIZE_SCROLL_TB) { | ||||||
| this.element.scroll({ | ||||||
| top: this.element.scrollTop + (moveEvent.clientY < contentRect.top + Constants.SIZE_SCROLL_TB ? -Constants.SIZE_SCROLL_STEP : Constants.SIZE_SCROLL_STEP), | ||||||
| behavior: "smooth" | ||||||
| }); | ||||||
| // 如果还没有开始滚动,则开始持续滚动 | ||||||
| if (!this.scrollAnimationId) { | ||||||
| const scrollDirection = moveEvent.clientY < contentRect.top + Constants.SIZE_SCROLL_TB ? -1 : 1; | ||||||
| this.scrollLastFrameTime = performance.now(); | ||||||
| let scrollFrameCount = 0; | ||||||
|
|
||||||
| const scrollAnimation = (currentTime: number) => { | ||||||
| if (!this.scrollAnimationId) { | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| // 每隔 20 帧重新计算一次帧率 | ||||||
| if (scrollFrameCount % 20 === 0) { | ||||||
|
||||||
| const deltaTime = currentTime - this.scrollLastFrameTime; | ||||||
| this.scrollLastFrameTime = currentTime; | ||||||
| // 计算过去 20 帧的平均帧率 | ||||||
| this.scrollCurrentFPS = deltaTime > 0 ? (20 * 1000) / deltaTime : 60; | ||||||
| } | ||||||
| scrollFrameCount++; | ||||||
|
|
||||||
| // 基于当前帧率计算滚动步长,确保等效于 60fps 时的 16px/帧 | ||||||
| const baseScrollStep = 16; | ||||||
| const targetFPS = 60; | ||||||
|
Comment on lines
+408
to
+410
|
||||||
| const scrollStep = baseScrollStep * (targetFPS / this.scrollCurrentFPS); | ||||||
|
|
||||||
| this.element.scroll({ | ||||||
| top: this.element.scrollTop + scrollStep * scrollDirection | ||||||
| }); | ||||||
|
|
||||||
| // 使用 requestAnimationFrame 继续动画 | ||||||
| this.scrollAnimationId = requestAnimationFrame(scrollAnimation); | ||||||
| }; | ||||||
|
|
||||||
| // 检查浏览器是否支持 requestAnimationFrame | ||||||
| if (typeof requestAnimationFrame !== "undefined") { | ||||||
| this.scrollAnimationId = requestAnimationFrame(scrollAnimation); | ||||||
| } else { | ||||||
| // 回退到 setTimeout 方法 | ||||||
| const scrollInterval = 16; // 约 60fps | ||||||
| const scrollStep = 16; // 每次滚动的距离 | ||||||
|
||||||
| const scrollStep = 16; // 每次滚动的距离 | |
| const scrollStep = Constants.SIZE_SCROLL_STEP; // 每次滚动的距离 |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The scroll animation cleanup logic is duplicated in two places (lines 440-447 and 480-487). Consider extracting this into a private method to reduce code duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The logic for checking scroll boundaries and starting animation is nested deeply within the existing drag logic. Consider extracting the scroll animation logic into a separate private method to improve code organization and readability.