微信小程序-导航吸顶+view锚点

导航栏滑动定位+view锚点

我们在做小程序的时候,难免会遇到页面里面有很长的数据,页面下面又有到导航栏部分;用户希望页面滑动到导航栏的位置,导航栏固定在页面的最上面,同时里面的数变化,也能改变导航栏的高亮。

效果图

图1:
在这里插入图片描述
图2:
在这里插入图片描述
图3:
在这里插入图片描述

实现原理

通过对scroll的监听获取滚动条的scrollTop值;
在导航的下子集class判断距离整个页面Top;
切换position:fixed与position:relative。

WXML

我是使用自定义组件来写的
在这里插入图片描述


<rui-sticky scroll="{{curNodes}}" bindstickyscroll="getScrollTop">
  <view slot="stickychild">
    <view class='flex-row border_b mar-t bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list1</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <view class='flex-row border_b  bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list2</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <view class='flex-row border_b  bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list3</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <view class='flex-row border_b  bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list4</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <view class='flex-row border_b  bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list5</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <view class='flex-row border_b  bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list6</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <view class='flex-row border_b  bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list7</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <view class='flex-row border_b  bg_white uinn'>
      <view class='flex1 flex-row'>
        <view class='s_width1 colorTitle'>list8</view>
        <input type='text' class='flex1' value='' disabled='true' />
      </view>
    </view>
    <!-- 导航栏组件 -->
    <rui-content navcur='{{navcur}}' bind:compontpass="compontpass" bind:myevent='myevent'> </rui-content>
  </view>
</rui-sticky>

WXSS主页面

//所有的css
.rui-flex-content {
  display: -webkit-flex;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.rui-nav-flex {
  background-color: #fff;
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 1000;
}

.rui-goods-content {
  padding-top: 4vw;
}

.rui-nav-li text {
  display: -webkit-flex;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #969799;
  border-bottom: 4px solid #fff;
}

.rui-nav-li {
  font-size: 30rpx;
  display: -webkit-flex;
  display: flex;
  justify-content: center;
  flex: 0 0 auto;
  width: 25%;
  height: 88rpx;
}

.rui-nav-li.rui-active text {
  font-size: 30rpx;
  color: #323233;
  border-bottom: 4px solid #7a6cf9;
}

.rui-flex-li {
  width: 100%;
  margin: 0 0 4vw 0;
}

.rui-flex-li:last-child {
  width: 100%;
  margin: 0 0 128rpx 0;
}

.imgline {
  width: 100%;
  height: 400rpx;
}

.imgline image {
  width: 100%;
  height: 100%;
}

/* .rui-flex-li view {
  height: 45rpx;
  line-height: 45rpx;
  color: #000;
} */

.bacred {
  padding: 20rpx 0;
  background: #fff;
  border-radius: 4px;
}

.vertical {
  float: left;
  display: block;
  width: 8rpx;
  height: 30rpx;
  margin: 10rpx auto;
  background: linear-gradient(360deg, rgba(139, 115, 250, 1) 0%, rgba(122, 108, 249, 1) 100%);
  border-radius: 4px;
}

.vertical_tit {
  font-weight: 500;
  font-size: 32rpx;
  color: #9970ed;
  margin-left: 10rpx;
  height: 45rpx;
  line-height: 45rpx;
  float: left;
  display: block;
}

.ovh {
  overflow: hidden;
}

.liucheng {
  position: relative;
  width: 100%;
  border: 1px solid #969799;
}

.liucheng image {
  width: 100%;
  height: 100%;
}

.fullscreen {
  text-align: center;
  position: absolute;
  bottom: 20rpx;
  right: 20rpx;
  width: 104rpx;
  height: 52rpx;
  line-height: 52rpx;
  background: rgba(255, 255, 255, 1);
  border-radius: 26px;
  border: 1px solid rgba(220, 222, 227, 1);
  color: #333;
  font-size: 28rpx;
}

.uinn {
  padding: 20rpx;
}

.footsubmit {
  z-index: 999999;
  background-color: #fff;
  width: 100%;
  position: fixed;
  bottom: 0px;
  box-shadow:0px -2px 10px 0px rgba(239,239,239,0.5);
}

.succ_btn {
  
  margin-top: 0rpx;
  margin-bottom: 20rpx;
  background-color: #9970ed;
  color: white;
  font-size: 36rpx;
}
.notavailable{
  color: #969799;
  font-size: 30rpx;
}
/* upload */
.flex25{
  width: 25%;
  word-wrap:break-word;
  word-break:break-all;
}
.border-radius{
  border-radius: 6rpx;
}
.bg_eb{
  background-color: #EBEBEB;
}
.lineh{
  line-height: 50rpx;
}
.exceptionimgbox{
  width: 140rpx;
  height: 140rpx;
  margin: auto;
  vertical-align: middle;
  position: relative;
}
.exceptionimgbox .add{
  width: 30%;
  height: 100%;
  display: block;
  margin: auto;
}
.exceptionimgbox image,.exceptionimgbox video{
  width: 100%;
  height: 100%;
  display: block;
}
.exceptionimgbox image.delimg{
  position: absolute;
  right: -10rpx;
  top: -10rpx;
  width: 40rpx;
  height: 40rpx;
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.3);
  z-index: 999;
}

.dingwei{
  width: 40rpx;
  height: 40rpx;
}
.xline{
  text-decoration: underline;
}

.exceptionimgbox icon{
  position: absolute;
  top: 36%;
  left: 36%;
}
.flex-rows{
  -webkit-display:flex;
  display:flex;
  flex-direction: row;
  flex-wrap: wrap;
  -webkit-align-items:center;
  align-items:center;
  /* -webkit-justify-content:center;
  justify-content:center; */
}
/* sticky */
.rui-sticky-content{
  height: 100%;
}

JS-主页面

var main = require('../../utils/util.js');
Page({

  /**
   * 页面的初始数据
   */
  data: {
    // scroll_height:0,
    navcur: 0,
    curNodes: 0,
    // navlist: ['历史意见', '协同意见', '相关附件', '流程图'],
  },
  //父组件接收子组件传值
  compontpass(val) {
    var self=this
    self.setData({
      navcur: val.detail.navcur,
      curNodes: val.detail.curNodes
    })
  },
   //父组件接收子组件传值
  myevent(res){
    var self=this
    self.setData({
      tops: res.detail
    })
  },
  getScrollTop(e) {
    // console.log('getScrollTop----',e)
    var self = this;
    let scrollTop = e.detail.current.detail.scrollTop;
    let navcur = parseInt(self.data.navcur);
    let min = self.data.tops[navcur].top;
    let max = self.data.tops[navcur + 1] ? self.data.tops[navcur + 1].top : self.data.tops[navcur].top;
    if (max - 56 < scrollTop && navcur < self.data.tops.length - 1) {
      navcur++
    } else if (min - 56 > scrollTop && navcur > 0) {
      navcur--
    }
    self.setData({
      navcur: navcur
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {},

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {
  },


  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage(opts) {
  },
})

JS-主页面

{
  "usingComponents": {
    "rui-sticky": "../../../component/sticky/sticky",
    "rui-content": "../../../component/newcontent/newcontent"
  }
}

子页面-newcontent

wxml:

<!-- 导航栏 -->
<view class="rui-flex-content rui-nav-flex">
  <view bindtap="getNavIndex" data-index="{{index}}" class='rui-nav-li {{navcur==index ? "rui-active" : ""}} ' wx:for="{{navlist}}" wx:key="navlist">
    <text>{{item}}</text>
  </view>
</view>
<view class=" rui-flex-content rui-goods-content uinn">
  <view class='rui-flex-li rui-goods-nodes bacred '>
    <view class="ovh">
      <text class="vertical"></text>
      <text class="vertical_tit">示例1</text>
    </view>
    <view class="uinn">
      <view class="notavailable">示例1-暂无数据</view>
     
    </view>
  </view>
  <view class='rui-flex-li rui-goods-nodes bacred '>
    <view class="ovh">
      <text class="vertical"></text>
      <text class="vertical_tit">示例2</text>
    </view>
    <view class="uinn">
      <view class="notavailable">示例2-暂无数据</view>
    </view>
  </view>
  <view class='rui-flex-li rui-goods-nodes bacred '>
    <view class="ovh">
      <text class="vertical"></text>
      <text class="vertical_tit">上传图片</text>
    </view>
    <view class="uinn">
      <rui-uploadfile bind:onload='onload'> 上传图片</rui-uploadfile>
    </view>
  </view>
  <view class='rui-flex-li rui-goods-nodes bacred '>
    <view class="ovh">
      <text class="vertical"></text>
      <text class="vertical_tit">效果图</text>
    </view>
    <view class="uinn">
      <view class="liucheng" style='height:{{scroll_height}}rpx; ' data-scroll_height="{{scroll_height}}">
        <image src="{{imgUrl}}"></image>
        <!-- <text class="fullscreen" catchtap='previewphoto'>全屏</text> -->
      </view>
    </view>
  </view>
</view>

wxss:

@import  "../../utils/pulic.wxss";

js:

var app = getApp().globalData;
Component({
  externalClasses: ['rui-class'],

  options: {
    multipleSlots: true
  },
  
  properties: {
   //导航index值
    navcur: {
      type: Number,
      value: 0
    },
    //效果图的高度
    scroll_height: {
      type: Number,
      value: 0
    },
  },
  data: {
    navcur: 0,
    curNodes: 0,
    navlist: ['示例1', '示例2', '上传图片', '效果图'],
    imgUrl:'../../src/images/liu.jpg'
  },
  methods: {
   onload(rect){
     var self = this
     const query = wx.createSelectorQuery().in(this);
     query.selectAll('.rui-goods-nodes').boundingClientRect((res) => {
      //  console.log(res)
       self.setData({
         tops: res,
       });
       self.triggerEvent('myevent', res) 
     }).exec()
   },
    getNavIndex(e) {
      var self = this;
      let index = e.currentTarget.dataset.index;
      if (self.data.navcur == index) {
        return false
      }
      self.setData({
        navcur: index,
        curNodes: self.data.tops[index].top - 55
      })
      //nav--index;curNodes---距离页面的top
      var curNodesNum = {
        navcur: self.data.navcur,
        curNodes: self.data.curNodes
      }
      self.triggerEvent("compontpass", curNodesNum)
    },
  },
  ready: function () {
    var self = this
    const query = wx.createSelectorQuery().in(this);
    query.selectAll('.rui-goods-nodes').boundingClientRect((res) => {
      self.setData({
        tops: res,
      });
      self.triggerEvent('myevent', res) 
    }).exec()
    let windowHeight = wx.getSystemInfoSync().windowHeight 
    let windowWidth = wx.getSystemInfoSync().windowWidth 
    self.setData({
      scroll_height: (windowHeight * 750 / windowWidth) - 280
    })
  }
})

json:

{
  "component": true,
  "usingComponents": {}
}

子页面-sticky

wxml:

<scroll-view class="rui-sticky-content rui-class" bindscroll="getScrollTop" scroll-y="true"   scroll-top="{{scroll}}">
  <slot name="stickychild"></slot>
</scroll-view>

wxss:

@import  "../../utils/pulic.wxss";

js:

Component({
  externalClasses: ['rui-class'],

  options: {
    multipleSlots: true
  },
  properties: {
    scroll: {
      type: Number,
      value: 0
    }
  },

  methods: {
    getScrollTop(e){
      this.triggerEvent('stickyscroll', { current: e }, {});
    }
  }
})

json:

{
  "component": true,
  "usingComponents": {}
}

子页面-uploadfile

wxml:

<view class='bg_white border-a border-radius mar-t'>
  <view class='uinn'>
    <text>上传图片</text>
    <text class='color_red'>(最少上传一张图片,最多十张)</text>
  </view>
  <view class='uinn flex-rows border_b border_t'>
    <view class='flex25 mar-b' wx:for='{{photoList}}' wx:for-index='idx' wx:for-item='items' wx:key='index'>
      <view class='exceptionimgbox bg_eb' hover-class='opacity' data-index="{{idx}}" catchtap='previewphoto'>
        <image src='{{items}}'></image>
        <image src='../../src/images/del.png' class='delimg' catchtap='delphoto' data-index="{{idx}}"></image>
      </view>
    </view>
    <view class='flex25 mar-b'>
      <view class='exceptionimgbox bg_eb' hover-class='opacity' bindtap='chooseimg'>
        <image src='../../src/images/add.png' mode="aspectFit" class='add'></image>
      </view>
    </view>

  </view>
</view>

wxss:

@import  "../../utils/pulic.wxss";

js:

var main = require("../../utils/util.js");
var app = getApp().globalData;
Component({

  options: {
    multipleSlots: true
  },
  properties: {},
  data: {
    code: '',
    photoNum: 10, //照片数量
    photoList: [], //照片数组
    photoindex: 'none', //照片当前位置  
  },
  methods: {
    chooseimg: function(e) {
      var self = this;
      if (self.data.photoNum <= 0) {
        main.showToast('还能选择' + self.data.photoNum + '张照片');
        return;
      }
      wx.chooseImage({
        count: self.data.photoNum,
        success(res) {
          const tempFilePaths = res.tempFilePaths
          if (res.tempFiles[0].size >= 10000000) {
            main.showToast('图片大小超过10M');
            return;
          }
          var len = res.tempFilePaths.length
          self.setData({
            photoNum: self.data.photoNum - len,
            photoList: self.data.photoList.concat(tempFilePaths)
          })
          self.triggerEvent("onload", {flag:true})
        }
      })
    },
    delphoto: function(e) {
      var self = this;
      var photolist = self.data.photoList;
      var photindex = Number(e.currentTarget.dataset.index);
      main.showModal('提示', '是否确认删除?', true, function(res) {
        if (res.confirm) {
          photolist.splice(photindex, 1);
          self.setData({
            photoList: photolist,
            photoNum: 10 - photolist.length,
            photoindex: 'none'
          });
        } else {
          self.setData({
            photoindex: 'none'
          })
        }
      })
    },
    
  }
})

  methods: {
    getScrollTop(e){
      this.triggerEvent('stickyscroll', { current: e }, {});
    }
  }
})

json:

{
  "component": true,
  "usingComponents": {}
}

如果有感兴趣,可以去我的 https://download.csdn.net/my. 下载

这里注意一下:在上传功能上有改变导航栏里面的高度,这时候要重新获取一次导航栏下子元素的高度。——这是我遇到的坑,与大家共勉一下,希望大家代码之路都能避坑,一路顺畅

发布了5 篇原创文章 · 获赞 1 · 访问量 496

猜你喜欢

转载自blog.csdn.net/weixin_41539046/article/details/105455252