Bootstrap滾動(dòng)監(jiān)聽組件scrollspy.js使用方法詳解
其實(shí)滾動(dòng)監(jiān)聽使用的情況還是很多的,比如導(dǎo)航居于右側(cè),當(dāng)主題內(nèi)容滾動(dòng)某一塊的時(shí)候,右側(cè)導(dǎo)航對(duì)應(yīng)的要高亮。
實(shí)現(xiàn)功能
1、當(dāng)滾動(dòng)區(qū)域內(nèi)設(shè)置的hashkey距離頂點(diǎn)到有效位置時(shí),就關(guān)聯(lián)設(shè)置其導(dǎo)航上的指定項(xiàng)
2、導(dǎo)航必須是 .nav > li > a 結(jié)構(gòu),并且a上href或data-target要綁定hashkey
3、菜單上必須有.nav樣式
4、滾動(dòng)區(qū)域的data-target與導(dǎo)航父級(jí)Id(一定是父級(jí))要一致。
<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的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/></p> <h4 id="two" >two</h4><p>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/></p> <h4 id="three" >three</h4><p>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/>One的具體內(nèi)容<br/></p> </div>
下面來(lái)看一下實(shí)現(xiàn)的具體代碼,原理:當(dāng)滾動(dòng)容器內(nèi)的hashkey位置距離容器頂部只有 offset設(shè)置的值,就會(huì)設(shè)置導(dǎo)航中對(duì)應(yīng)的href高亮。
ScrollSpy構(gòu)造函數(shù)
首先新建一個(gè)構(gòu)造函數(shù),如下:
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()
}
該構(gòu)造函數(shù)主要干了啥:
1.基本設(shè)置,主要是設(shè)置當(dāng)前滾動(dòng)元素是設(shè)置的body還是具體的某一塊元素;其次是導(dǎo)航的結(jié)構(gòu)要是.nav li > a的結(jié)構(gòu),也就是你的菜單中也要有.nav這個(gè)class。
2.監(jiān)聽元素滾動(dòng)的時(shí)候,執(zhí)行process方法。
3.同時(shí)初始化的時(shí)候也執(zhí)行了refresh與process方法。
下面講解一下這幾個(gè)方法。
getScrolHeight方法
獲取滾動(dòng)容器的內(nèi)容高度(包含被隱藏部分)
this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
refresh方法
刷新并存儲(chǔ)滾動(dòng)容器內(nèi)各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])
})
}
它主要實(shí)現(xiàn)了什么呢?
1.默認(rèn)用offset來(lái)獲取定位值,如果滾動(dòng)區(qū)域不是window則用position來(lái)獲取
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
2.根據(jù)導(dǎo)航上的hashkey來(lái)遍歷獲取 滾動(dòng)區(qū)域內(nèi)的hashkey對(duì)應(yīng)的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方法
滾動(dòng)條事件觸發(fā)函數(shù),用于計(jì)算當(dāng)前需要高亮那個(gè)導(dǎo)航菜單
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.獲取滾動(dòng)容器已滾動(dòng)距離:
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
2.滾動(dòng)容器可以滾動(dòng)的最大高度:
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
3.設(shè)置滾動(dòng)元素邏輯,給當(dāng)前匹配元素添加高亮:
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
&& this.activate(targets[i])
}
active方法
設(shè)置指定的導(dǎo)航菜單高亮
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);
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- bootstrap監(jiān)聽滾動(dòng)實(shí)現(xiàn)頭部跟隨滾動(dòng)
- BootStrap下拉菜單和滾動(dòng)監(jiān)聽插件實(shí)現(xiàn)代碼
- 學(xué)習(xí)Bootstrap滾動(dòng)監(jiān)聽 附調(diào)用方法
- 全面解析Bootstrap中scrollspy(滾動(dòng)監(jiān)聽)的使用方法
- Bootstrap教程JS插件滾動(dòng)監(jiān)聽學(xué)習(xí)筆記分享
- Bootstrap滾動(dòng)監(jiān)聽(Scrollspy)插件詳解
- Bootstrap每天必學(xué)之滾動(dòng)監(jiān)聽
- Bootstrap+Vue滑動(dòng)監(jiān)聽Scrollspy實(shí)現(xiàn)餐廳餐品展示
相關(guān)文章
分享幾個(gè)JavaScript運(yùn)算符的使用技巧
這篇文章主要介紹了分享幾個(gè)JavaScript運(yùn)算符的使用技巧,幫助大家更好的理解和學(xué)習(xí)使用JavaScript,感興趣的朋友可以了解下2021-04-04
javascript 實(shí)現(xiàn) 秒殺,團(tuán)購(gòu) 倒計(jì)時(shí)展示的記錄 分享
這篇文章介紹了javascript 實(shí)現(xiàn) 秒殺,團(tuán)購(gòu) 倒計(jì)時(shí)展示的記錄方法,有需要的朋友可以參考一下2013-07-07
javascript修改瀏覽器title方法 JS動(dòng)態(tài)修改瀏覽器標(biāo)題
給大家講一個(gè)用javascript修改瀏覽器title方法和技巧,需要的朋友把代碼測(cè)試吧。2017-11-11
Bootstrap基本組件學(xué)習(xí)筆記之縮略圖(13)
這篇文章主要為大家詳細(xì)介紹了Bootstrap基本組件學(xué)習(xí)筆記之縮略圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
JavaScript檢測(cè)用戶是否在線的6種方法總結(jié)
這篇文章主要為大家詳細(xì)介紹了JavaScript中實(shí)現(xiàn)檢測(cè)用戶是否在線的6種常用方法,文中的示例代碼講解詳細(xì),感興趣的可以跟隨小編一起學(xué)習(xí)一下2023-08-08
JS多個(gè)矩形塊選擇效果代碼(模擬CS結(jié)構(gòu))
非常不錯(cuò)的可以選擇多個(gè)矩形塊的功能代碼2008-11-11
JS前端千萬(wàn)級(jí)彈幕數(shù)據(jù)循環(huán)優(yōu)化示例
這篇文章主要為大家介紹了JS前端一千萬(wàn)條彈幕數(shù)據(jù)循環(huán)優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07

