Files
2023-09-20 21:49:33 +08:00

651 lines
15 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="hx-navbar" >
<view
:class="{'hx-navbar--fixed': fixed,'hx-navbar--shadow':shadow,'hx-navbar--border':border}"
:style="{'background': backgroundColorRgba}"
class="hx-navbar__content">
<block v-if="backgroundImg">
<image class="navbgimg" :style="bgImgHeight?`height:${bgImgHeight}`:''" :src="backgroundImg" :mode="bgImgHeight=='auto'?'widthFix':''"></image>
</block>
<view :style="{ height: statusBarHeight ,'background': statusBarBackground}" class="hx-status-bar" v-if="statusBar" ></view>
<view :style="{color:colorInfo,height: height,'line-height':height}" class="hd hx-navbar__header hx-navbar__content_view">
<view class="hx-navbar__header-btns hx-navbar__content_view" @tap="onClickLeft" v-if="leftSlot" :style="{'color': colorInfo}">
<block v-if="leftText.length || leftIcon.length || back">
<view
v-if="leftIcon.length || back"
:class="back ? 'left_back' : ''"
class="hx-navbar__content_view" >
<uni-icons :type="back ? 'arrowleft' : leftIcon" :color="colorInfo" size="28"/>
</view>
<view
v-if="leftText.length"
:class="{'hx-navbar-btn-icon-left':!leftIcon.length}"
class="hx-navbar-btn-text hx-navbar__content_view">{{ leftText }}</view>
</block>
<block v-else>
<slot name="leftAfter" v-if="leftSlidiSwitch && slotSlidiSwitch == 1" />
<slot name="left" v-else/>
</block>
</view>
<view class="hx-navbar__header-container hx-navbar__content_view">
<view
v-if="title.length"
class="hx-navbar__header-container-inner hx-navbar__content_view" style="position: relative;">{{ title }}
</view>
<!-- 标题插槽 -->
<block v-else>
<slot name="centerAfter" v-if="centerSlidiSwitch && slotSlidiSwitch == 1"/>
<slot v-else/>
</block>
</view>
<view :class="title.length?'hx-navbar__header-btns-right':''"
class="hx-navbar__header-btns hx-navbar__content_view"
@tap="onClickRight"
v-if="rightSlot">
<!-- 优先显示图标 -->
<block v-if="rightIcon.length || rightText.length">
<view class="hx-navbar__content_view" v-if="rightIcon.length">
<uni-icons :type="rightIcon" :color="colorInfo" size="28"/>
</view>
<view v-if="rightText.length" class="hx-navbar-btn-text hx-navbar__content_view">{{ rightText }}</view>
</block>
<block v-else>
<slot name="rightAfter" v-if="rightSlidiSwitch && slotSlidiSwitch == 1"/>
<slot name="right" v-else/>
</block>
</view>
</view>
</view>
<view
v-if="placeholder"
class="hx-navbar__placeholder">
<view :style="{ height: statusBarHeight}" class="hx-status-bar" v-if="statusBar" ></view>
<view :style="{ height: height}" />
</view>
</view>
</template>
<script>
import uniIcons from "@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue"
//获取系统状态栏高度
var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
export default {
name: "hx-navbar",
components: {
uniIcons
},
data() {
return {
statusBarHeight: statusBarHeight,
transparentValue: 0,
navTransparentFixedFontColor: '#fff',
statusBarFontColorInfo: [],
backgroundColorRgba: 'rgba(255,255,255,1)',
backgroundColorRgb: 'rgb(222,222,222)',
colorInfo: '#000000',
placeholder: false,
colorContainer: null,
slotSlidiSwitch: 0
};
},
props:{
height:{
type: String,
default: "44px"
},
//导航栏占位符 显示(show),隐藏(hidden),自动(auto:如果头部为固定fiexd ,则显示占位符)
barPlaceholder:{
type: String,
default: "auto"
},
//返回上一页
back:{
type: [Boolean, String],
default: true
},
//标题
title: {
type: String,
default: ''
},
//是否开启左插槽
leftSlot:{
type: [Boolean, String],
default: true
},
//是否开启右插槽
rightSlot:{
type: [Boolean, String],
default: true
},
//左边文字
leftText: {
type: String,
default: ''
},
//右插槽文字
rightText: {
type: String,
default: ''
},
//左插槽图标
leftIcon: {
type: String,
default: ''
},
//右插槽图标
rightIcon: {
type: String,
default: ''
},
//是否固定头
fixed: {
type: [Boolean, String],
default: false
},
//文字颜色
color: {
type: [Array,String],
default: "#000000"
},
//导航栏背景颜色
backgroundColor: {
type: Array,
default: function(){
return new Array([255,255,255],[255,255,255]);
}
},
//线性渐变角度
backgroundColorLinearDeg: {
type: String,
default: '45'
},
//背景图片
backgroundImg: {
type: String,
default: ''
},
bgImgHeight:{
type:String,
default:'auto'
},
//背景透明(show,hidden,auto
transparent: {
type: String,
default: 'show'
},
//状态栏字体颜色,只支持黑(#000000)和白(#FFFFFF)两种颜色。(,)
statusBarFontColor:{
type: [Array,String],
default:function(){
return new Array("#000000","#000000");
}
},
//是否包含状态栏
statusBar: {
type: [Boolean, String],
default: true
},
//状态栏背景颜色
statusBarBackground:{
type: String,
default: ''
},
//导航栏阴影
shadow: {
type: [String, Boolean],
default: false
},
//导航栏边框
border: {
type: [String, Boolean],
default: false
},
//跳至普通页面
defaultBackUrl: {
type: String,
default: ''
},
//跳至tabber页面
backTabbarUrl: {
type: String,
default: '/pages/home/index'
},
//滑动后切换左插槽
leftSlidiSwitch:{
type: [Boolean,String],
default: false,
},
//滑动后切换中间插槽
centerSlidiSwitch:{
type: [Boolean,String],
default: false
},
//滑动后切换右插槽
rightSlidiSwitch:{
type: [Boolean,String],
default: false
},
//页面的onPageScroll
pageScroll:{
type: Object,
default:function(){
return {}
}
},
},
created(){
var that = this;
//是否添加占位符
switch (that.barPlaceholder){
case 'show':
that.placeholder = true;
break;
case 'hidden':
that.placeholder = false;
break;
case 'auto':
if(that.fixed){
that.placeholder = true;
}
break;
}
//设置状态栏文字颜色
that.setStatusBarFontColor();
//文字颜色
that.colorContainer = typeof that.color == 'object' ? that.color : [that.color,that.color];
that.colorInfo = that.colorContainer[0];
//导航栏透明设置 及监听滚动
switch (that.transparent){
case 'show':
that.transparentValue = 1;
break;
case 'hidden':
that.transparentValue = 0;
break;
case 'auto':
this.setTVAuto(that.pageScroll)
break;
}
that.setBgColor();
//滑动切换
if(that.fixed && (that.leftSlidiSwitch || that.centerSlidiSwitch || that.rightSlidiSwitch)){
that.doScroll(that.pageScroll);
}
},
watch:{
pageScroll(val,oldVal){
var that = this;
//导航栏透明设置 及监听滚动
switch (that.transparent){
case 'show':
that.transparentValue = 1;
break;
case 'hidden':
that.transparentValue = 0;
break;
case 'auto':
this.setTVAuto(val)
break;
}
//滑动切换
if(that.fixed && (that.leftSlidiSwitch || that.centerSlidiSwitch || that.rightSlidiSwitch)){
that.doScroll(val);
}
},
//监控透明度变化
transparentValue(val,oldVal) {
var that = this;
//this.settingColor();
//头条小程序不支持setNavigationBarColor方法
// #ifndef MP-TOUTIAO || H5
if(oldVal > 0.8){
uni.setNavigationBarColor({
frontColor: that.statusBarFontColorInfo[1],
backgroundColor: that.backgroundColorRgb
});
}else if(oldVal < 0.2){
uni.setNavigationBarColor({
frontColor: that.statusBarFontColorInfo[0],
backgroundColor: that.backgroundColorRgb
});
}
// #endif
// #ifdef MP-TOUTIAO
if (tt.setNavigationBarColor) {
if(oldVal > 0.8){
tt.setNavigationBarColor({
frontColor: that.statusBarFontColorInfo[1],
backgroundColor: that.backgroundColorRgb,
success(res) {},
fail(res) {}
});
}else if(oldVal < 0.2){
tt.setNavigationBarColor({
frontColor: that.statusBarFontColorInfo[0],
backgroundColor: that.backgroundColorRgb,
success(res) {},
fail(res) {}
});
}
} else {
console.log("hx-navbar 提示:当前客户端版本过低,无法使用状态栏颜色修改功能,请升级(基础库1.40+)。")
}
// #endif
},
//监听背景颜色
backgroundColor(val,old){
var that = this;
that.setBgColor()
},
color(val,old){
var that = this;
//文字颜色
/* that.colorContainer = typeof val == 'object' ? val : [val,val];
that.colorInfo = that.colorContainer[0]; */
}
},
methods: {
onClickLeft () {
if(this.back){
if(getCurrentPages().length>1){
uni.navigateBack();
}else{
// #ifdef H5
history.back()
// #endif
// #ifndef H5
if(this.defaultBackUrl){
uni.redirectTo({
url:this.defaultBackUrl
})
}else{
if(this.backTabbarUrl){
uni.reLaunch({
url: this.backTabbarUrl
});
}
}
// #endif
}
}else{
this.$emit('click-left')
}
},
onClickRight () {
this.$emit('click-right')
},
//监听滚动后的操作
doScroll(e){
let that = this;
that.$emit('scroll', e);
if (e.scrollTop > 100) {
that.slotSlidiSwitch = 1;
} else {
that.slotSlidiSwitch = 0
}
},
//滑动渐变
setTVAuto(e){
let that = this;
that.$emit('scroll', e);
if (e.scrollTop > 100) {
that.transparentValue = 1;
that.colorInfo = that.colorContainer[1];
} else {
that.transparentValue = e.scrollTop / 100;
that.colorInfo = that.colorContainer[0];
}
that.setBgColor();
},
//背景颜色
setBgColor(){
var that = this;
//如果存在背景图片则背景颜色失效
// if(that.backgroundImg){
// that.backgroundColorRgba = "url(" + that.backgroundImg + ")";
// return;
// }
//背景颜色
if(typeof that.backgroundColor[0] == 'object'){
let l = that.backgroundColor.length;
if( l >= 2){
let rgbStr = "linear-gradient("+ that.backgroundColorLinearDeg +"deg,";
let c = null;
for(var i in that.backgroundColor){
c = that.backgroundColor[i];
rgbStr += "rgba("+ c[0] + "," + c[1] + "," + c[2] +"," + that.transparentValue+")";
if(l != (i*1)+1){
rgbStr += ",";
}
}
rgbStr += ")";
that.backgroundColorRgba = rgbStr;
}
}else{
let rgbStr = that.backgroundColor[0] + ','+ that.backgroundColor[1] + ','+ that.backgroundColor[2];
that.backgroundColorRgb= 'rgb('+ rgbStr + ')';
that.backgroundColorRgba = 'rgba('+ rgbStr +',' + that.transparentValue+')';
}
},
setStatusBarFontColor(){
var that = this;
if(typeof that.statusBarFontColor == 'string'){
that.statusBarFontColorInfo = [that.statusBarFontColor,that.statusBarFontColor];
}else if(typeof that.statusBarFontColor == 'object'){
if (that.statusBarFontColor.length==1){
that.statusBarFontColorInfo = [that.statusBarFontColor[0],that.statusBarFontColor[0]];
}else if(that.statusBarFontColor.length>=2){
that.statusBarFontColorInfo = [that.statusBarFontColor[0],that.statusBarFontColor[1]];
}
}
// #ifndef MP-TOUTIAO || H5
uni.setNavigationBarColor({
frontColor: that.statusBarFontColorInfo[0],
backgroundColor: that.backgroundColorRgb
});
// #endif
// #ifdef MP-TOUTIAO
if (tt.setNavigationBarColor) {
tt.setNavigationBarColor({
frontColor: that.statusBarFontColorInfo[0],
backgroundColor: that.backgroundColorRgb
});
} else {
console.log("hx-navbar 提示:当前客户端版本过低,无法使用状态栏颜色修改功能,请升级(基础库1.40+)。")
}
// #endif
}
},
destroyed(){
},
}
</script>
<style lang="scss">
$nav-height: 44px;
.hd{
overflow: hidden;
}
//防止其他ui影响
// .hx-navbar uni-view,
// .hx-navbar uni-scroll-view,
// .hx-navbar uni-swiper,
// .hx-navbar uni-button,
// .hx-navbar uni-input,
// .hx-navbar uni-textarea,
// .hx-navbar uni-label,
// .hx-navbar uni-navigator,
// .hx-navbar uni-image {
// box-sizing: unset;
// }
.hx-navbar {
position: relative;
padding-top: 0;
overflow: hidden;
&__content {
display: block;
position: relative;
width: 100%;
/*background-color: $uni-bg-color*/;
overflow: hidden;
.navbgimg{
position: absolute;
top: 0;
left: 0;
z-index: 0;
width: 100%;
}
.hx-navbar__content_view {
// line-height: $nav-height;
display: flex;
align-items: center;
}
.hx-status-bar {
display: block;
width: 100%;
height: 40px;
height: var(--status-bar-height);
position: relative;
z-index: 1;
}
}
&__header {
position: relative;
z-index: 1;
display: flex;
flex-direction: row;
width: 100%;
height: $nav-height;
line-height: $nav-height;
font-size: 36upx;
transition: color 0.5s ease 0s;
&-btns {
display: inline-flex;
flex-wrap: nowrap;
flex-shrink: 0;
min-width: 30px;
padding: 0 6px;
&:first-child {
padding-left: 0;
}
&:last-child {
min-width: 54px;
}
&-right:last-child{
width: 120upx;
text-align: right;
flex-direction: row-reverse;
}
}
&-container {
width: 100%;
margin: 0 10upx;
&-inner {
width: 100%;
display: flex;
justify-content: center;
font-size: 36upx;
// padding-right: 60upx;
}
}
}
&__placeholder {
&-view {
height: $nav-height;
}
}
&--fixed {
position: fixed;
top:0;
z-index: 998;
}
&--shadow {
box-shadow: 0 2upx 12upx #ccc;
}
&--border:after {
position: absolute;
z-index: 3;
bottom: 0;
left: 0;
right: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #efefef;
}
}
.left_back{
padding-left: 12upx;
padding-right: 12upx;
}
.pink-dot{
width:24rpx;
height:24px;
background:rgba(255,86,74,0.4);
border-radius:50%;
position: absolute;
bottom: 0;
right: 0;
}
</style>