小程序-二級(jí)導(dǎo)航吸頂效果

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>

        <!-- 篩選條件:累計(jì)直推獎(jiǎng)勵(lì)、上月直推獎(jiǎng)勵(lì)、本月直推獎(jiǎng)勵(lì) -->
        <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 的高度,用于設(shè)置 filter-tabs-sticky 的 top 值
            stickyContainerHeight: 0, // 默認(rèn)值 0rpx
            // filter-tabs-sticky 距離頂部的距離(rpx)
            filterTabsStickyTop: 0,
            // 是否隱藏導(dǎo)航(向上移動(dòng))
            isNavHidden: false,
            // 上次滾動(dòng)位置,用于判斷滾動(dòng)方向
            lastScrollTop: 0
onReady() {
    this.$nextTick(() => {
        this.updateFilterTabsStickyPosition()
    })
},
onPageScroll(e) {
    this.handlePageScroll(e.scrollTop || 0)
},

methods

        // 查詢?cè)爻叽缧畔?        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 時(shí),頁(yè)面應(yīng)該還沒(méi)有滾動(dòng),所以 top 就是相對(duì)于頁(yè)面頂部的位置
            const filterTabsRect = await this.queryRect('.filter-tabs-sticky')
            if (filterTabsRect && filterTabsRect.top !== undefined) {
                // top 是相對(duì)于視口的位置,在初始狀態(tài)下(scrollTop = 0)就是相對(duì)于頁(yè)面頂部的位置
                this.filterTabsStickyTop = filterTabsRect.top * pxToRpxRatio
            }
        },
        // 處理頁(yè)面滾動(dòng)
        handlePageScroll(scrollTop) {
            if (!this.stickyContainerHeight || !this.filterTabsStickyTop) return
            
            // 將 scrollTop (px) 轉(zhuǎn)換為 rpx
            const systemInfo = uni.getSystemInfoSync()
            const pxToRpxRatio = 750 / systemInfo.windowWidth
            const scrollTopRpx = scrollTop * pxToRpxRatio
            
            // 計(jì)算滾動(dòng)閾值:filter-tabs-sticky 距離頂部的距離 - stickyContainerHeight
            const threshold = this.filterTabsStickyTop - this.stickyContainerHeight
            
            // 判斷滾動(dòng)方向
            const isScrollingUp = scrollTop > this.lastScrollTop
            const isScrollingDown = scrollTop < this.lastScrollTop
            
            // 更新上次滾動(dòng)位置
            this.lastScrollTop = scrollTop
            
            // 判斷是否需要隱藏導(dǎo)航
            if (scrollTopRpx >= threshold) {
                // 超過(guò)閾值,根據(jù)滾動(dòng)方向決定是否隱藏
                if (isScrollingUp) {
                    // 向上滾動(dòng),隱藏導(dǎo)航
                    this.isNavHidden = true
                } else if (isScrollingDown) {
                    // 向下滾動(dòng),顯示導(dǎo)航
                    this.isNavHidden = false
                }
                // 如果滾動(dòng)方向不變,保持當(dāng)前狀態(tài)
            } else {
                // 未超過(guò)閾值,顯示導(dǎo)航
                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;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容