在UniApp中实现滚动时导航栏渐显固定效果

发布于:2025-06-19 ⋅ 阅读:(21) ⋅ 点赞:(0)

由于有时候UI出图很丰富,根本没有固定的导航栏,但是又要实现滚动页面有固定导航栏,还是渐渐显示的效果

<template>
  <view>
    <!-- 自定义导航栏 -->
    <view class="custom-navbar" :style="{opacity: navbarOpacity, position: navbarFixed ? 'fixed' : 'absolute', background: `rgba(255,255,255,${navbarOpacity})`}">
      <!-- 导航栏内容 -->
      <text>我的导航栏</text>
    </view>
    
    <!-- 页面内容 -->
    <view class="content" @scroll="handleScroll" :style="{paddingTop: navbarHeight + 'px'}">
      <!-- 页面内容 -->
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      navbarOpacity: 0, // 透明度
      navbarFixed: false, // 是否固定
      navbarHeight: 44, // 导航栏高度,根据实际调整
      scrollTop: 0 // 滚动位置
    }
  },
  methods: {
    handleScroll(e) {
      // 获取滚动位置(H5和微信小程序获取方式不同)
      let scrollTop = 0;
      // #ifdef H5
      scrollTop = e.target.scrollTop;
      // #endif
      // #ifdef MP-WEIXIN
      scrollTop = e.detail.scrollTop;
      // #endif
      
      this.scrollTop = scrollTop;
      
      // 计算透明度,根据滚动距离变化
      const opacity = Math.min(scrollTop / 100, 1);
      this.navbarOpacity = opacity;
      
      // 超过一定距离后固定导航栏
      this.navbarFixed = scrollTop > 50;
    }
  }
}
</script>

<style>
.custom-navbar {
  top: 0;
  left: 0;
  right: 0;
  height: 44px; /* 根据实际调整 */
  display: flex;
  align-items: center;
  padding: 0 15px;
  z-index: 999;
  transition: all 0.3s ease;
}

.content {
  height: 100vh;
  overflow-y: auto;
  box-sizing: border-box;
}
</style>

方案二:使用页面生命周期和onPageScroll 

export default {
  data() {
    return {
      navbarOpacity: 0
    }
  },
  onPageScroll(e) {
    const scrollTop = e.scrollTop;
    this.navbarOpacity = Math.min(scrollTop / 100, 1);
  }
}

之前我还手搓了一个,实现原理是写了2个header,固定的header开始是透明的,根据滚动使opacity为1,背景颜色也通过滚动实现

<template>
	<view>
		<view style="position: fixed;left: 0;top: 0;width: 100%;z-index: 1111;"
			:style="{ opacity: navbarOpacity,backgroundColor: navBarColor }">
			<!-- <view style="height: 30rpx;"></view> -->
			<view :style="{height:statusBarHeight+'px'}"></view>
			<view style="height: 82rpx;" class="base-flex-between">
				<view class="flex-center" style="width: 20%;">
					<view class="flex-center" style="padding: 0 22rpx 0 30rpx;height: 82rpx;" @click="onBack">
						<image style="width: 19rpx;height: 33rpx;" src="/static/home/left.png"></image>
					</view>

				</view>
				<view style="width: 60%;font-size: 36rpx;color: #1E2433;font-weight: 600;" class="flex-item-center">
					<!-- 理财宝 -->个人中心
				</view>
				<view style="width: 20%;"></view>
			</view>
		</view>
		<view class="headerWrap">
			<view class="status_bar"></view>
			<view class="d-flex a-center j-sb pr-3" style="height: 88rpx">
				<view @click="navBack" style="width: 62rpx;padding-left: 24rpx;">
					<image style="width: 20rpx;" src="/static/home/left.png" mode="widthFix"></image>
				</view>
				<u-icon name="share-square" color="#51b300" size="28"></u-icon>
			</view>
			<view class="px-3">
				<view class="wrapcneter">
					<image class="avatarImg" src="/static/test.jpg" mode=""></image>
					<view class="d-flex a-center j-center setimg">
						<u-icon name="edit-pen" color="#51b300" size="18"></u-icon>
					</view>
					<view class="font-16 font-600" style="margin-top: 120rpx;">用户昵称</view>

					<view class="d-flex a-center mt-2">
						<view class="btnwrap d-flex a-center">
							<text class="font-14 font-600 mr-1">15</text>
							<text style="color: #AFAFAF;font-size: 22rpx;">关注</text>
						</view>
						<view class="btnwrap d-flex a-center ml-2">
							<text class="font-14 font-600 mr-1">15234</text>
							<text style="color: #AFAFAF;font-size: 22rpx;">粉丝</text>
						</view>
					</view>
					<view class="text-two-line w-100 px-3 mt-3" style="font-size: 22rpx;">
						个人主页介绍个人主页介绍个人主页介绍个人主页介绍个人主页介绍个人主页介绍个人主页介绍个人主页介绍介绍个页个…
					</view>
				</view>
			</view>

		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {

				navBarColor: 'rgba(188, 237, 0,0)',
				navbarOpacity: 0, // 透明度
			}
		},
		onReady() {
			this.getTabItemWidth();
		},
		onPageScroll(e) {
			// 页面滚动时的处理
			let topHeight = 150;
			const opacity = 1 - (topHeight - e.scrollTop) / topHeight;
			// console.log(opacity,'opacity')
			this.navBarColor = `rgba(188, 237, 0,${opacity})`;
			let newTop = uni.upx2px(920);
			let newTop1 = uni.upx2px(1050);
			let opacity1 = e.scrollTop / newTop1;
			this.navbarOpacity = Math.min(e.scrollTop / 100, 1);
			if (e.scrollTop >= newTop) {
				if (opacity1 > 1) {
					opacity1 = 1;
				}
				this.navBarColorOne = `rgba(188, 237, 0,${opacity1})`;

			} else {
				this.navBarColorOne = 'rgba(188, 237, 0,0)';
			}

		},
		methods: {
			
		}
	}
</script>

<style lang="scss" scoped>
	.status_bar {
		height: var(--status-bar-height);
		// background-color: rgba(255, 255, 255, 0);
	}

	.headerWrap {
		background: url(@/static/assets/mybg.png);
		background-size: cover;
		width: 100%;

		// height: 698rpx;
	}

	.wrapcneter {
		margin-top: 100rpx;
		width: 690rpx;
		height: 364rpx;
		background: rgba(255, 255, 255, 0.51);
		border-radius: 40rpx;
		border: 2rpx solid #fff;
		position: relative;
		display: flex;
		flex-direction: column;
		align-items: center;
	}

	.avatarImg {
		width: 200rpx;
		height: 200rpx;
		border-radius: 50%;
		border: 4rpx solid #fff;
		position: absolute;
		top: -27%;
		z-index: 666;
	}

	.setimg {
		width: 40rpx;
		height: 40rpx;
		background-color: #fff;
		border-radius: 50%;
		position: absolute;
		top: 21%;
		z-index: 777;
	}

	.btnwrap {
		padding: 4rpx 20rpx;
		background: #E1FB7B;
		border-radius: 26rpx;
	}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到