关于小程序:小程序导航栏悬浮切换导航栏滚动页面滚动页面切换导航栏

6次阅读

共计 4483 个字符,预计需要花费 12 分钟才能阅读完成。

前言

很多小程序、app 都有这种设计:

成果 1. 将导航栏固定在页面顶部。

成果 2. 点击导航栏,页面主动滚动到对应内容地位。

成果 3. 滚动页面主动切换至对应导航栏

成果演示:

代码:
wxml

<!-- 导航栏 -->
<view class="topView">
  <scroll-view class="tabs" scroll-x="true" scroll-with-animation='true' scroll-into-view="x{{xId}}">
    <view class="tab {{xId==item.id?'greenColor':''}}"wx:for="{{list}}"wx:key="item"data-id="{{item.id}}"catchtap="changeTab"id="x{{item.id}}">
      <view class="tab_text">{{item.title}}</view>
      <view class="tab_line {{xId==item.id?'greenBg':''}}"></view>
    </view>
  </scroll-view>
</view>

<view style="height:80rpx"></view>

<!-- 滚动内容 -->
<scroll-view class="columns" scroll-y="true" scroll-with-animation='true' scroll-into-view="f{{yId}}"
  style='height:{{height}}rpx;' bindscroll="scrollFloor">
  <view class="column" wx:for="{{list}}" wx:key="item" id="f{{item.id}}">
    <view class="column_title">{{item.title}}</view>
    <view class="column_imgs">
      <view class="img_div" wx:for="{{item.photo}}" wx:for-item="items" wx:key="items">
        <image src="{{items}}" mode="aspectFill"></image>
      </view>
      <view class="img_div" wx:if="{{item.photo.length>7}}">
        <view class="showMore"> 点击查看更多 </view>
      </view>
    </view>
  </view>
  <view style="height:200rpx"></view>
</scroll-view>

属性解释:

scroll-x=”true”:容许横向滚动, 反之 scroll-y=”true” 容许纵向滚动。

scroll-with-animation:在设置滚动条地位时是否应用动画过渡。

scroll-into-view:滚动到哪个元素(值应为某子元素 id【id 不能以数字结尾】, 例如本文的:id=”x{{item.id}}” 或 id=”f{{item.id}}” 设置哪个方向可滚动,则在哪个方向滚动到该元素)。

bindscroll:内容滚动时触发的事件。

wxss

.greenColor {color: rgb(59 185 80);
}

.greenBg {background-color: rgb(59 185 80);
}

.topView {
  position: fixed;
  top:0rpx;
  left:0rpx;
  z-index:999;
  width:100%;
  background-color: #fff;
  height: 80rpx;
}

/* 导航 tab */
.tabs {
  white-space: nowrap;
  padding-left: 32rpx;
  width: 100%;
  overflow: hidden;
}

/* 暗藏 scroll-view 页面滚动条 */
::webkit-scrollbar {
  width: 0;
  height: 0;
  color: #fff;
  display: none;
}

.tabs .tab {
  display: inline-block;
  padding-right: 50rpx;
}

.tab_text {
  height: 50rpx;
  line-height: 50rpx;
  padding-bottom: 10rpx;
}

.tab_line {
  margin: 0 auto;
  width: 30rpx;
  height: 5rpx;
}

/* 滚动内容 */
.column {
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;
}

.column .column_title {padding: 40rpx 32rpx 0rpx 32rpx;}

.column .column_imgs {
  padding: 0 28rpx;
  overflow: hidden;
  margin-top: 15rpx;

}

.column_imgs .img_div {
  width: 230rpx;
  height: 190rpx;
  padding: 7rpx 7rpx;
  box-sizing: border-box;
  float: left;
  display: -webkit-flex;
  -webkit-flex-wrap: nowrap;
  flex-wrap: nowrap;
}

.column_imgs .img_div image {
  width: 100%;
  height: 100%;
  background: #b5b5b5;
}

.column_imgs .img_div .showMore {
  width: 100%;
  height: 100%;
  background: #f3f5f8;
  line-height: 190rpx;
  text-align: center;
  font-size: 28rpx;
  color: #0f0d6b;
}

js

Page({
  data: {
    height: 0,         // 页面高度 rpx
    ratio: 0,          //rpx,px 转化比
    xId: 1,           // x 轴选中项
    yId: 1,           // y 轴滚动地位
    heightArray: [],
    list: [{
        id: 1,
        title: "特色",
        photo: [
          "图片 url",
          "图片 url",
          "图片 url"        ],
      },
      {
        id: 2,
        title: "楼盘",
        photo: [
          "图片 url",
          "图片 url"
        ],
      },
      {
        id: 3,
        title: "样板房",
        photo: [
          "图片 url",
          "图片 url"
        ],
      },
      {
        id: 4,
        title: "周边配套",
        photo: [
          "图片 url",
          ""
        ],
      },
      {
        id: 5,
        title: "售楼处",
        photo: [
          "图片 url",
          "图片 url"
        ],
      },
      {
        id: 6,
        title: "楼盘证件",
        photo: [
          "t 图片 url",
          "图片 url"
        ],
      },
    ]
  },

  onLoad: function (options) {
    let that = this
    wx.setNavigationBarTitle({title: '相册页'})
    //1. 获取页面高度
    wx.getSystemInfo({success: function (res) {
        let width = res.windowWidth
        let ratio = 750 / width
        let height = ratio * res.windowHeight
        that.setData({
          height: height, // 单位 rpx
          ratio: ratio
        })
      }
    })
  },

  onShow: function () {
    let that = this,
      heightArray = [];
    //1. 获取滚动元素间隔顶部地位 -y
    setTimeout(function () {let query = wx.createSelectorQuery() // 创立节点查询器
      query.selectAll('.column').boundingClientRect(function (rect) {rect.forEach(function (value) {heightArray.push((value.top - (170 / that.data.ratio)))
        })
        that.setData({heightArray})
      }).exec()}, 1000) // 此处最好用延时,否则获取的后果有可能是 null,也有可能值不精确。},
// 切换 tab 导航栏
  changeTab: function (e) {
    let that = this
    let id = e.currentTarget.dataset.id
    that.setData({
      xId:id,
      yId:id,
    })
  },

  // 监听滚动 切换 tab
  scrollFloor: function (e) {
    var that = this
    var scrollTop = e.detail.scrollTop // 滚动条间隔顶部
    var heightArray = that.data.heightArray // 滚动项间隔顶部
    var id = null
    // 计算比拟得出下标
    for (let i = 0; i <= heightArray.length; i++) {if (scrollTop >= heightArray[i] - 90 && scrollTop < heightArray[i + 1]) {id = that.data.list[i].id
      }
    }
    that.setData({xId: id})
  },
})

思路

成果 1 导航栏悬浮:
父盒子 class=”topView” 包裹 scroll-view 导航栏,父盒子款式属性
.topView {
position: fixed;
top:0rpx;
left:0rpx;
z-index:999;
width:100%;
background-color: #fff;
height: 80rpx;
}
留神:
1.z-index 进步层级,防止被滚动内容笼罩。
2. 宽度肯定要设置,不然会顶部 tab 栏将无奈左右滑动。
3.scroll-view 组件应用:white-space: nowrap;overflow: hidden; 并且其子元素设置:display: inline-block;

成果 2 点击导航栏,页面主动滚动到对应内容地位:

导航栏绑定点击事件 changeTab, 并通过 data-id 把以后 tab 的元素的 id 值传给事件,扭转 xId(导航栏选中项)和 yId(滚动内容选中项)的值。

成果 3 滚动页面主动切换至对应导航栏:

1、页面 onLoad 时获取页面高度并赋值给 scroll-view 的 style:height 款式属性。
2、onShow 时获取 scroll-view 内子元素间隔顶部间隔并顺次保留在 heightArray 数组中。
3、页面滚动触发 scrollFloor 事件,获取 scroll-view 整个滚动框间隔顶部的间隔 scrollTop,遍历 heightArray,如果 scrollTop 介于 heightArray[i]和 heightArray[i+1]之间,则阐明页面曾经滚动至 i 元素,把 i 元素的 id 赋值给 xId。

小结
以上便是我对这个性能的了解跟实现办法,代码均已给出,各位同学有疑难或者有其余解决方案,欢送沟通探讨!!!

正文完
 0