简体   繁体   English

使用粘性导航栏平滑滚动引导页面

[英]Smooth-scroll a bootstrap page with sticky navbar

Smooth-scroll scripts in common, stop the default link action (by returning false) to prevent a jump in the animation. 通常,平滑滚动脚本会停止默认的链接操作(返回false),以防止动画跳转。 This also stops bootstrap navbar menus to collapse when clicked on a link (bad). 单击链接(错误)时,这也可以停止引导导航栏菜单折叠。

Example: 例:
http://www.bootply.com/NoGAvuQGDE http://www.bootply.com/NoGAvuQGDE

In the smooth scroll script's last line; 在平滑滚动脚本的最后一行;

  • if you return false , it conflicts and stops the menu closing when clicked on a link. 如果返回false ,则会发生冲突,并在单击链接时停止菜单关闭。
  • If you return true , the animation gets jumpy due to the link working. 如果返回true ,则由于链接有效,动画会跳动。

Reproduce: 复制:

  • click on the dropdown / action link 点击dropdown / action链接
  • the dropdown stays open (bad), due to the blocked default action 由于默认操作被阻止,因此下拉菜单保持打开状态(错误)

Excluding navbar links from smooth-scrolling would beat the purpose. 从导航滚动中排除导航栏链接将达到目的。

Idea: 理念:
We could modify the smooth-scroll script to close all navbar menus when a link is smooth-scrolled. 当链接被平滑滚动时,我们可以修改平滑滚动脚本以关闭所有导航栏菜单。 Something like $('.dropdown-toggle').dropdown('collapse') would work but there is no 'collapse' action in the API, only 'toggle'. $('.dropdown-toggle').dropdown('collapse')这样的东西可以工作,但是API中没有“ collapse”操作,只有“ toggle”。

Q: How can I have smooth-scrolling on a bootstrap page, without it conflicting with navbar menus , stopping them close? 问:如何在引导页面上进行平滑滚动, 而又不与导航栏菜单发生冲突 ,并阻止它们关闭?


The smoothscroll script, for future reference : smoothscroll脚本,以供将来参考:

$(function(){
    $('.navbar a[href*=#], a.smooth').click(function() {return smoothScroll(this)});
});

function smoothScroll(linkItem) {

    if (location.pathname.replace(/^\//,'') == linkItem.pathname.replace(/^\//,'')
    && location.hostname == linkItem.hostname) {

        var $target = $(linkItem.hash);
        $target = $target.length && $target || $('[name=' + linkItem.hash.slice(1) +']');

        if ($target.length) {
        var targetOffset = $target.offset().top;
        $('html,body').animate({scrollTop: targetOffset}, 500);
        return false;
        }
    }
}

Looking at the document tree while toggling the dropdown menu, the Bootstrap functionality seems to rely on an open class on the parent. 在切换下拉菜单的同时查看文档树,Bootstrap功能似乎依赖于父级上的open类。 In the relevant code concerning the event handlers (which is a bit obscure to read), this class is toggled. 在有关事件处理程序的相关代码中(有点晦涩难懂),此类已切换。 The following would emulate it when the default behaviour is prevented on a menu that is active and seems to be doing the trick : 当在活动的菜单上阻止了默认行为并且似乎正在执行此操作时,以下将模拟它:

dropdown = linkItem.closest('.dropdown');

if ($(dropdown).hasClass('open')) $(dropdown).removeClass('open');

One could argue the link is only clickable when the dropdown is open so even this should suffice : 有人可能会说,只有在下拉列表打开的情况下,链接才可以单击,因此即使这样也足够了:

$(dropdown).toggleClass('open');

A dropdown inside another one would need some additional script but I guess that's an unlikely configuration. 另一个内部的下拉菜单将需要一些其他脚本,但是我想这是一个不太可能的配置。 Interaction with any siblings is apparently working well too. 与任何同胞的互动显然也很好。 Integrated in the code : 集成在代码中:

$(function(){
    $('.navbar a[href*=#]').click(function() {return smoothScroll(this)});
});

function smoothScroll(linkItem) {

    if (location.pathname.replace(/^\//,'') == linkItem.pathname.replace(/^\//,'')
    && location.hostname == linkItem.hostname) {

        var $target = $(linkItem.hash);
        $target = $target.length && $target || $('[name=' + linkItem.hash.slice(1) +']');
        var dropdown = linkItem.closest('.dropdown');

        if ($target.length) {
        if (dropdown) $(dropdown).toggleClass('open');
        var targetOffset = $target.offset().top;
        $('html,body').animate({scrollTop: targetOffset}, 500);
        return false;
        }
    }
}

When only using this script on anchor links, it could be simplified by the way : 仅在锚链接上使用此脚本时,可以通过以下方式进行简化:

$(function(){
    $('.navbar a[href*=#]').click(function() {smoothScroll(this)});
});

function smoothScroll(linkItem) {

    var $target = $(linkItem.hash),
    dropdown = linkItem.closest('.dropdown');

    if ($target.length) {
    if (dropdown) $(dropdown).toggleClass('open');
    var targetOffset = $target.offset().top;
    $('html,body').animate({scrollTop: targetOffset}, 500);
    return false;
    }
}

While getting the expected results with what was posted in the comments earlier, after additional debugging the code needed to be a bit more subtle to find the correct parent - also added an extra if (dropdown) check. 在通过注释中发布的内容获得预期结果的同时,在进行额外的调试之后,需要更微妙的代码才能找到正确的父级-还添加了额外的if (dropdown)检查。 No need to apply a method on something that doesn't exist of course. 当然不需要在不存在的事物上应用方法。

http://www.bootply.com/hC4s6OEgA1 http://www.bootply.com/hC4s6OEgA1

One way to accomplish this is to add an additional class to the navigation menu items that need the smooth scrolling which will leave the other menu items that you dont want to scroll to work as intended. 实现此目的的一种方法是向需要平滑滚动的导航菜单项添加一个附加类,这将使您不想滚动的其他菜单项按预期工作。

Your updated navigation menu HTML 您更新的导航菜单HTML

<ul class="nav navbar-nav">
  <li class="smooth"><a href="#a">About</a></li>
  <li class="smooth"><a href="#b">Contact</a></li>
  <li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
    <ul class="dropdown-menu">
      <li><a href="http://www.google.com" target="_blank">Action</a></li>
    </ul>
  </li>
</ul>

and your updated JQuery: 和您更新的JQuery:

$(function(){
    $('.navbar .smooth a[href*=#], a.smooth').click(function() {return smoothScroll(this)});
});

I have added a JS.Fiddle if you want to see it working. 如果您希望看到它,我添加了一个JS.Fiddle Hope that helps. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM