
本文讲解如何通过监听鼠标滚轮事件,将用户垂直方向的滚动操作映射为页面水平滚动,从而在保持常规交互习惯的同时实现横向内容浏览。
本文讲解如何通过监听鼠标滚轮事件,将用户垂直方向的滚动操作映射为页面水平滚动,从而在保持常规交互习惯的同时实现横向内容浏览。
在响应式网页中,有时需要突破浏览器默认的“垂直滚动 = 垂直位移”逻辑,实现「用户向上/下滑动,页面却向左/右平移」的效果——这在全屏横向画廊、时间轴展示或创意型单页布局中非常实用。核心原理是:拦截原生滚动行为,将其 delta 值重新定向到水平轴。
你当前代码中的关键问题在于 window.scrollBy(evt.deltaY, 0) —— 这实际是让页面沿 Y 轴(垂直方向)移动,与目标相悖。正确做法是交换参数顺序,将滚轮的垂直偏移量(evt.deltaY)应用于 X 轴:
const scrollContainer = document.querySelector(".sp");
scrollContainer.addEventListener("wheel", (evt) => {
evt.preventDefault(); // 阻止默认垂直滚动
window.scrollBy(evt.deltaY, 0); // ❌ 错误:仍触发垂直滚动
});
✅ 应改为:
scrollContainer.addEventListener("wheel", (evt) => {
evt.preventDefault();
window.scrollBy(evt.deltaY, 0); // ⚠️ 注意:此处看似未改?实则需结合 CSS 方向理解
});
但更准确、更健壮的写法是 显式控制水平滚动,尤其当页面存在复杂嵌套或 overflow-x: hidden 时:
scrollContainer.addEventListener("wheel", (evt) => {
evt.preventDefault();
// 将垂直滚轮位移映射为水平滚动(正向滑动向下 → 向右滚动)
const scrollAmount = evt.deltaY;
scrollContainer.scrollLeft += scrollAmount;
});
✅ 推荐此方式:直接操作
scrollLeft,避免全局window.scrollBy可能引发的布局重排冲突,且精准作用于目标容器。
此外,关于你提到的「canvas 3 后出现大片空白」问题,根源极可能在于:
-
.sp容器宽度计算误差(如totalWidth - 2500中的硬编码-2500缺乏自适应性); - 子元素
.sb的margin-right: -4px或inline-block间隙导致总宽塌陷; -
height: 100vh在移动端或缩放下引发高度溢出,间接影响scrollWidth计算。
优化建议:
- 移除硬编码宽度减法,改用
scrollContainer.scrollWidth = [...document.querySelectorAll('.sb')].reduce((sum, el) => sum + el.offsetWidth, 0); - 使用
display: flex替代inline-block,彻底消除间隙; - 添加防抖机制避免高频滚动卡顿:
let isScrolling = false; scrollContainer.addEventListener("wheel", (evt) => { if (isScrolling) return; isScrolling = true; evt.preventDefault(); scrollContainer.scrollLeft += evt.deltaY; setTimeout(() => isScrolling = false, 16); // 约 60fps 限制 });
最后,请确保 和 的 overflow-x: hidden 已正确设置(你已在 JS 中设置 document.documentElement.style.overflowX = 'hidden'),并配合 CSS scroll-behavior: smooth 提升体验:
.sp {
scroll-behavior: smooth;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch; /* iOS 平滑滚动支持 */
}
这样,用户只需自然上下滑动,即可流畅浏览横向内容,同时空白区域问题也将随布局规范化一并解决。










