提交 23a904ba 编写于 作者: I iotjin

add jh-nav-bar

上级 180fbc2e
Component({
options: {
multipleSlots: true,
addGlobalClass: true
},
properties: {
extClass: {
type: String,
value: ''
},
background: {
type: String,
// value: 'rgba(255, 255, 255, 1)',
value: '#38BC9D',
observer: '_showChange'
},
backgroundColorTop: {
type: String,
// value: 'rgba(255, 255, 255, 1)',
value: '#38BC9D',
observer: '_showChangeBackgroundColorTop'
},
color: {
type: String,
// value: 'rgba(0, 0, 0, 1)'
value: 'white'
},
title: {
type: String,
value: ''
},
searchText: {
type: String,
value: '点我搜索'
},
searchBar: {
type: Boolean,
value: false
},
back: {
type: Boolean,
value: true
},
home: {
type: Boolean,
value: false
},
iconTheme: {
type: String,
value: 'white'
},
/* animated: {
type: Boolean,
value: true
},
show: {
type: Boolean,
value: true,
observer: '_showChange'
}, */
delta: {
type: Number,
value: 1
}
},
created() {
this.getSystemInfo()
},
attached() {
this.setStyle() // 设置样式
},
data: {},
pageLifetimes: {
show() {
if (getApp().globalSystemInfo.ios) {
this.getSystemInfo()
this.setStyle() // 设置样式1
}
},
hide() {}
},
methods: {
setStyle(life) {
const {
statusBarHeight,
navBarHeight,
capsulePosition,
navBarExtendHeight,
ios,
windowWidth
} = getApp().globalSystemInfo
const {
back,
home,
title
} = this.data
const rightDistance = windowWidth - capsulePosition.right // 胶囊按钮右侧到屏幕右侧的边距
const leftWidth = windowWidth - capsulePosition.left // 胶囊按钮左侧到屏幕右侧的边距
const navigationbarinnerStyle = [
`color: ${this.data.color}`,
`background: ${this.data.background}`,
`height:${navBarHeight + navBarExtendHeight}px`,
`padding-top:${statusBarHeight}px`,
`padding-right:${leftWidth}px`,
`padding-bottom:${navBarExtendHeight}px`
].join(';')
let navBarLeft = []
if ((back && !home) || (!back && home)) {
navBarLeft = [`width:${capsulePosition.width}px`, `height:${capsulePosition.height}px`].join(';')
} else if ((back && home) || title) {
navBarLeft = [
`width:${capsulePosition.width}px`,
`height:${capsulePosition.height}px`,
`margin-left:${rightDistance}px`
].join(';')
} else {
navBarLeft = ['width:auto', 'margin-left:0px'].join(';')
}
if (life === 'created') {
this.data = {
navigationbarinnerStyle,
navBarLeft,
navBarHeight,
capsulePosition,
navBarExtendHeight,
ios
}
} else {
this.setData({
navigationbarinnerStyle,
navBarLeft,
navBarHeight,
capsulePosition,
navBarExtendHeight,
ios
})
}
},
_showChange() {
this.setStyle()
},
// 返回事件
back() {
wx.navigateBack({
delta: 1
});
this.triggerEvent('back', {
delta: this.data.delta
})
},
home() {
this.triggerEvent('home', {})
},
search() {
this.triggerEvent('search', {})
},
checkRect(rect) { // 胶囊信息4种任一属性为0返回true
return !rect.width || !rect.top || !rect.left || !rect.height
},
getMenuButtonBoundingClientRect(systemInfo) {
const ios = !!(systemInfo.system.toLowerCase().search('ios') + 1)
let rect
try {
rect = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null
if (rect === null) {
throw new Error('getMenuButtonBoundingClientRect error')
}
// 取值为0的情况 有可能width不为0 top为0的情况
if (this.checkRect(rect)) {
throw new Error('getMenuButtonBoundingClientRect error')
}
} catch (error) {
let gap = '' // 胶囊按钮上下间距 使导航内容居中
let width = 96 // 胶囊的宽度
if (systemInfo.platform === 'android') {
gap = 8
width = 96
} else if (systemInfo.platform === 'devtools') {
if (ios) {
gap = 5.5 // 开发工具中ios手机
} else {
gap = 7.5 // 开发工具中android和其他手机
}
} else {
gap = 4
width = 88
}
if (!systemInfo.statusBarHeight) {
// 开启wifi的情况下修复statusBarHeight值获取不到
systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20
}
rect = {
// 获取不到胶囊信息就自定义重置一个
bottom: systemInfo.statusBarHeight + gap + 32,
height: 32,
left: systemInfo.windowWidth - width - 10,
right: systemInfo.windowWidth - 10,
top: systemInfo.statusBarHeight + gap,
width
}
}
return rect
},
getSystemInfo() {
const app = getApp()
if (app.globalSystemInfo && !app.globalSystemInfo.ios) {
return app.globalSystemInfo
} else {
const systemInfo = wx.getSystemInfoSync()
const ios = !!(systemInfo.system.toLowerCase().search('ios') + 1)
const rect = this.getMenuButtonBoundingClientRect(systemInfo)
let navBarHeight = ''
if (!systemInfo.statusBarHeight) {
systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20
navBarHeight = (function () {
const gap = rect.top - systemInfo.statusBarHeight
return 2 * gap + rect.height
}())
systemInfo.statusBarHeight = 0
systemInfo.navBarExtendHeight = 0 // 下方扩展4像素高度 防止下方边距太小
} else {
navBarHeight = (function () {
const gap = rect.top - systemInfo.statusBarHeight
return systemInfo.statusBarHeight + 2 * gap + rect.height
}())
if (ios) {
systemInfo.navBarExtendHeight = 4 // 下方扩展4像素高度 防止下方边距太小
} else {
systemInfo.navBarExtendHeight = 0
}
}
systemInfo.navBarHeight = navBarHeight // 导航栏高度不包括statusBarHeight
systemInfo.capsulePosition = rect
systemInfo.ios = ios // 是否ios
app.globalSystemInfo = systemInfo // 将信息保存到全局变量中,后边再用就不用重新异步获取了
// console.log('systemInfo', systemInfo);
return systemInfo
}
}
}
})
\ No newline at end of file
{
"component": true,
"usingComponents": {}
}
<view class="lxy-nav-bar {{extClass}}"
style="background: {{backgroundColorTop}};height: {{navBarHeight+ navBarExtendHeight}}px;">
<view class="lxy-nav-bar__placeholder {{ios ? 'ios' : 'android'}}"
style="padding-top: {{navBarHeight+ navBarExtendHeight}}px;visibility: hidden;"></view>
<view class="lxy-nav-bar__inner {{ios ? 'ios' : 'android'}}" style="{{navigationbarinnerStyle}}{{displayStyle}}">
<view class='lxy-nav-bar__left' style="{{navBarLeft}}">
<block wx:if="{{back&&!home}}">
<view bindtap="back" class="lxy-nav-bar__button lxy-nav-bar__btn_goback {{iconTheme}}"></view>
</block>
<block wx:if="{{!back&&home}}">
<view bindtap="home" class="lxy-nav-bar__button lxy-nav-bar__btn_gohome {{iconTheme}}"></view>
</block>
<block wx:elif="{{back&&home}}">
<view class="lxy-nav-bar__buttons {{ios ? 'ios' : 'android'}}" wx:if="{{home}}">
<view bindtap="back" class="lxy-nav-bar__button lxy-nav-bar__btn_goback {{iconTheme}}" wx:if="{{back}}">
</view>
<view bindtap="home" class="lxy-nav-bar__button lxy-nav-bar__btn_gohome {{iconTheme}}"></view>
</view>
</block>
<block wx:else>
<slot name="left"></slot>
</block>
</view>
<view class='lxy-nav-bar__center'>
<block wx:if="{{title}}">
<text>{{title}}</text>
</block>
<view class='lxy-nav-bar-search' style="height:{{capsulePosition.height}}px;" wx:elif="{{searchBar}}"
bindtap="search">
<view class='lxy-nav-bar-search__icon' />
<view class='lxy-nav-bar-search__input'>{{searchText}}</view>
</view>
<!-- 暂时不开发标题loading. 看后期需要 -->
<!-- <view wx:if="{{loading}}" class="lxy-nav-bar__loading">
<view class="lxy-loading" style="width:{{size.width}}rpx;height:{{size.height}}rpx;"></view>
</view> -->
<block wx:else>
<slot name="center"></slot>
</block>
</view>
<view class='lxy-nav-bar__right'>
<slot name="right"></slot>
</view>
</view>
</view>
\ No newline at end of file
/* view,
text,
scroll-view,
input,
button,
image,
cover-view {
box-sizing: border-box;
} */
page {
--height: 44px;
/* 4*2+32 */
--right: 97px;
/* 10+87 */
--navBarExtendHeight: 4px;
box-sizing: border-box;
}
.lxy-nav-bar .ios {
--height: 44px;
/* 4*2+32 */
--right: 97px;
/* 10+87 */
--navBarExtendHeight: 4px;
box-sizing: border-box;
}
.lxy-nav-bar .android {
--height: 48px;
/* 8*2+32 */
--right: 96px;
/* 10+87 */
--navBarExtendHeight: 4px;
box-sizing: border-box;
}
.lxy-nav-bar .devtools {
--height: 42px;
/* 5*2+32 */
--right: 88px;
/* 10+87 */
--navBarExtendHeight: 4px;
box-sizing: border-box;
}
.lxy-nav-bar__inner {
position: fixed;
top: 0;
left: 0;
z-index: 5001;
height: var(--height);
display: flex;
align-items: center;
padding-right: var(--right);
width: 100%;
padding-bottom: var(--navBarExtendHeight);
}
.lxy-nav-bar__inner .lxy-nav-bar__left {
position: relative;
width: var(--right);
height: 32px;
/* padding-left: 10px; */
display: flex;
align-items: center;
}
.lxy-nav-bar__buttons {
height: 100%;
width: 100%;
display: flex;
align-items: center;
border-radius: 16px;
border: 1rpx solid rgba(204, 204, 204, 0.6);
position: relative;
}
.lxy-nav-bar__buttons.android {
border: 1rpx solid rgba(234, 234, 234, 0.6);
}
.lxy-nav-bar__buttons::after {
position: absolute;
content: '';
width: 1rpx;
height: 18.4px;
background: rgba(204, 204, 204, 0.6);
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.lxy-nav-bar__buttons.android::after {
background: rgba(234, 234, 234, 0.6);
}
.lxy-nav-bar__button {
width: 50%;
height: 100%;
display: flex;
font-size: 12px;
background-repeat: no-repeat;
background-position: center center;
background-size: 1em 2em;
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_goback:active,
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_gohome:active {
opacity: 0.5;
}
.lxy-nav-bar__inner .lxy-nav-bar__center {
font-size: 17px;
line-height: 17px;
text-align: center;
position: relative;
flex: 1;
display: -webkit-box;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
padding-left: 10px;
}
.lxy-nav-bar__inner .lxy-nav-bar__center .lxy-nav-bar__center-title {
margin-top: -2px;
}
.lxy-nav-bar__inner .lxy-nav-bar__loading {
font-size: 0;
}
.lxy-nav-bar__inner .lxy-nav-bar__loading .lxy-loading {
margin-left: 0;
}
.lxy-nav-bar__inner .lxy-nav-bar__right {
margin-right: 10px;
}
.lxy-nav-bar__placeholder {
height: var(--height);
background: #f8f8f8;
position: relative;
z-index: 50;
}
.lxy-nav-bar-search {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 32px;
border-radius: 16px;
position: relative;
background: #f6f6f6;
}
.lxy-nav-bar-search__input {
height: 100%;
display: flex;
align-items: center;
color: #999;
font-size: 15px;
line-height: 15px;
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_goback {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z'/%3E%3C/svg%3E");
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_goback.white {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z' fill='%23ffffff'/%3E%3C/svg%3E");
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_gohome {
background-image: url("data:image/svg+xml,%3Csvg t='1565752242401' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='4326' width='48' height='48'%3E%3Cpath d='M931.148 451.25L591.505 97.654c-21.106-21.953-49.313-34.034-79.551-34.034-30.235 0-58.448 12.081-79.554 34.034L92.76 451.25c-35.049 36.498-30.536 68.044-24.742 81.222 4.13 9.35 18.07 35.05 58.231 35.05h49.78v272.016c0 61.756 44.342 119.906 107.357 119.906h144.587v-287.87c0-30.866-4.675-48.062 26.848-48.062h114.268c31.52 0 26.845 17.196 26.845 48.061v287.872h144.588c63.013 0 107.358-58.15 107.358-119.906V567.523h49.782c40.16 0 54.1-25.7 58.229-35.05 5.793-13.18 10.306-44.726-24.743-81.224z m-33.486 60.28h-105.77v328.007c0 30.865-19.877 63.917-51.37 63.917h-88.6V671.572c0-61.761-19.79-104.05-82.832-104.05H454.821c-63.045 0-82.836 42.289-82.836 104.05v231.883h-88.599c-31.495 0-51.37-33.052-51.37-63.917V511.529H126.25c-0.984 0-1.888-3.852-2.708-3.907 1.94-3.388 5.276-11.975 10.825-17.743l339.671-353.35c10.142-10.578 24.467-17.057 38.353-16.924 13.888-0.133 27.342 6.346 37.483 16.923L889.54 489.88c5.549 5.768 8.885 14.355 10.825 17.743-0.818 0.055-1.72 3.907-2.704 3.907z' fill='%23000000' p-id='4327'%3E%3C/path%3E%3C/svg%3E");
background-size: 22px 22px;
}
.lxy-nav-bar__inner .lxy-nav-bar__left .lxy-nav-bar__btn_gohome.white {
background-image: url("data:image/svg+xml,%3Csvg t='1565752242401' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='4326' width='48' height='48'%3E%3Cpath d='M931.148 451.25L591.505 97.654c-21.106-21.953-49.313-34.034-79.551-34.034-30.235 0-58.448 12.081-79.554 34.034L92.76 451.25c-35.049 36.498-30.536 68.044-24.742 81.222 4.13 9.35 18.07 35.05 58.231 35.05h49.78v272.016c0 61.756 44.342 119.906 107.357 119.906h144.587v-287.87c0-30.866-4.675-48.062 26.848-48.062h114.268c31.52 0 26.845 17.196 26.845 48.061v287.872h144.588c63.013 0 107.358-58.15 107.358-119.906V567.523h49.782c40.16 0 54.1-25.7 58.229-35.05 5.793-13.18 10.306-44.726-24.743-81.224z m-33.486 60.28h-105.77v328.007c0 30.865-19.877 63.917-51.37 63.917h-88.6V671.572c0-61.761-19.79-104.05-82.832-104.05H454.821c-63.045 0-82.836 42.289-82.836 104.05v231.883h-88.599c-31.495 0-51.37-33.052-51.37-63.917V511.529H126.25c-0.984 0-1.888-3.852-2.708-3.907 1.94-3.388 5.276-11.975 10.825-17.743l339.671-353.35c10.142-10.578 24.467-17.057 38.353-16.924 13.888-0.133 27.342 6.346 37.483 16.923L889.54 489.88c5.549 5.768 8.885 14.355 10.825 17.743-0.818 0.055-1.72 3.907-2.704 3.907z' fill='%23ffffff' p-id='4327'%3E%3C/path%3E%3C/svg%3E");
background-size: 22px 22px;
}
.lxy-nav-bar-search__icon {
width: 22px;
height: 22px;
display: flex;
align-items: center;
justify-content: center;
background-image: url("data:image/svg+xml,%3Csvg t='1565691512239' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='1240' width='48' height='48'%3E%3Cpath d='M819.2 798.254545L674.909091 653.963636c46.545455-48.872727 74.472727-114.036364 74.472727-186.181818 0-151.272727-123.345455-274.618182-274.618182-274.618182-151.272727 0-274.618182 123.345455-274.618181 274.618182 0 151.272727 123.345455 274.618182 274.618181 274.618182 65.163636 0 128-23.272727 174.545455-62.836364l144.290909 144.290909c2.327273 2.327273 6.981818 4.654545 11.636364 4.654546s9.309091-2.327273 11.636363-4.654546c6.981818-6.981818 6.981818-18.618182 2.327273-25.6zM235.054545 467.781818c0-132.654545 107.054545-239.709091 239.709091-239.709091 132.654545 0 239.709091 107.054545 239.709091 239.709091 0 132.654545-107.054545 239.709091-239.709091 239.709091-132.654545 0-239.709091-107.054545-239.709091-239.709091z' fill='%23999999' p-id='1241'%3E%3C/path%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: cover;
}
\ No newline at end of file
// 自定义导航条
const app = getApp();
Component({
/**
* 组件的一些选项
*/
options: {
addGlobalClass: true,
multipleSlots: true
},
/**
* 组件的对外属性
*/
properties: {
title: {
type: String,
value: '',
},
delta: {
type: Number,
value: 1
},
bgColor: {
type: String,
value: '#38BC9D',
},
isBack: {
type: Boolean,
value: true
},
backText: {
type: String,
value: ''
},
backColor: { //返回文字和返回按钮颜色
type: String,
value: 'white'
},
homeColor: { //home按钮颜色
type: String,
value: 'white'
},
titleColor: { //标题颜色
type: String,
value: 'white'
},
isCustom: {
type: Boolean,
value: false
},
bgImage: {
type: String,
value: '',
},
},
/**
* 组件的初始数据
*/
data: {
StatusBar: app.globalData.StatusBar,
CustomBar: app.globalData.CustomBar,
Custom: app.globalData.Custom
},
lifetimes: {
attached: function () {
// 页面创建时执行
console.info('---jh-nav-bar loaded!---')
// console.log(this.data.StatusBar);
// console.log(this.data.CustomBar);
// console.log(this.data.Custom);
},
detached: function () {
// 页面销毁时执行
console.info('---jh-nav-bar unloaded!---')
},
},
/**
* 组件的方法列表
*/
methods: {
onClickBack() {
console.log('返回上个页面');
wx.navigateBack({
delta: this.properties.delta
});
this.triggerEvent('clickBack', {})
},
onClickHome() {
console.log('返回主页');
wx.reLaunch({
url: '/pages/demoList/demoList',
})
this.triggerEvent('clickHome', {})
}
}
})
\ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<view class="nav-custom" style="height:{{CustomBar}}px">
<view class="nav-bar nav-fixed {{bgImage!=''?'nav-bg-img':''}}"
style="height:{{CustomBar}}px;padding-top:{{StatusBar}}px;background:{{bgColor}};{{bgImage?'background-image:url(' + bgImage+')':''}}">
<view class="nav-action nav-border-custom" wx:if="{{isCustom}}"
style="width:{{Custom.width}}px;height:{{Custom.height}}px;margin-left:calc(750rpx - {{Custom.right}}px)">
<van-icon class="nav-back" name="arrow-left" size="20px" color="{{backColor}}" bindtap="onClickBack" />
<van-icon class="nav-home" name="wap-home" size="20px" color="{{homeColor}}" bindtap="onClickHome" />
</view>
<view class="nav-action" bindtap="onClickBack" wx:else if="{{isBack}}">
<van-icon class="nav-back" name="arrow-left" size="20px" color="{{backColor}}" />
<view class="nav-backText" style="color:{{backColor}};">{{backText}}</view>
</view>
<view class="nav-content" style="top:{{StatusBar}}px;color:{{titleColor}};">