发布于: 2024-12-13最后更新: 2026-7-21字数 1019阅读时长 3 分钟

NoIndex
date
Dec 13, 2024
icon
password
Featured
Evergreen
LastVerified
synced
synced
paired_with
3551d487-a2a1-81d8-ad0f-f1ba4443cdcb
RedirectFrom
UpdateType
NotificationPolicy
TechVersions
type
Post
Series
category
技术分享
NotificationVersion
source_hash
md:v1:ed066ba0f37e3ee8fd1f6e1fe3d6139aa1761286752371e7af49c82cda08e79e
slug
内容自动跟随
RelatedProjects
translation_locked
translation_locked
status
Published
summary
AI 聊天界面的自动滚动不是两行 scrollTop,而是用户意图识别、跟随状态机、虚拟滚动和移动端边界的组合。
tags
工具
开发
思考
人工智能
NotifyAt
ContentType
💭
做 AI 聊天产品有一个细节最容易翻车,那就是"自动滚到底部"。AI 在流式输出,新字一个一个往外蹦,理想状态下窗口跟着滚到最新的位置。但如果用户中途想往上看一眼之前的内容,它又得识相地停下来。这个判断"用户现在到底想不想跟"的小逻辑,看着两行代码就能写完,实际上踩坑能踩半年。这篇聊聊我做这一类功能时的几次反复。

最简单的版本

第一版我和大多数人一样,用阈值。距离底部多少像素之内算"用户想跟",超出就停。
跑起来很丝滑。但只要用户想往上回看一段比较长的回答,就会发现一个尴尬的现象。AI 还在生成,每来一段新内容,scrollHeight 变大,distance 跟着变大,于是 shouldAutoScroll 翻成 false,看起来像"它停了"。但只要 distance 再次掉到阈值以内(比如用户继续往下滚),它又会自动跳到底部,把用户当前看的内容一下顶飞。

第二版,加状态机

意识到这是状态问题之后,我把它改成显式的"跟随模式"。
关键是把"用户主动滚动"和"内容增长导致的位置变化"分开来。前者影响模式,后者只在 following 模式下才触发自动滚。
但还有个细节。怎么区分"用户主动滚"和"我自己滚的"?因为每次 scrollTop = scrollHeight 也会触发一次 scroll 事件。解决办法是写完之后立刻设个 flag

长对话的性能问题

问题不止在状态切换。当一段对话长到几千行,DOM 节点全部留着,光是滚动本身就开始卡。这时候得上虚拟滚动,只渲染视窗附近的几屏内容。
但虚拟滚动给"自动跟到底部"这件事增加了难度。scrollHeight 是按"假装所有 item 都渲染了"算的虚拟高度,所以 scrollTop = scrollHeight 不再等于"滚到最后一条"。要专门写一个 scrollToIndex(lastIndex) 才行。

那些更隐蔽的边界情况

写这种自动滚的时候,能掉进的坑远不止上面几个。
  • 窗口缩放。用户拉大浏览器窗口,clientHeight 变了,distance 算法重新跑一遍判断
  • 字号变化。用户按 Ctrl 加号放大字体,每个 item 的高度变了,虚拟滚动里假定的 itemHeight 失效
  • 图片加载。AI 输出里嵌了图,图加载完之前 DOM 里它的高度是 0,加载完后突然撑高,跟随逻辑乱跳
  • 键盘事件。用户按 Page Up 翻页,应该被识别为"想自由浏览",进入 free 模式
  • 触摸滑动。手机端用户用手指滑屏,wheel 事件不会触发,得听 touchmove
每一个都不难,但加起来够你写一个礼拜的。

写在最后

最后我学到一件事,跟用户意图打交道的功能,不要去预测用户想要什么,而是老老实实记录用户做了什么。所谓"智能跟随",本质上是把用户的滚动行为分类(主动离开 / 主动回归 / 被动跳变)然后按规则响应。机器学习不是这件事的好答案,状态机才是。

📎 参考文章

继续关注

通过开放 Feed 获取新文章、研究和重要更新。


Loading...
算法学习的正确姿势:先理解,再写代码

算法学习的正确姿势:先理解,再写代码

学算法要先画结构、模拟过程、讲清不变量,再把思路写成代码。


Next.js 还是 Remix:OpenAI 迁移之后怎么选

Next.js 还是 Remix:OpenAI 迁移之后怎么选

借 OpenAI 从 Next.js 迁到 Remix 的案例,比较两个 React 框架的数据加载、服务端渲染和心智模型,并给出个人项目和大流量产品的选择建议。


公告
网站持续更新中…