bootstrap源码之滚动监听组件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í))要一致。
下面來(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 = nullthis.scrollHeight = 0this.$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 = thisvar offsetMethod = 'offset'var offsetBase = 0this.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.offsetvar scrollHeight = this.getScrollHeight()var maxScroll = this.options.offset scrollHeight - this.$scrollElement.height()var offsets = this.offsetsvar targets = this.targetsvar activeTarget = this.activeTargetvar iif (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 = nullreturn 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.offset2.滾動(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 = targetthis.clear()var selector = this.selector '[data-target="' target '"],' this.selector '[href="' target '"]'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 = nullthis.scrollHeight = 0this.$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 = thisvar offsetMethod = 'offset'var offsetBase = 0this.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.offsetvar scrollHeight = this.getScrollHeight()var maxScroll = this.options.offset scrollHeight - this.$scrollElement.height()var offsets = this.offsetsvar targets = this.targetsvar activeTarget = this.activeTargetvar iif (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 = nullreturn 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 = targetthis.clear()var selector = this.selector '[data-target="' target '"],' this.selector '[href="' target '"]'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' && optionif (!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 = oldreturn 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);?
更多專業(yè)前端知識(shí),請(qǐng)上 【猿2048】www.mk2048.com
總結(jié)
以上是生活随笔為你收集整理的bootstrap源码之滚动监听组件scrollspy.js详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JS对全角与半角的验证,相互转化以及介绍
- 下一篇: HTML5效果:实现树叶飘落