You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

504 lines
12 KiB

<template>
<view class="niu-navbar">
<view class="niu-navbar__status" v-if="status" :style="{
position: toShow&&block?'':'relative',
backgroundColor: gradient?gradient:statusColor?statusColor:'',
height: x_statusHeight?(x_statusHeight+'px'):''
}"></view>
<view class="niu-navbar__block"
:style="{height: x_height?(x_height+'px'):'',paddingTop: x_statusHeight?(x_statusHeight+'px'):''}"
v-if="toShow&&toFixed&&block"></view>
<view class="niu-navbar__wrapper" v-if="toShow" :style="{
height: x_height?(x_height+'px'):'',
paddingTop: x_statusHeight?(x_statusHeight+'px'):'',
top: x_statusHeight?(0+'px'):'',
opacity:x_opacity,
backgroundImage: gradient?gradient:'',
backgroundColor: !gradient?bg:'transparent'
}" :class="[toFixed?'fixed':'',border?'border':'']">
<view v-if="!oneline" class="niu-navbar__left" @click="clickLeft"
:style="{color: color,height: x_height?(x_height+'px'):'',lineHeight: x_height?(x_height+'px'):'',top: x_statusHeight?(x_statusHeight+'px'):''}">
<slot name="left">
<!-- <i v-if="back" class="niu-navbar__icon iconfont icon-back_light"></i> -->
<image v-if="!firstPage&&back" class="niu-navbar__icon"
src="https://shidaizhu.oss-cn-shenzhen.aliyuncs.com/app_static/icons/icon3.png" mode=""></image>
<text v-if="!firstPage&&back&&leftText" class="niu-navbar__text">{{leftText}}</text>
</slot>
</view>
<!-- ,marginRight: adjust?(x_width+'px'):'' -->
<view v-if="!oneline" class="niu-navbar__middle"
:class="{center:middleLayout=='center',left:middleLayout=='left'}"
:style="{ color: color,top: x_statusHeight?(x_statusHeight+'px'):'',height: x_height?(x_height+'px'):'',lineHeight: x_height?(x_height+'px'):'' }">
<slot></slot>
</view>
<view v-if="!oneline" class="niu-navbar__right"
:style="{color: color,height: x_height?(x_height+'px'):'',lineHeight: x_height?(x_height+'px'):'',top: x_statusHeight?(x_statusHeight+'px'):'',marginRight: adjust?(x_width+'px'):''}">
<slot name="right"></slot>
</view>
<view v-if="oneline" class="niu-navbar__middle"
:class="{center:middleLayout=='center',left:middleLayout=='left'}"
:style="{ color: color,top: x_statusHeight?(x_statusHeight+'px'):'',height: x_height?(x_height+'px'):'',lineHeight: x_height?(x_height+'px'):'',marginRight: adjust?(x_width+'px'):'' }">
<slot></slot>
</view>
</view>
</view>
</template>
<script>
let mainPagePath = "pages/index/index"
const _throttle = function(fn, interval) {
var last;
var timer;
var interval = interval || 200;
return function() {
var th = this;
var args = arguments;
var now = +new Date();
if (last && now - last < interval) {
clearTimeout(timer);
timer = setTimeout(function() {
last = now;
fn.apply(th, args);
}, interval);
} else {
last = now;
fn.apply(th, args);
}
}
}
export default {
props: {
oneline: {
type: Boolean,
default: false
},
gradient: {
type: String,
default: ""
},
middleLayout: {
type: String,
default: "center"
},
adjust: {
type: Boolean,
default: false,
},
color: {
type: String,
default: "#000"
},
bg: {
type: String,
default: ""
},
border: {
type: Boolean,
default: true
},
leftText: {
type: String,
default: ""
},
back: {
type: Boolean,
default: true
},
status: {
type: Boolean,
default: true
},
statusColor: {
type: String,
default: ''
},
/**
* 是否显示
*/
show: {
type: Boolean,
default: true
},
/**
* 是否吸顶
*/
fixed: {
type: Boolean,
default: false
},
/**
* 是否强制吸顶
*/
forceFixed: {
type: Boolean,
default: false
},
/**
* 非强制吸顶+吸顶:偏移这么多之后吸顶
*/
offset: {
type: Number,
default: 0
},
/**
* 强制吸顶+吸顶:渐隐的距离
*/
opacityOffset: {
type: Number,
default: 400
},
/**
* 强制吸顶+吸顶+渐隐:
*/
offsetHideOpacity: {
type: Number,
default: 0
},
/**
* 强制吸顶+吸顶:是否渐隐
*/
offsetHide: {
type: Boolean,
default: false
},
/**
* 是否需要占位块
*/
block: {
type: Boolean,
default: true
},
},
beforeDestroy() {
// #ifdef H5
window.removeEventListener("scroll", this.scroll)
// #endif
},
created() {
// #ifdef MP
let statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
let menuButtonInfo = uni.getMenuButtonBoundingClientRect()
this.x_statusHeight = statusBarHeight
this.x_height = (menuButtonInfo.top - statusBarHeight) * 2 + menuButtonInfo.height;
this.x_width = menuButtonInfo.width + 10
// #endif
// #ifdef APP-PLUS
let statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
this.x_statusHeight = statusBarHeight
// #endif
},
mounted() {
let pages = getCurrentPages();
if (pages.length == 1 && mainPagePath.includes(pages[0].route)) {
this.firstPage = true;
}
this.$n.$obs.setTop(this.getNavbarHeight())
// #ifdef H5
window.addEventListener("scroll", this.scroll, false)
// #endif
// #ifndef H5
if (pages.length) {
let that = this;
let onPageScroll = pages[pages.length - 1].onPageScroll;
pages[pages.length - 1].onPageScroll = function(e) {
onPageScroll.call(this, e);
that.$emit('scroll', e);
that.scroll(e);
};
}
// #endif
},
computed: {
toFixed() {
return this.fixed && this.x_fixed
},
toShow() {
return this.show && this.x_show
}
},
data() {
return {
firstPage: false,
x_height: 0,
x_width: 0,
x_statusHeight: 0,
x_show: true,
x_fixed: this.fixed,
x_opacity: 1,
};
},
methods: {
statusBarHeight(isPx = false) {
let height = uni.getSystemInfoSync().statusBarHeight
return isPx ? height + 'px' : height;
},
getNavbarHeight(isPx = false) {
let height = uni.upx2px(88);
let statusBarHeight = this.statusBarHeight();
// #ifdef MP
let menuButtonInfo = uni.getMenuButtonBoundingClientRect()
height = (menuButtonInfo.top - statusBarHeight) * 2 + menuButtonInfo.height;
height = height + statusBarHeight;
// #endif
// #ifdef APP-PLUS
height = height + statusBarHeight;
// #endif
return isPx ? height + 'px' : height;
},
clickLeft(e) {
if (this.back) {
// #ifdef H5
history.back()
// #endif
// #ifndef H5
uni.navigateBack({
delta: 1
})
// #endif
}
this.$emit("clickLeft", e)
},
scroll(e) {
// #ifdef H5
let scrollTop = document.documentElement.scrollTop
// #endif
// #ifndef H5
let scrollTop = e.scrollTop;
// #endif
const navHeight = uni.upx2px(92);
if (!this.forceFixed) {
if (this.offset < navHeight) {
this.x_fixed = true;
} else {
if (navHeight <= (scrollTop - this.offset)) {
this.x_fixed = true;
} else {
this.x_fixed = false;
}
}
} else {
if (this.offsetHide && this.opacityOffset >= uni.upx2px(92) * 2) {
if (!this.x_show) {
scrollTop = scrollTop + navHeight + 20;
}
let opacity = ~~((this.opacityOffset - scrollTop) / this.opacityOffset * 1000);
opacity = opacity > 1000 ? 1000 : opacity;
opacity = opacity < this.offsetHideOpacity ? 0 : opacity;
this.x_opacity = opacity / 1000;
if (this.x_opacity <= 0) {
this.x_show = false
} else {
this.x_show = true
}
} else {
this.x_show = true
}
}
},
// scroll: _throttle(async function(e) {
// // #ifdef H5
// let scrollTop = document.documentElement.scrollTop
// // #endif
// // #ifndef H5
// let scrollTop = e.scrollTop;
// // #endif
// const navHeight = uni.upx2px(92);
// if (!this.forceFixed) {
// if (this.offset < navHeight) {
// this.x_fixed = true;
// } else {
// if (navHeight <= (scrollTop - this.offset)) {
// this.x_fixed = true;
// } else {
// this.x_fixed = false;
// }
// }
// } else {
// if (this.offsetHide && this.opacityOffset >= uni.upx2px(92) * 2) {
// if (!this.x_show) {
// scrollTop = scrollTop + navHeight + 20;
// }
// let opacity = ~~((this.opacityOffset - scrollTop) / this.opacityOffset * 1000);
// opacity = opacity > 1000 ? 1000 : opacity;
// opacity = opacity < this.offsetHideOpacity ? 0 : opacity;
// this.x_opacity = opacity / 1000;
// if (this.x_opacity <= 0) {
// this.x_show = false
// } else {
// this.x_show = true
// }
// } else {
// this.x_show = true
// }
// }
// }, 0)
}
}
</script>
<style lang="scss" scoped>
$name: niu-navbar;
$height: 88rpx;
// @mixin hairline {
// position: relative;
// &::after {
// position: absolute;
// box-sizing: border-box;
// content: " ";
// pointer-events: none;
// top: -50%;
// right: -50%;
// bottom: -50%;
// left: -50%;
// border: 0 solid #ebedf0;
// -webkit-transform: scale(0.5);
// transform: scale(0.5);
// @content
// }
// }
// @mixin hairline--bottom {
// @include hairline {
// border-bottom-width: 1px;
// }
// }
.niu-navbar {
position: relative;
z-index: 99;
box-sizing: content-box;
&__status {
box-sizing: content-box;
position: fixed;
top: 0;
left: 0;
right: 0;
height: var(--status-bar-height);
background-color: transparent;
z-index: 999;
}
&__block {
box-sizing: content-box;
// position: relative;
padding-top: var(--status-bar-height);
height: $height;
// background-color: red;
// z-index: 9999999;
}
&__wrapper {
// padding-top: var(--status-bar-height);
box-sizing: content-box;
&.fixed {
box-sizing: content-box;
position: fixed;
top: var(--status-bar-height);
// top: 0;
left: 0;
right: 0;
}
z-index: 999;
position: relative;
background-color: white;
width: 750rpx;
height: $height;
display: flex;
align-items: center;
&.border {
@include hairline--bottom;
}
font-size: 29rpx;
.#{$name}__left {
box-sizing: content-box;
padding: 0 20rpx;
width: 150rpx;
// position: absolute;
// left: 0;
// top: 0;//var(--status-bar-height);
display: flex;
align-items: center;
// cursor: pointer;
font-size: 28rpx;
height: $height;
// line-height: 1.5;
.#{$name}__icon {
box-sizing: content-box;
margin-right: 8rpx;
vertical-align: middle;
line-height: 1.5;
width: 25rpx;
height: 28rpx;
}
.#{$name}__text {
box-sizing: content-box;
flex: 1;
width: 0;
font-size: 32rpx;
font-weight: bold;
line-height: 1.2;
margin-left: 20rpx;
vertical-align: middle;
white-space: nowrap;
}
}
.#{$name}__middle {
box-sizing: content-box;
white-space: nowrap;
text-align: center;
// position: absolute;
font-size: 32rpx;
font-weight: 600;
display: flex;
align-items: center;
&.center {
justify-content: center;
}
&.left {
justify-content: flex-start;
}
// justify-content: center;
height: $height;
line-height: $height;
flex: 1;
width: 0;
// right: 90rpx;
// left: 90rpx;
// top: 0;//var(--status-bar-height);
}
.#{$name}__right {
box-sizing: content-box;
width: 100rpx;
padding: 0 20rpx;
// position: absolute;
display: flex;
align-items: center;
justify-content: flex-end;
// right: 0;
height: $height;
width: 150rpx;
// top: 0;//var(--status-bar-height);
// cursor: pointer;
}
}
}
</style>