如何实现带独立滚动的粘性元素及GSAP相关技术问题
问题描述
项目需求:页面加载后,初始窗口包含随滚动移动的对象;滚动至底部时该元素消失并显示页面开头。需使用GSAP实现动画效果与章节跳转。
存在两个核心问题:
- 窗口初始阶段无法平滑滚动,GSAP章节跳转导致滚动不均匀,仅需在第一个区块结束后生效,希望在第一个区块关闭后再初始化GSAP。
- 滚动时所有元素向下滚动,元素透明度降至0时显示页面中间而非开头,需修正此逻辑。
解决方案
问题1:延迟GSAP初始化,仅在首区块结束后生效
原逻辑中GSAP随页面加载直接初始化,干扰了初始滚动行为。我们可以监听首区块的完成状态(即html添加.movement-finished类的时机),再触发GSAP的ScrollTrigger初始化:
- 将GSAP的初始化逻辑封装为独立函数
initGSAP。 - 在首区块滚动完成的代码块中调用该函数,确保仅在初始滚动流程结束后启用GSAP章节跳转。
问题2:修正滚动至页面开头的逻辑
当前滚动到顶部的触发时机和执行逻辑存在偏差,需调整:
- 优化
scrollPercent的计算逻辑,确保触发滚动到顶部的时机更精准。 - 滚动到顶部前,先终止可能存在的GSAP滚动动画,避免冲突导致定位偏差。
修改后的完整代码
$(document).ready(function () { $(window).on("scroll", function () { var obj = $(".before-element"); var currY = $(window).scrollTop(); var postHeight = $(window).height(); var scrollHeight = obj.height(); var scrollPercent = 0; // 修正百分比计算,确保触发时机准确 scrollPercent = (currY / (scrollHeight - postHeight)) * 100; if (scrollPercent > 0 && scrollPercent < 100) $("div.moving-element").css("min-width", (scrollPercent + 30) + "%"); if (scrollPercent > 100 && !$("html").hasClass("movement-finished")) { $(".before-element").addClass("finished"); // 终止可能存在的GSAP滚动动画,避免干扰 if (window.scrollTween) { window.scrollTween.kill(); window.scrollTween = null; } $("html").scrollTop(0).addClass("movement-finished"); $("div.moving-element").css("min-width", "100%"); // 首区块完成后初始化GSAP initGSAP(); } }); }); function initGSAP() { gsap.registerPlugin(ScrollTrigger, ScrollToPlugin); let panels = gsap.utils.toArray(".panel"), observer = ScrollTrigger.normalizeScroll(true), scrollTween; document.addEventListener( "touchstart", (e) => { if (scrollTween) { e.preventDefault(); e.stopImmediatePropagation(); } }, { capture: true, passive: false } ); function goToSection(i) { scrollTween = gsap.to(window, { scrollTo: { y: i * innerHeight, autoKill: false }, duration: 2, onStart: () => { observer.disable(); observer.enable(); }, onComplete: () => (scrollTween = null), overwrite: true }); } panels.forEach((panel, i) => { ScrollTrigger.create({ trigger: panel, toggleClass: { targets: panel, className: "active" }, start: "top bottom", end: "+=199%", ease: "power1.inOut", onToggle: (self) => self.isActive && !scrollTween && goToSection(i) }); }); } // 保留桌面端媒体查询逻辑,不提前初始化GSAP let mm = gsap.matchMedia(); mm.add("(min-width: 768px)", () => { mm.revert(); });
内容的提问来源于stack exchange,提问作者Vigil
相关产品推荐
相关产品推荐

