如何在不使用 bootstrap 的情况下使用 scrollspy
how to use scrollspy without using bootstrap
有人知道如何在不使用 bootstrap 的情况下使用 scrollspy 吗?
我正在尝试使用此存储库让它在我的一个项目中工作:
https://github.com/sxalexander/jquery-scrollspy
但它与 bootstrap 不同。 li 标签未标记为活动 :(
任何帮助将不胜感激。
我试过这样做:
$('#intel_nav').scrollspy({
//n: $('#nav').offset().top,
onEnter: function (element, position) {
console.log(element);
$("#intel_nav").addClass('moo');
},
onLeave: function (element, position) {
$("#intel_nav").removeClass('out');
}
});
该元素似乎是实际的菜单,所以我不知道如何实际获取我当前悬停在其上的元素的 ID。
github.com/sxalexander/jquery-scrollspy 似乎没有像 Bootstrap 插件那样自动激活 <nav>
菜单。
但是它确实提供了进入视图的元素的 ID。请参阅在控制台中打印元素 ID 的 this JSFiddle。
您需要决定如何突出显示与具有其 ID 的元素对应的菜单项。例如,在菜单 link 上设置 data-target="section1"
属性,然后当 ID 为 section1
的元素出现时,通过 $("#intel_nav a[data-target='" + "section1" + "']")
定位菜单
为了解决这个问题,我编写了自己的插件。
可以在这里找到:
您可以使用 bootstrap 的自定义页面仅下载 scrollspy JS。您还需要 "nav" css。这个 link 应该正是您所需要的:http://getbootstrap.com/customize/?id=8f4a63b0157214af61c9ce380630a64d
下载 JS 和 CSS 文件并将它们添加到您的站点。 Scrollspy 应该按照 bootstrap 的文档工作 (http://getbootstrap.com/javascript/#scrollspy)
如果有人仍然对此感兴趣,我无法使 bootstrap scrollspy 足够快地工作,所以我编写了自己的(技术上效率低下但简单)解决方案。
这是一个演示:
$(window).bind('scroll', function() {
var currentTop = $(window).scrollTop();
var elems = $('.scrollspy');
elems.each(function(index){
var elemTop = $(this).offset().top;
var elemBottom = elemTop + $(this).height();
if(currentTop >= elemTop && currentTop <= elemBottom){
var id = $(this).attr('id');
var navElem = $('a[href="#' + id+ '"]');
navElem.parent().addClass('active').siblings().removeClass( 'active' );
}
})
});
.active{
color: red;
background-color: red;
}
#nav{
position:fixed;
top:0;
right:50%;
}
section{
min-height: 500px;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<nav id="nav" class="navbar navbar-template">
<div class="row col-xs-12 text-center">
<ul>
<li class="active">
<a href="#Home">Home</a>
</li>
<li>
<a href="#AboutUs">AboutUs</a>
</li>
<li>
<a href="#Images">Images</a>
</li>
<li>
<a href="#Contact">Contact</a>
</li>
</ul>
</div>
</nav>
<section class="scrollspy" id="Home">
Home
</section>
<section class="scrollspy" id="AboutUs">
AboutUs
</section>
<section class="scrollspy" id="Images">
Images
</section>
<section class="scrollspy" id="Contact">
Contact
</section>
</body>
在查看所有建议后,我遵循 Gyrocode.com idea, with the Mr. Sam Alexander (sxalexander) jquery-scrollspy, a nicely work based on David Walsh's MooTools scrollspy; I believe that is not to hard use this with any menu (with or without nav) or in any creative duty as the proposed by Gyrocode.com in their JSFiddle。
当所有部分都具有相同的标签(如 <部分>)或在本例中具有相同的 class 名称(.scrollspy),这些部分告诉我们它们的 ID(作为插件的一部分)
我分享我的实现:
var menuSelected = null; // var to detect current selected element to pass the class that does visible the spy.
jQuery(document).ready(function( $ ){
// Detect Initial scroll position
var currentTop = $(window).scrollTop();
$('.scrollspy').each(function (i) {
var position = $(this).position();
// Only to activate the top element ( current # )
// if current is less than height.
if ( i === 0 && !menuSelected && currentTop < $(this).height() ) navUpdate( $('a[href="#' + $(this).attr( 'id' ) + '"]') );
// Basic implementation
$(this).scrollspy({
min: position.top - 100,
max: position.top + $(this).height(),
onEnter: function (element, position) {
// update the button that have the element ID
navUpdate( $('a[href="#' + element.id+ '"]') );
}
});
});
// method to update the navigation bar
function navUpdate( where ){
if ( menuSelected ) menuSelected.removeClass( 'active' );
menuSelected = where.parent();
menuSelected.addClass( 'active' );
}
});
纯javascript。 (主脚本50行↓)
要点:
- window.scrollY:获取文档当前垂直滚动的像素数。
- Element.offsetTop:获取当前元素外边框相对于top
内边框的距离
<style>
body {
min-height: 150em
}
article {
min-height: 20em
}
.active {
color: #fff307;
}
</style>
<nav style="position: fixed; top:0; right: 50%">
<ul>
<li><a href="#about">about</a></li>
<li><a href="#product">product</a></li>
<li><a href="#contact">contact</a></li>
</ul>
</nav>
<body>
<article id="about" style="background-color: #a6b4cd">About</article>
<article id="product" style="background-color: #eeb554">Product</article>
<article id="contact" style="background-color: #88f3d1">Contact</article>
</body>
<script>
// main script
/***
* @param {Element} scrollTarget
* @param {Element} labelTarget
* @param {?Number} frequency : Number (millisecond) Control how often to do the check.
*/
function ScrollSpy(scrollTarget, labelTarget, {frequency = 500}) {
const labelTargets = [...labelTarget.querySelectorAll(`a[href^="#"]`)]
.map(e => {
const m = e.href.match(/.*#(.*)/)
if (m) {
return [e, m[1]]
}
return null
}).filter(e => e !== null)
const hrefArray = labelTargets.map(([e, href]) => href)
// dataArray: [{targetElem, labelElem, id}, ...]
const dataArray = [...scrollTarget.querySelectorAll(`[id]`)].map(e => {
if (hrefArray.includes(e.id)) {
return [e, ...labelTargets.filter(([_, href]) => href === e.id)[0]]
}
return null
}).filter(e => e !== null)
document.addEventListener("scroll", (e) => {
if (Date.now() - ScrollSpy.lastChangeTime < frequency) {
return
}
ScrollSpy.lastChangeTime = Date.now()
for (const [curElem, labelElem, curID] of dataArray) {
if (
window.scrollY >= curElem.offsetTop &&
window.scrollY <= curElem.offsetTop + curElem.clientHeight
) {
labelElem.classList.add("active")
continue
}
labelElem.classList.remove("active")
}
})
}
ScrollSpy.lastChangeTime = 0 // Create a new attribute to keep the variable.
</script>
<script>
// usage
ScrollSpy(document.body, document.querySelector(`nav`), {})
// ScrollSpy(document.body, document.querySelector(`nav`), {frequency: 1000})
</script>
有人知道如何在不使用 bootstrap 的情况下使用 scrollspy 吗? 我正在尝试使用此存储库让它在我的一个项目中工作:
https://github.com/sxalexander/jquery-scrollspy
但它与 bootstrap 不同。 li 标签未标记为活动 :( 任何帮助将不胜感激。
我试过这样做:
$('#intel_nav').scrollspy({
//n: $('#nav').offset().top,
onEnter: function (element, position) {
console.log(element);
$("#intel_nav").addClass('moo');
},
onLeave: function (element, position) {
$("#intel_nav").removeClass('out');
}
});
该元素似乎是实际的菜单,所以我不知道如何实际获取我当前悬停在其上的元素的 ID。
github.com/sxalexander/jquery-scrollspy 似乎没有像 Bootstrap 插件那样自动激活 <nav>
菜单。
但是它确实提供了进入视图的元素的 ID。请参阅在控制台中打印元素 ID 的 this JSFiddle。
您需要决定如何突出显示与具有其 ID 的元素对应的菜单项。例如,在菜单 link 上设置 data-target="section1"
属性,然后当 ID 为 section1
的元素出现时,通过 $("#intel_nav a[data-target='" + "section1" + "']")
为了解决这个问题,我编写了自己的插件。 可以在这里找到:
您可以使用 bootstrap 的自定义页面仅下载 scrollspy JS。您还需要 "nav" css。这个 link 应该正是您所需要的:http://getbootstrap.com/customize/?id=8f4a63b0157214af61c9ce380630a64d
下载 JS 和 CSS 文件并将它们添加到您的站点。 Scrollspy 应该按照 bootstrap 的文档工作 (http://getbootstrap.com/javascript/#scrollspy)
如果有人仍然对此感兴趣,我无法使 bootstrap scrollspy 足够快地工作,所以我编写了自己的(技术上效率低下但简单)解决方案。
这是一个演示:
$(window).bind('scroll', function() {
var currentTop = $(window).scrollTop();
var elems = $('.scrollspy');
elems.each(function(index){
var elemTop = $(this).offset().top;
var elemBottom = elemTop + $(this).height();
if(currentTop >= elemTop && currentTop <= elemBottom){
var id = $(this).attr('id');
var navElem = $('a[href="#' + id+ '"]');
navElem.parent().addClass('active').siblings().removeClass( 'active' );
}
})
});
.active{
color: red;
background-color: red;
}
#nav{
position:fixed;
top:0;
right:50%;
}
section{
min-height: 500px;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<nav id="nav" class="navbar navbar-template">
<div class="row col-xs-12 text-center">
<ul>
<li class="active">
<a href="#Home">Home</a>
</li>
<li>
<a href="#AboutUs">AboutUs</a>
</li>
<li>
<a href="#Images">Images</a>
</li>
<li>
<a href="#Contact">Contact</a>
</li>
</ul>
</div>
</nav>
<section class="scrollspy" id="Home">
Home
</section>
<section class="scrollspy" id="AboutUs">
AboutUs
</section>
<section class="scrollspy" id="Images">
Images
</section>
<section class="scrollspy" id="Contact">
Contact
</section>
</body>
在查看所有建议后,我遵循 Gyrocode.com idea, with the Mr. Sam Alexander (sxalexander) jquery-scrollspy, a nicely work based on David Walsh's MooTools scrollspy; I believe that is not to hard use this with any menu (with or without nav) or in any creative duty as the proposed by Gyrocode.com in their JSFiddle。
当所有部分都具有相同的标签(如 <部分>)或在本例中具有相同的 class 名称(.scrollspy),这些部分告诉我们它们的 ID(作为插件的一部分)
我分享我的实现:
var menuSelected = null; // var to detect current selected element to pass the class that does visible the spy.
jQuery(document).ready(function( $ ){
// Detect Initial scroll position
var currentTop = $(window).scrollTop();
$('.scrollspy').each(function (i) {
var position = $(this).position();
// Only to activate the top element ( current # )
// if current is less than height.
if ( i === 0 && !menuSelected && currentTop < $(this).height() ) navUpdate( $('a[href="#' + $(this).attr( 'id' ) + '"]') );
// Basic implementation
$(this).scrollspy({
min: position.top - 100,
max: position.top + $(this).height(),
onEnter: function (element, position) {
// update the button that have the element ID
navUpdate( $('a[href="#' + element.id+ '"]') );
}
});
});
// method to update the navigation bar
function navUpdate( where ){
if ( menuSelected ) menuSelected.removeClass( 'active' );
menuSelected = where.parent();
menuSelected.addClass( 'active' );
}
});
纯javascript。 (主脚本50行↓)
要点:
- window.scrollY:获取文档当前垂直滚动的像素数。
- Element.offsetTop:获取当前元素外边框相对于top 内边框的距离
<style>
body {
min-height: 150em
}
article {
min-height: 20em
}
.active {
color: #fff307;
}
</style>
<nav style="position: fixed; top:0; right: 50%">
<ul>
<li><a href="#about">about</a></li>
<li><a href="#product">product</a></li>
<li><a href="#contact">contact</a></li>
</ul>
</nav>
<body>
<article id="about" style="background-color: #a6b4cd">About</article>
<article id="product" style="background-color: #eeb554">Product</article>
<article id="contact" style="background-color: #88f3d1">Contact</article>
</body>
<script>
// main script
/***
* @param {Element} scrollTarget
* @param {Element} labelTarget
* @param {?Number} frequency : Number (millisecond) Control how often to do the check.
*/
function ScrollSpy(scrollTarget, labelTarget, {frequency = 500}) {
const labelTargets = [...labelTarget.querySelectorAll(`a[href^="#"]`)]
.map(e => {
const m = e.href.match(/.*#(.*)/)
if (m) {
return [e, m[1]]
}
return null
}).filter(e => e !== null)
const hrefArray = labelTargets.map(([e, href]) => href)
// dataArray: [{targetElem, labelElem, id}, ...]
const dataArray = [...scrollTarget.querySelectorAll(`[id]`)].map(e => {
if (hrefArray.includes(e.id)) {
return [e, ...labelTargets.filter(([_, href]) => href === e.id)[0]]
}
return null
}).filter(e => e !== null)
document.addEventListener("scroll", (e) => {
if (Date.now() - ScrollSpy.lastChangeTime < frequency) {
return
}
ScrollSpy.lastChangeTime = Date.now()
for (const [curElem, labelElem, curID] of dataArray) {
if (
window.scrollY >= curElem.offsetTop &&
window.scrollY <= curElem.offsetTop + curElem.clientHeight
) {
labelElem.classList.add("active")
continue
}
labelElem.classList.remove("active")
}
})
}
ScrollSpy.lastChangeTime = 0 // Create a new attribute to keep the variable.
</script>
<script>
// usage
ScrollSpy(document.body, document.querySelector(`nav`), {})
// ScrollSpy(document.body, document.querySelector(`nav`), {frequency: 1000})
</script>