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 switch开关组件使用方法详解
-
Bootstrap滚动监听组件scrollspy.js使用方法详解
-
bootstrap switch开关组件使用方法详解
-
Bootstrap图片轮播组件Carousel使用方法详解
-
JS组件Bootstrap Select2使用方法详解_javascript技巧
-
Bootstrap图片轮播组件Carousel使用方法详解
-
JS组件Bootstrap Table使用方法详解_javascript技巧
-
JS组件Bootstrap导航条使用方法详解_javascript技巧
-
JS组件Bootstrap Select2使用方法详解_javascript技巧