f-navbar.vue 9.27 KB
<template>
	<view class="f-navbar">
		<view
			:class="[navbarType == 1 ? 'f-relative' : 'f-fixed']"
			:style="[navbarType == 1 ? { height: systemInfo.navBarH + 'px' } : { paddingTop: systemInfo.statusBarHeight + 'px' }]"
		>
			<!-- 背景色 -->
			<view class="bgColor" :style="{ height: systemInfo.navBarH + 'px', background: bgColor, backgroundImage: gradient, opacity: navbarType == 5 ? transparentValue : '' }">
				<image :src="image" :mode="imageMode" style="width: 750rpx;" :style="{ height: systemInfo.navBarH + 'px' }" v-if="image"></image>
			</view>
			<view class="u-flex content" :style="{ height: systemInfo.titleBarHeight + 'px', top: systemInfo.statusBarHeight + 'px' }">
				<block v-if="navbarType != 4 && isShowLeft">
					<view class="u-flex left" hover-class="left--hover" hover-start-time="150" v-if="navbarType == 3">
						<view class="u-flex u-home-arrow-left" :style="{ borderColor: isWhite ? 'rgba(255,255,255,.5)' : '#dadbde' }">
							<view @click="onBack"><u-icon name="arrow-left" size="19" :color="leftColor"></u-icon></view>
							<u-line direction="column" :hairline="false" length="16" margin="0 8px" :color="isWhite ? 'rgba(255,255,255,.3)' : '#dadbde'"></u-line>
							<view @click="onHome"><u-icon name="home" size="20" :color="leftColor"></u-icon></view>
						</view>
					</view>
					<view class="u-flex left" hover-class="left--hover" hover-start-time="150" @click="leftClick" v-else>
						<slot name="left">
							<!-- 左边箭头背景渐变 -->
							<view
								class="iconBg u-flex"
								:style="{ background: 'rgba(0,0,0,' + (navbarType == 5 ? (1 - transparentValue > 0.4 ? 0.4 : 1 - transparentValue) : 0) + ')' }"
							>
								<u-icon :name="iconLeft" size="16" :color="leftColor"></u-icon>
							</view>
							<text v-if="leftText" class="left__text" :style="{ color: leftColor }">{{ leftText }}</text>
						</slot>
					</view>
				</block>
				<view class="center" :style="{ width: titleWidth + 'rpx' }">
					<slot name="default">
						<view
							class="title u-line-1"
							:style="[
								isShowTransparentTitle ? {} : { opacity: navbarType == 5 ? transparentValue : '' },
								{ color: fontColor, width: titleWidth + 'rpx', fontSize: fontSize + 'rpx' }
							]"
						>
							{{ title }}
						</view>
					</slot>
				</view>
				<view class="u-flex right" @click="rightClick"><slot name="right"></slot></view>
			</view>
		</view>
		<!-- 防止塌陷高度 -->
		<view v-if="isFillHeight && navbarType != 5 && navbarType != 1" :style="{ height: systemInfo.navBarH + 'px' }"></view>
	</view>
</template>

<script>
// 主页页面的页面路径
// 关联功能:打开的页面只有一个的时候右上角自动显示返回首页按钮,下面这个数组是排除显示返回首页的页面。
// 主页使用场景:小程序分享出去的页面,用户点击开是分享页面,很多情况下是没有返回首页按钮的
const mainPagePath = ['pages/index/index', 'pages/device/device', 'pages/alarm/alarm', 'pages/personal/personal'];
//返回首页的地址
const homePath = '/pages/index/index';
//白色表达值
const whiteList = ['#FFF', '#fff', '#FFFFFF', '#ffffff', 'white', 'rgb(255,255,255)', 'rgba(255,255,255,1)'];
// import base from '@/config/baseUrl.js';
export default {
	name: 'f-navbar',
	props: {
		title: {
			type: String
		},
		// navbarType等于5透明背景时title是否显示
		isShowTransparentTitle: {
			type: Boolean,
			default: function() {
				return true;
			}
		},
		// 左边文字
		leftText: {
			type: String
		},
		// 背景颜色
		bgColor: {
			type: String,
			default: '#fff'
		},
		// 背景图片
		image: {
			type: String
		},
		// 背景图片mode
		imageMode: {
			type: String,
			default: 'aspectFill'
		},
		// 导航状态 0、默认固定在顶部 1、不固定在顶部 2、自定义点击事件 3、同时显示箭头和去首页按钮 4、不显示左侧内容 5、上拉渐变显示背景色
		navbarType: {
			type: [String, Number],
			default: 0
		},
		// 是否显示左侧内容
		isShowLeft: {
			type: Boolean,
			default: function() {
				return true;
			}
		},
		// 左边按钮icon
		leftIcon: {
			type: String,
			default: 'arrow-left'
		},
		// 左边icon颜色
		leftIconColor: {
			type: String,
			default: '#303133'
		},
		// 屏幕滑动距离顶部距离(透明固定导航比传)
		scrollTop: {
			type: Number,
			default: 0
		},
		//导航字体颜色,字体颜色为白色的时候会把手机状态栏设置为白色,否则为黑色
		fontColor: {
			type: String,
			default: '#303133'
		},
		titleWidth: {
			type: [String, Number],
			default: 400
		},
		fontSize: {
			type: [String, Number],
			default: 30
		},
		gradient: {
			type: String
		},
		// 是否设置防止塌陷高度
		isFillHeight: {
			type: Boolean,
			default: function() {
				return true;
			}
		}
	},
	data() {
		return {
			// systemInfo:base.systemInfo,
			systemInfo: {
				statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
				// #ifdef MP-ALIPAY
				navBarH: uni.getSystemInfoSync().statusBarHeight + uni.getSystemInfoSync().titleBarHeight, //菜单栏总高度--单位px
				titleBarHeight: uni.getSystemInfoSync().titleBarHeight, //标题栏高度--单位px
				// #endif
				// #ifndef MP-ALIPAY
				navBarH: uni.getSystemInfoSync().statusBarHeight + 35, //菜单栏总高度--单位px
				titleBarHeight: 35 //标题栏高度--单位px
				// #endif
			},
			//当前页面是否是第一个页面
			firstPage: false,
			//透明度值
			transparentValue: 0,
			iconLeft: 'arrow-left', //左边icon
			// 上次显示的导航栏颜色
			lastFrontColor: '',
			//字体色
			navFontColor: '#303133',
			isWhite: false //是否白色
		};
	},
	watch: {
		leftIcon: {
			immediate: true,
			handler(val) {
				this.iconLeft = val;
			}
		},
		fontColor: {
			immediate: true,
			handler(val) {
				this.navFontColor = val;
				this.settingColor();
			}
		},
		navbarType: {
			immediate: true,
			handler(val) {
				console.log(val, 'navbarType');
				if (val == 5) {
					if (this.scrollTop > 180) {
						this.transparentValue = 1;
					} else {
						this.transparentValue = this.scrollTop / 180;
					}
				}
			}
		},
		scrollTop(val) {
			this.pageScroll({
				scrollTop: val
			});
		}
	},
	computed: {
		leftColor() {
			let color = '#303133';
			if (this.leftIconColor == '#303133') {
				//如果等于默认值
				// 背景不是白色或者背景是渐变色
				if (!whiteList.includes(this.bgColor) || this.gradient) {
					color = '#fff';
				}
			} else {
				color = this.leftIconColor;
			}
			return color;
		}
	},
	created() {
		this.pageScroll({
			scrollTop: this.scrollTop
		});
		//获取所有页面
		let currentPages = getCurrentPages();
		let pageLen = currentPages.length;
		//判断是否是第一个页面,如果是有设置back为true的页面,将不显示返回箭头,而显示返回首页按钮
		if (pageLen == 1 && !mainPagePath.includes(currentPages[0].route)) {
			this.firstPage = true;
			this.iconLeft = 'home';
		}
	},
	methods: {
		onBack() {
			if (this.firstPage) {
				uni.reLaunch({
					url: homePath
				});
			} else {
				uni.navigateBack();
			}
		},
		onHome() {
			uni.switchTab({
				url: homePath
			});
		},
		leftClick() {
			if (this.navbarType == 2) {
				this.$emit('leftClick');
			} else {
				this.onBack();
			}
		},
		rightClick() {
			this.$emit('rightClick');
		},
		pageScroll(e) {
			if (this.navbarType == 5) {
				if (e.scrollTop && e.scrollTop > 0) {
					if (e.scrollTop > 180) {
						this.transparentValue = 1;
					} else {
						this.transparentValue = e.scrollTop / 180;
					}
				} else {
					this.transparentValue = 0;
				}
				// this.settingColor();
			}
		},
		//设置手机状态栏颜色
		settingColor() {
			let navColor = this.navFontColor;
			let frontColor = '#000000';
			if (whiteList.includes(navColor)) {
				frontColor = '#ffffff';
				this.isWhite = true;
			}
			if (this.lastFrontColor == frontColor) {
				return;
			}
			setTimeout(() => {
				this.lastFrontColor = frontColor;
				// 改变手机状态栏颜色
				// #ifndef MP-ALIPAY
				uni.setNavigationBarColor({
					frontColor: frontColor,
					backgroundColor: '#FFFFFF'
				});
				// #endif
				// #ifdef MP-ALIPAY
				uni.setNavigationBarColor({
					backgroundColor: frontColor == '#000000' ? '#ffffff' : '#000000'
				});
				// #endif
			}, 150);
		}
	}
};
</script>

<style scoped lang="scss">
.u-flex {
	/* #ifndef APP-NVUE */
	display: flex;
	/* #endif */
	flex-direction: row;
	align-items: center;
}

.f-navbar {
	width: 750rpx;

	.f-fixed {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		z-index: 1000;
	}

	.f-relative {
		position: relative;
	}

	.bgColor {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
	}

	.content {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
	}

	.title {
		text-align: center;
		color: #303133;
	}

	.center {
		margin: 0 auto;
	}

	.left,
	.right {
		padding: 0 24rpx;
		position: absolute;
		top: 0;
		bottom: 0;
	}

	.left {
		left: 0;

		&--hover {
			opacity: 0.7;
		}

		&__text {
			font-size: 30rpx;
			margin-left: 3px;
		}

		.iconBg {
			width: 50rpx;
			height: 50rpx;
			background: rgba(0, 0, 0, 0.4);
			border-radius: 25rpx;
			justify-content: center;
		}
	}

	.right {
		right: 0;
	}

	.u-home-arrow-left {
		justify-content: space-between;
		border-radius: 100px;
		padding: 3px 7px;
		opacity: 0.8;
		border: 0.5px solid #dadbde;
	}
}
</style>