GSAP+ScrollTrigger实现滚动到指定模块固定后滚动鼠标滑动元素

Web前端开发 / 10 次阅读

浏览器窗口向下向上滚动到指定模块后,模块固定,滚动鼠标实现该模块内的元素上下滑动。实现原理,在模块内添加一个固定显示元素和一个滑动元素,窗口滚动到它们的父元素时,一个元素固定显示,另一个元素通过滚动鼠标上下滑动。

gsap_scrollTrigger_mouse_scrolltop_01.jpg

HTML代码:

PS:GSAP自行下载。

<!--gsap-->
<script src="../js/gsap/gsap.min.js"></script>
<script src="../js/gsap/ScrollSmoother.min.js"></script> <!--可选,更加流畅,不然会有卡顿-->
<script src="../js/gsap/ScrollTrigger.min.js"></script>
<div id="main-wrapper">
    <div id="main-content">
        <section id="main-section">
            <div class="bgimg wap" style="background-color:#000;"></div> <!--为了做响应式-->
            <div class="pic-cont">
                <div class="bgimg pc" style="background-color:#000;"></div> <!--为了做响应式-->
                <div class="inner">
                    <div class="text">
                        <h2 class="name">关于我们</h2>
                        <div class="intro">资源分享,掏点东西<br/>大杂烩储存的个人站点!</div> 
                    </div>
                </div>
            </div>
            <div class="scroll-wrap">
                <div class="inner">
                    <div class="wrap">
                        <article class="item">
                            <div class="box">
                                <a class="info" href="">
                                    内容
                                </a>
                            </div>
                        </article>
                        <article class="item">
                            <div class="box">
                                <a class="info" href="">
                                    内容
                                </a>
                            </div>
                        </article>
                        <article class="item">
                            <div class="box">
                                <a class="info" href="">
                                    内容
                                </a>
                            </div>
                        </article>
                        <article class="item">
                            <div class="box">
                                <a class="info" href="">
                                    内容
                                </a>
                            </div>
                        </article>
                        <article class="item">
                            <div class="box">
                                <a class="info" href="">
                                    内容
                                </a>
                            </div>
                        </article>
                    </div>
                </div>
            </div>
        </section>
    </div>
</div>

CSS代码:

#main-section {
    position: relative;
    overflow: hidden;    
    .bgimg,
    .pic-cont {        
        position: absolute;
        left:0;
        top:0;
        width: 100%;
        height: 100%;
    }
    .wap {
        display: none;
    }
    .pic-cont {
        height: 100vh;
        display:flex;
        align-items: center;
    }
    .text {
        width:(720/1600*100%);
        color:#fff;
        display:flex;
        flex-direction:column;
        justify-content:center;
    }
    .intro {
        margin-top: 0.31rem;
    }
    .scroll-wrap {
        overflow: hidden;
        padding:1.9rem 0 1.2rem;
        height: max-content;   
        .inner {
            display:flex;
            justify-content:flex-end;
        }        
    }
    .wrap {
        width: 50%;
    }
    .item {
        display:flex;
        flex-wrap:wrap;
        &:nth-child(2n){
            justify-content: flex-end
        }
        &:nth-child(n+2){
            .box {
                margin-top:(-190/800*100%);
            }
        }
    }
    .box {
        width:(360/800*100%);
        position: relative;        
        &:after {
            padding:(460/360*100%);
            display: block;
            content: '';
        }
    }
    .info {        
        position: absolute;
        left:0;
        top:0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        padding:0.22rem 0.3rem;
        color:#222;
        &:before {
            position:absolute;
            left:0;
            top:0;
            display:block;
            content:'';
            width: 100%;
            height: 100%;
            background-color: #fff;
            transition: inherit;
        }
        &:hover {
            &:before {
                background-color: rgba(255,255,255,0.4);
                backdrop-filter: blur(0.1rem);
            }
        }
    }
}
@media only screen and (max-width:1024px) {
    #main-section {
        padding:1.2rem 0;
        .pc {
            display: none;
        }
        .wap {
            display: block;
        }
        .pic-cont {
            position: static;
            height: auto;
            margin-bottom: 0.65rem;
        }
        .text,
        .wrap {
            width: 100%;
        }
        .scroll-wrap {
            padding:0;
        }
        .box {
            &:after {
                padding-bottom: 75%;
            }
        }
        .item {
            &:nth-child(n+2){
                .box {
                    margin-top: -12%;
                }
            }
        }
    }
}
@media only screen and (max-width:750px) {
    #main-section {
        padding:0.8rem 0;
        .box {
            width: 100%;
        }
        .item {
            margin-bottom: 0.5rem;
            &:last-child {
                margin-bottom: 0;
            }
            &:nth-child(n+2){
                .box {
                    margin-top:0;
                }
            }
        }
    }
}

JS代码:

/**/
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
const smoother = ScrollSmoother.create({
    smooth: 2,
    effects: true,
    smoothTouch: 0.1,
    wrapper:'#main-wrapper',
    content:'#main-content',    
});
const listContainer = document.querySelector('.scroll-wrap');
const listHeight = listContainer.scrollHeight;
const viewportHeight = window.innerHeight;
const scrollDistance = listHeight - viewportHeight;
const lt = ScrollTrigger.create({
    trigger: `#main-section .pic-cont`,
    start: `top top`,
    end: `+=${scrollDistance}`,
    pin: true, //固定
    pinSpacing: false,
    markers: false,
    scrub: 1, //固定
    anticipatePin: 1
});

提示:end位置是滚动元素的高度。