小程序-二级导航吸顶效果

template

        <view class="sticky-container u-m-b-20" :class="{ 'sticky-container--hidden': isNavHidden }" :style="{ transform: isNavHidden ? `translateY(-${stickyContainerHeight}rpx)` : 'translateY(0)' }">
            <ld-custom-tabs
                class="shop-type-tabs"
                :list="shopTypeTabs"
                :current="activeShopTab"
                @change="handleShopTabChange"
            />
        </view>

        <!-- 筛选条件:累计直推奖励、上月直推奖励、本月直推奖励 -->
        <view class="filter-tabs-sticky" :class="{ 'filter-tabs-sticky--hidden': isNavHidden }" :style="{ top: stickyContainerHeight + 'rpx', transform: isNavHidden ? `translateY(-${stickyContainerHeight}rpx)` : 'translateY(0)' }">
            <ld-filter-tabs
                class="filter-tabs"
                :list="filterTabs"
                :current="activeFilterIndex"
                :item-style="{ backgroundColor: '#fff', border: '1rpx solid #e5e5e5' }"
                @change="handleFilterChange"
                @reclick="handleFilterReclick"
            />
        </view>

data

            loading: false,
            // sticky-container 的高度,用于设置 filter-tabs-sticky 的 top 值
            stickyContainerHeight: 0, // 默认值 0rpx
            // filter-tabs-sticky 距离顶部的距离(rpx)
            filterTabsStickyTop: 0,
            // 是否隐藏导航(向上移动)
            isNavHidden: false,
            // 上次滚动位置,用于判断滚动方向
            lastScrollTop: 0
onReady() {
    this.$nextTick(() => {
        this.updateFilterTabsStickyPosition()
    })
},
onPageScroll(e) {
    this.handlePageScroll(e.scrollTop || 0)
},

methods

        // 查询元素尺寸信息
        queryRect(selector) {
            return new Promise(resolve => {
                uni.createSelectorQuery()
                    .in(this)
                    .select(selector)
                    .boundingClientRect(rect => {
                        resolve(rect)
                    })
                    .exec()
            })
        },
        // 更新 filter-tabs-sticky 的 top 值
        async updateFilterTabsStickyPosition() {
            const systemInfo = uni.getSystemInfoSync()
            const pxToRpxRatio = 750 / systemInfo.windowWidth
            
            // 获取 sticky-container 的高度
            const stickyRect = await this.queryRect('.sticky-container')
            if (stickyRect && stickyRect.height) {
                this.stickyContainerHeight = stickyRect.height * pxToRpxRatio
            }
            
            // 获取 filter-tabs-sticky 距离顶部的距离
            // 在 onReady 时,页面应该还没有滚动,所以 top 就是相对于页面顶部的位置
            const filterTabsRect = await this.queryRect('.filter-tabs-sticky')
            if (filterTabsRect && filterTabsRect.top !== undefined) {
                // top 是相对于视口的位置,在初始状态下(scrollTop = 0)就是相对于页面顶部的位置
                this.filterTabsStickyTop = filterTabsRect.top * pxToRpxRatio
            }
        },
        // 处理页面滚动
        handlePageScroll(scrollTop) {
            if (!this.stickyContainerHeight || !this.filterTabsStickyTop) return
            
            // 将 scrollTop (px) 转换为 rpx
            const systemInfo = uni.getSystemInfoSync()
            const pxToRpxRatio = 750 / systemInfo.windowWidth
            const scrollTopRpx = scrollTop * pxToRpxRatio
            
            // 计算滚动阈值:filter-tabs-sticky 距离顶部的距离 - stickyContainerHeight
            const threshold = this.filterTabsStickyTop - this.stickyContainerHeight
            
            // 判断滚动方向
            const isScrollingUp = scrollTop > this.lastScrollTop
            const isScrollingDown = scrollTop < this.lastScrollTop
            
            // 更新上次滚动位置
            this.lastScrollTop = scrollTop
            
            // 判断是否需要隐藏导航
            if (scrollTopRpx >= threshold) {
                // 超过阈值,根据滚动方向决定是否隐藏
                if (isScrollingUp) {
                    // 向上滚动,隐藏导航
                    this.isNavHidden = true
                } else if (isScrollingDown) {
                    // 向下滚动,显示导航
                    this.isNavHidden = false
                }
                // 如果滚动方向不变,保持当前状态
            } else {
                // 未超过阈值,显示导航
                this.isNavHidden = false
            }
        }
    },

css

.sticky-container {
    position: sticky;
    top: 0;
    left: 0;
    right: 0;
    z-index: 10;
    background-color: #f5f6fa;
    padding: 12rpx 0;
    margin: 0 -24rpx 16rpx;
    transition: transform 0.3s ease-out;
}
.filter-tabs-sticky {
    position: sticky;
    left: 0;
    z-index: 9;
    background-color: #f5f6fa;
    padding: 12rpx 0;
    margin: 0 -24rpx 16rpx;
    transition: transform 0.3s ease-out;
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容