使用GSAP实现可变高度分屏滚动,回滚功能异常求助
分屏滚动向上回滚异常问题排查与修复
问题背景
我使用GSAP的gsap.to实现类FullPage的分屏滚动网站,大部分section默认高度与屏幕一致,但存在部分section(如示例中的section_4)内容高度超过屏幕的情况。目前向下滚动到高内容区域功能正常,但向上回滚时出现异常,无法正常切换到上一个section。
核心修复代码
const sections = $("section"); const sectionContents = $("section > div"); let currentSectionIndex = 0; let isScrolling = false; let isTouching = false; $(document).on("wheel", handleWheel); $(document).on("touchstart", handleTouchStart); $(document).on("touchmove", handleTouchMove); $(document).on("touchend", handleTouchEnd); let touchStartY = 0; let touchStartTime = 0; function handleTouchStart(event) { console.log('handleTouchStart - is on'); isTouching = true; touchStartY = event.originalEvent.touches[0].clientY; touchStartTime = Date.now(); } function handleTouchMove(event) { console.log('handleTouchMove - is on'); if (!isTouching) return; event.preventDefault(); } function handleTouchEnd(event) { console.log('handleTouchEnd - is on'); isTouching = false; const touchEndY = event.originalEvent.changedTouches[0].clientY; const touchEndTime = Date.now(); const deltaY = touchEndY - touchStartY; const deltaTime = touchEndTime - touchStartTime; const velocity = Math.abs(deltaY / deltaTime); const direction = deltaY > 0 ? "down" : "up"; // 新增触摸方向判断 const currentSection = sections.eq(currentSectionIndex); const contentHeight = currentSection.find("> div").prop("scrollHeight"); const windowHeight = $(window).height(); if (contentHeight > windowHeight) { scrollInSection(currentSection, deltaY, direction); // 传入方向参数 } else { if (velocity > 1) { scrollInSection(currentSection, deltaY, direction); } else { scrollToSection(currentSection); } } } function handleWheel(event) { event.preventDefault(); if (isScrolling) return; isScrolling = true; const deltaY = event.originalEvent.deltaY; const direction = deltaY > 0 ? "down" : "up"; const targetSection = sections.eq(currentSectionIndex); if (targetSection.hasClass("large-content")) { scrollInSection(targetSection ,deltaY, direction); } else { if (direction === "down") { currentSectionIndex = Math.min(currentSectionIndex + 1, sections.length - 1); } else { currentSectionIndex = Math.max(currentSectionIndex - 1, 0); } scrollToSection(sections.eq(currentSectionIndex)); } } function scrollInSection(targetSection, deltaY, direction) { console.log('scrollInSection - to ' + targetSection.attr('class')); const windowHeight = $(window).height(); const sectionContent = targetSection.find("> div"); const currentScrollTop = sectionContent.scrollTop(); const sectionHeight = sectionContent.prop("scrollHeight"); const sectionVisibleHeight = windowHeight / 3; let targetScrollTop; const isAtTop = currentScrollTop === 0; const isAtBottom = currentScrollTop + windowHeight === sectionHeight; // 修复:边界滚动时切换对应section if (isAtTop && deltaY < 0 && direction === "up") { currentSectionIndex = Math.max(currentSectionIndex - 1, 0); scrollToSection(sections.eq(currentSectionIndex)); return; } if (isAtBottom && deltaY > 0 && direction === "down") { currentSectionIndex = Math.min(currentSectionIndex + 1, sections.length - 1); scrollToSection(sections.eq(currentSectionIndex)); return; } if (deltaY > 0) { targetScrollTop = Math.min(currentScrollTop + sectionVisibleHeight, sectionHeight - windowHeight); } else { targetScrollTop = Math.max(currentScrollTop - sectionVisibleHeight, 0); } // 统一用GSAP实现内容滚动,保持动画逻辑一致 gsap.to(sectionContent, { scrollTop: targetScrollTop, duration: 0.5, onComplete: () => { isScrolling = false; } }); } function scrollToSection(targetSection) { console.log('scrollToSection to ' + targetSection.attr('class'), targetSection.height(), $(window).height()); const targetY = targetSection.offset().top; gsap.to(window, { duration: 1.7, scrollTo: { y: targetY }, onComplete: function() { isScrolling = false; } }); }
错误分析与修复说明
缺失边界滚动的section切换逻辑
原代码中,当高内容section滚到顶部且向上滚动时,仅重置isScrolling后返回,未执行切换到上一个section的操作,导致无法向上回滚。修复时在对应条件分支中更新currentSectionIndex并调用scrollToSection完成切换。触摸事件未传递方向参数
handleTouchEnd中调用scrollInSection时未传入direction参数,导致触摸操作下的边界滚动判断失效。新增方向计算并传入参数即可解决该问题。动画库混用优化(可选)
原代码同时使用jQuery的animate和GSAP动画,统一为GSAP实现内容区域滚动,可保持动画逻辑一致并利用GSAP的性能优势。
内容的提问来源于stack exchange,提问作者Jc Denton
相关产品推荐
相关产品推荐

