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.
229 lines
5.1 KiB
229 lines
5.1 KiB
<template> |
|
<view |
|
class="tui-navigation-bar" |
|
:class="{ 'tui-bar-line': opacity > 0.85 && splitLine, 'tui-navbar-fixed': isFixed, 'tui-backdrop__filter': backdropFilter }" |
|
:style="{ height: height + 'px', backgroundColor: `rgba(${background},${opacity})`, opacity: dropDownOpacity }" |
|
> |
|
<view class="tui-status-bar" :style="{ height: statusBarHeight + 'px' }" v-if="isImmersive"></view> |
|
<view class="tui-navigation_bar-title" :style="{ opacity: opacity, color: color, paddingTop: top - statusBarHeight + 'px' }" v-if="title && !isCustom">{{ title }}</view> |
|
<slot /> |
|
</view> |
|
</template> |
|
|
|
<script> |
|
export default { |
|
name: 'tuiNavigationBar', |
|
props: { |
|
//NavigationBar标题 |
|
title: { |
|
type: String, |
|
default: '' |
|
}, |
|
//NavigationBar标题颜色 |
|
color: { |
|
type: String, |
|
default: '#333' |
|
}, |
|
//NavigationBar背景颜色,不支持rgb |
|
backgroundColor: { |
|
type: String, |
|
default: '#fff' |
|
}, |
|
//是否需要分割线 |
|
splitLine: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
//是否设置不透明度 |
|
isOpacity: { |
|
type: Boolean, |
|
default: true |
|
}, |
|
//不透明度最大值 0-1 |
|
maxOpacity: { |
|
type: [Number, String], |
|
default: 1 |
|
}, |
|
//滚动条滚动距离 |
|
scrollTop: { |
|
type: [Number, String], |
|
default: 0 |
|
}, |
|
/* |
|
isOpacity 为true时生效 |
|
opacity=scrollTop /windowWidth * scrollRatio |
|
*/ |
|
scrollRatio: { |
|
type: [Number, String], |
|
default: 0.3 |
|
}, |
|
//是否自定义header内容 |
|
isCustom: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
//是否沉浸式 |
|
isImmersive: { |
|
type: Boolean, |
|
default: true |
|
}, |
|
isFixed: { |
|
type: Boolean, |
|
default: true |
|
}, |
|
//是否开启高斯模糊效果[仅在支持的浏览器有效果] |
|
backdropFilter: { |
|
type: Boolean, |
|
default: false |
|
}, |
|
//下拉隐藏NavigationBar,主要针对有回弹效果ios端 |
|
dropDownHide: { |
|
type: Boolean, |
|
default: false |
|
} |
|
}, |
|
watch: { |
|
scrollTop(newValue, oldValue) { |
|
if (this.isOpacity) { |
|
this.opacityChange(); |
|
} |
|
}, |
|
backgroundColor(val) { |
|
if (val) { |
|
this.background = this.hexToRgb(val); |
|
} |
|
} |
|
}, |
|
data() { |
|
return { |
|
width: 375, //header宽度 |
|
left: 375, //小程序端 左侧距胶囊按钮距离 |
|
height: 44, //header高度 |
|
top: 0, |
|
scrollH: 1, //滚动总高度,计算opacity |
|
opacity: 1, //0-1 |
|
statusBarHeight: 0, //状态栏高度 |
|
background: '255,255,255', //header背景色 |
|
dropDownOpacity: 1 |
|
}; |
|
}, |
|
created() { |
|
this.opacity = this.isOpacity ? 0 : this.maxOpacity; |
|
this.background = this.hexToRgb(this.backgroundColor); |
|
let obj = {}; |
|
// #ifdef MP-WEIXIN |
|
obj = wx.getMenuButtonBoundingClientRect(); |
|
// #endif |
|
// #ifdef MP-BAIDU |
|
obj = swan.getMenuButtonBoundingClientRect(); |
|
// #endif |
|
// #ifdef MP-ALIPAY |
|
my.hideAddToDesktopMenu(); |
|
// #endif |
|
uni.getSystemInfo({ |
|
success: res => { |
|
this.statusBarHeight = res.statusBarHeight; |
|
this.width = res.windowWidth; |
|
this.left = obj.left || res.windowWidth; |
|
if (this.isImmersive) { |
|
this.height = obj.top ? obj.top + obj.height + 8 : res.statusBarHeight + 44; |
|
} |
|
this.scrollH = res.windowWidth * this.scrollRatio; |
|
this.top = obj.top ? obj.top + (obj.height - 32) / 2 : res.statusBarHeight + 6; |
|
this.$emit('init', { |
|
width: this.width, |
|
height: this.height, |
|
left: this.left, |
|
top: this.top, |
|
statusBarHeight: this.statusBarHeight, |
|
opacity: this.opacity |
|
}); |
|
} |
|
}); |
|
}, |
|
methods: { |
|
hexToRgb(hex) { |
|
let rgb = '255,255,255'; |
|
if (hex && ~hex.indexOf('#')) { |
|
if (hex.length === 4) { |
|
let text = hex.substring(1, 4); |
|
hex = '#' + text + text; |
|
} |
|
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); |
|
if (result) { |
|
rgb = `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`; |
|
} |
|
} |
|
return rgb; |
|
}, |
|
opacityChange() { |
|
if (this.dropDownHide) { |
|
if (this.scrollTop < 0) { |
|
if (this.dropDownOpacity > 0) { |
|
this.dropDownOpacity = 1 - Math.abs(this.scrollTop) / 30; |
|
} |
|
} else { |
|
this.dropDownOpacity = 1; |
|
} |
|
} |
|
let scroll = this.scrollTop <= 1 ? 0 : this.scrollTop; |
|
let opacity = scroll / this.scrollH; |
|
if ((this.opacity >= this.maxOpacity && opacity >= this.maxOpacity) || (this.opacity == 0 && opacity == 0)) { |
|
return; |
|
} |
|
this.opacity = opacity > this.maxOpacity ? this.maxOpacity : opacity; |
|
this.$emit('change', { |
|
opacity: this.opacity |
|
}); |
|
} |
|
} |
|
}; |
|
</script> |
|
|
|
<style scoped> |
|
.tui-navigation-bar { |
|
width: 100%; |
|
transition: opacity 0.4s; |
|
} |
|
.tui-backdrop__filter { |
|
/* Safari for macOS & iOS */ |
|
-webkit-backdrop-filter: blur(15px); |
|
/* Google Chrome */ |
|
backdrop-filter: blur(15px); |
|
} |
|
|
|
.tui-navbar-fixed { |
|
position: fixed; |
|
left: 0; |
|
top: 0; |
|
z-index: 9998; |
|
} |
|
|
|
.tui-status-bar { |
|
width: 100%; |
|
} |
|
|
|
.tui-navigation_bar-title { |
|
width: 100%; |
|
font-size: 17px; |
|
line-height: 17px; |
|
/* #ifndef APP-PLUS */ |
|
font-weight: 500; |
|
/* #endif */ |
|
height: 32px; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
} |
|
|
|
.tui-bar-line::after { |
|
content: ''; |
|
position: absolute; |
|
border-bottom: 1rpx solid #eaeef1; |
|
-webkit-transform: scaleY(0.5); |
|
transform: scaleY(0.5); |
|
bottom: 0; |
|
right: 0; |
|
left: 0; |
|
} |
|
</style>
|
|
|