You need to enable JavaScript to run this app. 如何用原生JS实现滚动停止后回视口垂直居中的聊天组件过渡效果?
优惠活动
大模型
产品
解决方案
定价
更多

如何用原生JS实现滚动停止后回视口垂直居中的聊天组件过渡效果?

实现方案

你参考的方案存在的过渡卡顿问题,本质是元素在fixed/absolute定位模式间切换时,DOM会发生即时重排,没有平滑过渡的空间。本方案全程固定使用fixed定位,所有位置偏移通过transform属性实现,既可以精准模拟滚动跟随效果,又能依靠CSS原生过渡实现丝滑的回中动画,完全避免定位跳变问题,全程无jQuery依赖。

核心实现逻辑

  • 组件初始状态直接实现视口垂直居中,匹配页面加载时的展示要求
  • 滚动过程中给组件同步叠加和页面滚动距离相等的向上偏移,模拟普通文档元素的滚动跟随效果,滚动距离足够大时组件可完全移出视口
  • 通过定时器判定滚动停止时机,滚动停止后清除叠加的偏移量,依靠预先配置的CSS过渡让组件平滑回到视口居中位置
  • 滚动过程中临时关闭CSS过渡,保证滚动时的跟手性,避免动画延迟导致的拖影感

可直接复用的完整代码

<style>
/* 聊天组件基础样式 */
.chat-widget {
  position: fixed;
  width: 60px;
  height: 60px;
  border-radius: 8px;
  background: #1677ff;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  top: 50%;
  left: 50%;
  /* 预配置transform过渡规则,回中动画直接复用 */
  transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  transform: translate(-50%, -50%);
  z-index: 999;
}
/* 滚动状态下临时关闭过渡,保证跟手 */
.chat-widget.is-scrolling {
  transition: none;
}
/* 长页面测试用样式 */
.test-page {
  height: 200vh;
  background: #f5f5f5;
  padding: 20px;
}
</style>

<!-- 页面测试容器 -->
<div class="test-page">
  向下滚动页面测试效果
</div>

<!-- 聊天组件 -->
<div id="chatWidget" class="chat-widget">
  客服
</div>

<script>
const chatWidget = document.getElementById('chatWidget');
let scrollStopTimer = null;

// 监听页面滚动
window.addEventListener('scroll', () => {
  // 进入滚动状态,临时关闭过渡
  chatWidget.classList.add('is-scrolling');
  // 清除之前的停止判定定时器
  clearTimeout(scrollStopTimer);

  // 获取当前页面垂直滚动距离
  const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  // 同步叠加向上偏移,实现和文档元素一致的滚动跟随效果
  chatWidget.style.transform = `translate(-50%, calc(-50% - ${scrollTop}px))`;

  // 200ms无新滚动动作,判定为滚动停止
  scrollStopTimer = setTimeout(() => {
    // 恢复过渡效果
    chatWidget.classList.remove('is-scrolling');
    // 清除滚动偏移,组件自动带平滑动画回到居中位置
    chatWidget.style.transform = `translate(-50%, -50%)`;
  }, 200);
});

// 初始化:兼容刷新时页面已存在滚动偏移的场景
const initialScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (initialScrollTop > 0) {
  chatWidget.style.transform = `translate(-50%, calc(-50% - ${initialScrollTop}px))`;
}
</script>

效果说明

  • 页面加载时,组件稳定展示在视口垂直居中位置
  • 用户滚动页面过程中,组件与普通文档元素保持完全一致的移动速度,滚动距离足够大时会完全移出视口,过程无延迟、无跳变
  • 滚动停止200ms后,组件以0.3s的缓动动画平滑回到视口垂直居中位置,无生硬切换感
  • 所有位置修改均通过transform实现,不会触发页面重排,性能开销极低

内容的提问来源于stack exchange,提问作者Ricky55

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.25 08:06:03