全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Bootstrap滚动监听组件scrollspy.js使用方法详解

其实滚动监听使用的情况还是很多的,比如导航居于右侧,当主题内容滚动某一块的时候,右侧导航对应的要高亮。

实现功能

1、当滚动区域内设置的hashkey距离顶点到有效位置时,就关联设置其导航上的指定项
2、导航必须是 .nav > li > a 结构,并且a上href或data-target要绑定hashkey
3、菜单上必须有.nav样式
4、滚动区域的data-target与导航父级Id(一定是父级)要一致。

<div id="selector" class="navbar navbar-default"> 
<ul class="nav navbar-nav"> 
<li><a href="#one">one</a> </li> 
<li><a href="#two">two</a> </li> 
<li><a href="#three">three</a> </li> 
</ul>
</div>
<div data-spy="scroll" data-target="#selector" style="height:100px; overflow:hidden;overflow-y: auto;" > 
<h4 id="one" >ibe</h4><p>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/></p> 
<h4 id="two" >two</h4><p>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/></p> 
<h4 id="three" >three</h4><p>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/>One的具体内容<br/></p>
</div>

下面来看一下实现的具体代码,原理:当滚动容器内的hashkey位置距离容器顶部只有 offset设置的值,就会设置导航中对应的href高亮。

ScrollSpy构造函数

首先新建一个构造函数,如下:

function ScrollSpy(element, options) {
  this.$body     = $(document.body)
  this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
  this.options    = $.extend({}, ScrollSpy.DEFAULTS, options)
  this.selector    = (this.options.target || '') + ' .nav li > a'
  this.offsets    = []
  this.targets    = []
  this.activeTarget  = null
  this.scrollHeight  = 0
  this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
  this.refresh()
  this.process()
 }

该构造函数主要干了啥:

1.基本设置,主要是设置当前滚动元素是设置的body还是具体的某一块元素;其次是导航的结构要是.nav li > a的结构,也就是你的菜单中也要有.nav这个class。

2.监听元素滚动的时候,执行process方法。

3.同时初始化的时候也执行了refresh与process方法。

下面讲解一下这几个方法。

getScrolHeight方法

获取滚动容器的内容高度(包含被隐藏部分)

this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)

refresh方法

刷新并存储滚动容器内各hashkey的值

ScrollSpy.prototype.refresh = function () {
  var that     = this
  var offsetMethod = 'offset'
  var offsetBase  = 0

  this.offsets   = []
  this.targets   = []
  this.scrollHeight = this.getScrollHeight()

  if (!$.isWindow(this.$scrollElement[0])) {
   offsetMethod = 'position'
   offsetBase  = this.$scrollElement.scrollTop()
  }

  this.$body
   .find(this.selector)
   .map(function () {
    var $el  = $(this)
    var href = $el.data('target') || $el.attr('href')
    var $href = /^#./.test(href) && $(href)
    
    return ($href
     && $href.length
     && $href.is(':visible')
     && [[$href[offsetMethod]().top + offsetBase, href]]) || null
   })
   .sort(function (a, b) { return a[0] - b[0] })
   .each(function () {
    that.offsets.push(this[0])
    that.targets.push(this[1])
   })

 }

它主要实现了什么呢?

1.默认用offset来获取定位值,如果滚动区域不是window则用position来获取

if (!$.isWindow(this.$scrollElement[0])) {
   offsetMethod = 'position'
   offsetBase  = this.$scrollElement.scrollTop()
  }

2.根据导航上的hashkey来遍历获取 滚动区域内的hashkey对应的offset值:

this.$body
   .find(this.selector)
   .map(function () {
    var $el  = $(this)
    var href = $el.data('target') || $el.attr('href')
    var $href = /^#./.test(href) && $(href)
    
    return ($href
     && $href.length
     && $href.is(':visible')
     && [[$href[offsetMethod]().top + offsetBase, href]]) || null
   })
   .sort(function (a, b) { return a[0] - b[0] })
   .each(function () {
    that.offsets.push(this[0])
    that.targets.push(this[1])
   })

process方法

滚动条事件触发函数,用于计算当前需要高亮那个导航菜单

ScrollSpy.prototype.process = function () {
  var scrollTop  = this.$scrollElement.scrollTop() + this.options.offset
  var scrollHeight = this.getScrollHeight()
  var maxScroll  = this.options.offset + scrollHeight - this.$scrollElement.height()
  var offsets   = this.offsets
  var targets   = this.targets
  var activeTarget = this.activeTarget
  var i

  if (this.scrollHeight != scrollHeight) {
   this.refresh()
  }

  if (scrollTop >= maxScroll) {
   return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
  }

  if (activeTarget && scrollTop < offsets[0]) {
   this.activeTarget = null
   return this.clear()
  }

  for (i = offsets.length; i--;) {
   activeTarget != targets[i]
    && scrollTop >= offsets[i]
    && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
    && this.activate(targets[i])
  }
 }

主要作用:

1.获取滚动容器已滚动距离:

var scrollTop  = this.$scrollElement.scrollTop() + this.options.offset

2.滚动容器可以滚动的最大高度:

var maxScroll  = this.options.offset + scrollHeight - this.$scrollElement.height()

3.设置滚动元素逻辑,给当前匹配元素添加高亮:

for (i = offsets.length; i--;) {
   activeTarget != targets[i]
    && scrollTop >= offsets[i]
    && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
    && this.activate(targets[i])
  }

active方法

设置指定的导航菜单高亮

ScrollSpy.prototype.activate = function (target) {
  this.activeTarget = target

  this.clear()

  var selector = this.selector +
   '[data-target="' + target + '"],' +
   this.selector + '[href="' + target + '" rel="external nofollow" rel="external nofollow" ]'

  var active = $(selector)
   .parents('li')
   .addClass('active')

  if (active.parent('.dropdown-menu').length) {
   active = active
    .closest('li.dropdown')
    .addClass('active')
  }

  active.trigger('activate.bs.scrollspy')
 }

clear方法

清除所有高亮菜单

ScrollSpy.prototype.clear = function () {
  $(this.selector)
   .parentsUntil(this.options.target, '.active')
   .removeClass('active')
 }

 源码

+function ($) {
 'use strict';

 // SCROLLSPY CLASS DEFINITION
 // ==========================

 function ScrollSpy(element, options) {
  this.$body     = $(document.body)
  this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
  this.options    = $.extend({}, ScrollSpy.DEFAULTS, options)
  this.selector    = (this.options.target || '') + ' .nav li > a'
  this.offsets    = []
  this.targets    = []
  this.activeTarget  = null
  this.scrollHeight  = 0
  this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
  this.refresh()
  this.process()
 }

 ScrollSpy.VERSION = '3.3.7'

 ScrollSpy.DEFAULTS = {
  offset: 10
 }

 ScrollSpy.prototype.getScrollHeight = function () {
  return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
 }

 ScrollSpy.prototype.refresh = function () {
  var that     = this
  var offsetMethod = 'offset'
  var offsetBase  = 0

  this.offsets   = []
  this.targets   = []
  this.scrollHeight = this.getScrollHeight()

  if (!$.isWindow(this.$scrollElement[0])) {
   offsetMethod = 'position'
   offsetBase  = this.$scrollElement.scrollTop()
  }

  this.$body
   .find(this.selector)
   .map(function () {
    var $el  = $(this)
    var href = $el.data('target') || $el.attr('href')
    var $href = /^#./.test(href) && $(href)
    
    return ($href
     && $href.length
     && $href.is(':visible')
     && [[$href[offsetMethod]().top + offsetBase, href]]) || null
   })
   .sort(function (a, b) { return a[0] - b[0] })
   .each(function () {
    that.offsets.push(this[0])
    that.targets.push(this[1])
   })

 }

 ScrollSpy.prototype.process = function () {
  var scrollTop  = this.$scrollElement.scrollTop() + this.options.offset
  var scrollHeight = this.getScrollHeight()
  var maxScroll  = this.options.offset + scrollHeight - this.$scrollElement.height()
  var offsets   = this.offsets
  var targets   = this.targets
  var activeTarget = this.activeTarget
  var i

  if (this.scrollHeight != scrollHeight) {
   this.refresh()
  }

  if (scrollTop >= maxScroll) {
   return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
  }

  if (activeTarget && scrollTop < offsets[0]) {
   this.activeTarget = null
   return this.clear()
  }

  for (i = offsets.length; i--;) {
   activeTarget != targets[i]
    && scrollTop >= offsets[i]
    && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
    && this.activate(targets[i])
  }
 }

 ScrollSpy.prototype.activate = function (target) {
  this.activeTarget = target

  this.clear()

  var selector = this.selector +
   '[data-target="' + target + '"],' +
   this.selector + '[href="' + target + '" rel="external nofollow" rel="external nofollow" ]'

  var active = $(selector)
   .parents('li')
   .addClass('active')

  if (active.parent('.dropdown-menu').length) {
   active = active
    .closest('li.dropdown')
    .addClass('active')
  }

  active.trigger('activate.bs.scrollspy')
 }

 ScrollSpy.prototype.clear = function () {
  $(this.selector)
   .parentsUntil(this.options.target, '.active')
   .removeClass('active')
 }


 // SCROLLSPY PLUGIN DEFINITION
 // ===========================

 function Plugin(option) {
  return this.each(function () {
   var $this  = $(this)
   var data  = $this.data('bs.scrollspy')
   var options = typeof option == 'object' && option

   if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
   if (typeof option == 'string') data[option]()
  })
 }

 var old = $.fn.scrollspy

 $.fn.scrollspy       = Plugin
 $.fn.scrollspy.Constructor = ScrollSpy


 // SCROLLSPY NO CONFLICT
 // =====================

 $.fn.scrollspy.noConflict = function () {
  $.fn.scrollspy = old
  return this
 }


 // SCROLLSPY DATA-API
 // ==================

 $(window).on('load.bs.scrollspy.data-api', function () {
  $('[data-spy="scroll"]').each(function () {
   var $spy = $(this)
   Plugin.call($spy, $spy.data())
  })
 })

}(jQuery);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Bootstrap  # 滚动监听  # scrollspy.js  # bootstrap监听滚动实现头部跟随滚动  # BootStrap下拉菜单和滚动监听插件实现代码  # 学习Bootstrap滚动监听 附调用方法  # 全面解析Bootstrap中scrollspy(滚动监听)的使用方法  # Bootstrap教程JS插件滚动监听学习笔记分享  # Bootstrap滚动监听(Scrollspy)插件详解  # Bootstrap每天必学之滚动监听  # Bootstrap+Vue滑动监听Scrollspy实现餐厅餐品展示  # 具体内容  # 容器内  # 就会  # 要有  # 遍历  # 什么呢  # 中也  # 干了  # 这几个  # 绑定  # 点到  # 大家多多  # 新建一个  # 则用  # 主要是  # 滚动条  # 实现了  # API  # offset  # load 


相关文章: SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  临沂网站制作企业,临沂第三中学官方网站?  如何在Golang中使用replace替换模块_指定本地或远程路径  图册素材网站设计制作软件,图册的导出方式有几种?  制作网站的软件免费下载,免费制作app哪个平台好?  天河区网站制作公司,广州天河区如何办理身份证?需要什么资料有预约的网站吗?  制作营销网站公司,淘特是干什么用的?  如何在阿里云香港服务器快速搭建网站?  已有域名如何快速搭建专属网站?  建站主机类型有哪些?如何正确选型  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  网站制作网站,深圳做网站哪家比较好?  正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?  如何在云服务器上快速搭建个人网站?  如何在腾讯云服务器上快速搭建个人网站?  高性能网站服务器部署指南:稳定运行与安全配置优化方案  高防服务器租用指南:配置选择与快速部署攻略  建站主机服务器选购指南:轻量应用与VPS配置解析  股票网站制作软件,网上股票怎么开户?  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  建站OpenVZ教程与优化策略:配置指南与性能提升  c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗  专业的网站制作设计是什么,如何制作一个企业网站,建设网站的基本步骤有哪些?  深圳 网站制作,深圳招聘网站哪个比较好一点啊?  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  建站之星如何配置系统实现高效建站?  如何在腾讯云服务器快速搭建个人网站?  孙琪峥织梦建站教程如何优化数据库安全?  建站之星后台密码如何安全设置与找回?  西安大型网站制作公司,西安招聘网站最好的是哪个?  广州美橙建站如何快速搭建多端合一网站?  建站之星安装需要哪些步骤及注意事项?  如何快速生成可下载的建站源码工具?  黑客如何利用漏洞与弱口令入侵网站服务器?  建站之星代理如何优化在线客服效率?  建站之星如何助力企业快速打造五合一网站?  个人摄影网站制作流程,摄影爱好者都去什么网站?  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  如何在阿里云虚拟服务器快速搭建网站?  可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?  网站制作说明怎么写,简述网页设计的流程并说明原因?  重庆市网站制作公司,重庆招聘网站哪个好?  小建面朝正北,A点实际方位是否存在偏差?  济南专业网站制作公司,济南信息工程学校怎么样?  高防服务器:AI智能防御DDoS攻击与数据安全保障  如何在IIS中新建站点并解决端口绑定冲突?  如何在IIS管理器中快速创建并配置网站?  实例解析angularjs的filter过滤器  常州自助建站费用包含哪些项目? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。