自定义navigation
隐藏页面自带的navigation
自定义组件我们需要将页面的json配置navigationStyle设为custom
json
{
"navigationBarTitleText": "首页",
"navigationStyle": "custom"
}
封装组件 custom-nav
计算navigation高度和胶囊按钮padding
自定义navigation需要知道两个主要信息,一个状态栏的高度,另一个是右上角微信自带的胶囊按钮,我们需要两个api查询到这两个信息,wx.getSystemInfoSync和wx.getMenuButtonBoundingClientRect
用这些信息我们可以计算出:
text
navigation高度 = systmemInfo.statusBarHeight + 44
胶囊右边界距离屏幕右边界距离 = systemInfo.windowWidth - menuBtnRect.right
js
const sysInfo = wx.getSystemInfoSync()
const menuBtnRect = wx.getMenuButtonBoundingClientRect()
this.navHeight = sysInfo.statusBarHeight + 44
this.menuBtnPadding = sysInfo.windowWidth - menuBtnRect.right
实现navigation title 居中和过长省略
为了防止title文本过长被胶囊按钮遮盖,思路是分为三栏,左右两栏最小宽度设为胶囊按钮的宽度,设为最小宽度是流程左侧的slot,宽度可能被实际内容撑开更长,同时右栏复制左栏,设置为隐藏
html
<view
class="custom-nav"
style="height: {{navHeight}}px; background-color: {{navBackgroundColor}};"
>
<view
class="custom-nav-content"
style="height: {{menuBtnRect.height}}px; margin-top: {{menuBtnRect.top}}px;"
>
<!--
左侧有两个目的:
1:left slot。
2:最小宽度样式复制menuBtn,以兼容title文字过长的省略打点演示。
-->
<view
class="custom-nav-left"
style="height: {{menuBtnRect.height}}px; min-width: {{menuBtnRect.width}}px; padding: 0 {{menuBtnPadding}}px; line-height: {{menuBtnRect.height}}px"
>
</view>
<view
class="custom-nav-title"
style="line-height: {{menuBtnRect.height}}px; color: {{titleColor}};"
>
{{title}}
</view>
<!-- menu btn 占位 -->
<!-- 复制一份nav left, 不展示, 保证 title 在中间 -->
<view
class="custom-nav-left"
style="height: {{menuBtnRect.height}}px; min-width: {{menuBtnRect.width}}px; padding: 0 {{menuBtnPadding}}px; line-height: {{menuBtnRect.height}}px; visibility: hidden;"
>
</view>
</view>
</view>
<!-- nav 占位 -->
<view class="custom-nav-placeholder" style="height: {{navHeight}}px;"></view>
动画
这里以常见的初始透明向下滚动渐变为纯白为例,实现分为两种情况,1. 使用页面的onPageScroll,2.在scroll-view
组件内使用
监听onPageScroll
首先要解决在组件内如何监听页面滚动事件,思路是使用getCurrentPages
接口获取当前页面实例,修改page.onPageScroll
js
// ....
attached: function () {
// 如果是默认 监听 page 滚动事件
if (!this.data.useScrollView) {
const pages = getCurrentPages()
const page = pages[pages.length - 1]
this._curPage = page
const _this = this
if (page !== null && page !== undefined) {
const pageScroll = page.onPageScroll
this._pageScroll = pageScroll
page.onPageScroll = function (e) {
if (typeof pageScroll === 'function') {
pageScroll.call(page, e)
}
_this.onScroll(e)
}
}
}
},
// 组件卸载时需要取消绑定的事件
detached: () => {
if (this.data.useScrollView) {
if (this._pageScroll) {
this._curPage.onPageScroll = this._pageScroll
} else if (this._curPage) {
this._curPage.onPageScroll = undefined
}
}
},
实现动画效果
js
onScroll: function(e) {
const scrollTop = e.scrollTop
const navHeight = this.navHeight
const oldNavOpacity = this.oldNavOpacity
const navOpacity = (scrollTop / navHeight).toFixed(2)
const oldTitleColor = this.data.titleColor
// 滚动过快
// 保留2位小数 相同不执行
if (scrollTop <= navHeight && oldNavOpacity !== navOpacity) {
this.oldNavOpacity = navOpacity
const newData = {
navBackgroundColor: `rgba(255, 255, 255, ${navOpacity})`
}
if (oldTitleColor !== '#fff') {
newData.titleColor = '#fff'
}
this.setData(newData)
} else if (scrollTop > navHeight) {
this.oldNavOpacity = 1
this.setData({
navBackgroundColor: `rgba(255, 255, 255, 1)`,
titleColor: '#333'
})
}
},
使用方式
html
<view id="index-wrapper">
<custom-nav
scroll-source="#index-wrapper"
title="设置设设置设设置设设置设设置设设置设设置设设置设设置设"
/>
<view>发射点发射点</view>
<view style="height: 1000px;"></view>
</view>
在scroll-view内使用
使用scroll-view
组件可以结合animate
, 实现性能更好的动画,组件用属性use-scroll-view
以区分页面滚动
js
ready: function () {
// scoll view animate
if (this.data.scrollSource && this.data.useScrollView) {
this.animate(
'.custom-nav',
[{
backgroundColor: 'rgba(255, 255, 255, 0)',
},
{
backgroundColor: 'rgba(255, 255, 255, 0.5)',
},
{
backgroundColor: 'rgba(255, 255, 255, 1)',
}],
2000,
{
scrollSource: this.data.scrollSource,
timeRange: 2000,
startScrollOffset: 0,
endScrollOffset: this.navHeight,
}
)
}
}
为知道何时滚动了navigation高度的距离,组件提供了一个方法
js
onScrollView: function (e) {
const scrollTop = e.detail.scrollTop
const curTitleColor = this.data.titleColor
const navHeight = this.navHeight
if (scrollTop < navHeight) {
if (curTitleColor !== '#fff') {
this.setData({titleColor: '#fff'})
}
} else if (curTitleColor === '#fff') {
this.setData({titleColor: '#333'})
}
}
使用时需要在页面通过this.selectComponent
获取组件实例,绑定scroll-view
组件的scroll方法触发
html
<scroll-view id="index-wrapper" scroll-y bindscroll="onScrollView">
<custom-nav
scroll-source="#index-wrapper"
title="设置设置设置设置设置设置设置设置设置设置设置设置设置设置设置"
use-scroll-view
id="custom-nav"
/>
</scroll-view>
js
Page({
onReady: function () {
this.customNavInt = this.selectComponent('#custom-nav')
},
onScrollView: function (e) {
const customNavInt = this.customNavInt
if (customNavInt) {
customNavInt.onScrollView(e)
}
}
})