You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

页面先水平滚动后垂直滚动的交互实现及参数设置咨询

解决水平转垂直滚动的两个核心问题

我来帮你理清这两个关键问题,咱们一步步拆解:

1. Horizontal区域的高度设置逻辑

Horizontal区域的高度决定了用户需要垂直滚动多少距离,才能完成整个水平滚动流程。它的核心关联公式是:

horizontal高度 = (内部元素总宽度 - 视口宽度) * (视口高度 / 视口宽度)

为什么是这个公式?

假设你的水平滚动区有N个100vw宽的item,那么内部元素总宽度是N * 100vw,需要水平移动的总距离是(N-1)*100vw(从第一个item到最后一个item完全占满视口)。

为了让鼠标滚轮的滚动体验更自然,我们希望垂直滚动的距离和水平移动的距离成比例:当你垂直滚动H像素时,水平刚好移动完(N-1)*100vw的距离。这个比例就是视口高度和宽度的比值(因为滚轮滚动的感知是垂直方向的,要对应水平方向的移动幅度)。

简化后,当每个item都是100vw宽时,公式可以写成:

horizontal高度 = (N-1) * 100vh

比如2个item时,高度就是100vh;3个item时就是200vh,以此类推。

2. 正确的Translate比例计算

我们的目标是:当垂直滚动到horizontal区域的底部时,水平滚动区的最后一个item刚好完全占满视口。对应的transform计算逻辑是:

水平移动距离 = - (垂直滚动距离 * 视口宽度 / 视口高度)

原理

当你滚动y像素的垂直距离时,水平方向需要移动的距离是y * (视口宽度/视口高度)——这个比例保证了滚动体验的一致性。用负数是因为要向左移动。

如果用百分比的话,也可以基于.slider-inner的总宽度计算,但用视口单位或px更直观,避免百分比的混淆。

修改后的完整代码

JavaScript

let slider = document.querySelector('.slider-inner');
let itemCount = slider.children.length;
// 计算horizontal区域的高度:(item数量-1)*视口高度
let horizontalHeight = (itemCount - 1) * window.innerHeight;
document.querySelector(".horizontal").style.height = `${horizontalHeight}px`;

function animate() {
  let y = window.scrollY;
  // 限制y的最大值不超过horizontal区域的高度,避免过度滚动
  let clampedY = Math.min(y, horizontalHeight);
  // 计算水平移动距离:- (滚动距离 * 视口宽度 / 视口高度)
  let translateX = - (clampedY * window.innerWidth / window.innerHeight);
  slider.style.transform = `translateX(${translateX}px)`;
  requestAnimationFrame(animate);
}
animate();

// 监听窗口大小变化,重新计算高度和移动距离
window.addEventListener('resize', () => {
  horizontalHeight = (itemCount - 1) * window.innerHeight;
  document.querySelector(".horizontal").style.height = `${horizontalHeight}px`;
});

CSS

/* 重置默认边距 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.horizontal{
  position: relative;
  width: 100vw;
  /* 高度由JS动态计算 */
}
.slider-container{
  position: sticky;
  top: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.slider-inner{
  display: flex;
  /* 总宽度由item数量自动决定,不需要硬写200vw */
  width: fit-content;
}
.item{
  width: 100vw;
  height: 100vh;
  background-color: red;
  border: solid 1px black;
}
.vertical{
  width: 100vw;
  height: 100vh;
  background-color: aqua;
}

HTML

<div class="horizontal">
  <div class="slider-container">
    <div class="slider-inner">
      <div class="item"></div>
      <div class="item"></div>
    </div>
  </div>
</div>
<div class="vertical"></div>

关键优化点

  • 用fit-content让.slider-inner的宽度自动适配item数量,不用手动写固定值
  • 添加了窗口resize监听,保证窗口大小变化时效果依然正确
  • 用Math.min限制滚动距离,避免horizontal滚动完成后继续触发不必要的水平移动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:57:49