【问题标题】:jQuery one-page website scrolling/hash problemsjQuery一页网站滚动/散列问题
【发布时间】:2012-11-04 15:10:32
【问题描述】:

我想创建一个单页网站,其中包含多个 (html5) 部分,其中包含所有子页面。有固定的导航。以下是一些要求:

  • 点击导航链接(例如#home、#about-me)时,我希望它平滑滚动到该部分
  • 我想在 URL 中使用哈希,例如 domain.com/#about-me
  • 我希望用户能够使用浏览器中的后退/前进按钮,并在使用时平滑滚动到该部分
  • 当 URL domain.com/#about-me 立即加载时,我希望它从顶部平滑滚动到 #about-me 部分。

我这几天一直在尝试解决这个问题。我尝试从头开始这样做,并使用大量不同的插件,如 BBQ 插件。我想不通。但我学到了一点,所以我决定从头开始。我更喜欢在没有插件的情况下自己编写它,因为它很轻量级。但是,如果自己编写插件太麻烦的话,我完全没有问题。

现在我有这个 HTML,一个简单的导航:

<nav>
    <ul>
        <li><a href="#home">Home</a></li>
        <li><a href="#about-me">About me</a></li>
        <li><a href="#portfolio">Portfolio</a></li>
        <li><a href="#contact">Contact</a></li>
    </ul>
</nav>

和部分:

<div id="content-wrapper">
    <section id="home">
        <div>content...</div>
    </section>
    <section id="about-me">
        <div>content...</div>
    </section>
    etc...
</div>

现在是 jQuery 部分:

// Function to check if section exists
function isSection(section){
    if($('section'+section).length > 0){
        return true;
    }
    else{
        return false;
    }
}

// Scroll function
function scrollToSection(section){
    var offset = $(section).offset().top;
    $('html, body').stop().animate({
        scrollTop: offset
    }, 600);
}

// The Click() function
$('nav ul a').click(function(){
    var section = $(this).attr('href');
    if(isSection(section)){
        scrollToSection(section);
    }
})

我马上就遇到了问题。哈希值发生了变化,但它会立即跳转到该部分,并且在一瞬间之后它仍然会执行滚动动画(从它之前的起始位置开始)。我可以使用 preventDefault() (这会导致完美的平滑动画),但哈希不会改变。很高兴它更改了哈希值,因此浏览器历史记录可以正常工作,但是按下历史记录按钮时不会发生滚动。

我将如何从这里开始牢记最高要求?有什么建议和最好的例子吗?

我听说BBQ hashchange 插件非常适合所有这些?我将如何实现这一点?文档没有完全考虑我的要求。

【问题讨论】:

    标签: jquery hash scroll


    【解决方案1】:

    动画完成后,您可以手动使用 set location.hash 更改 url。首先,您将使用 preventDefault 让它动画。滚动到您想去的地方后,您可以使用位置。

    // Scroll function
    function scrollToSection(section){
        var offset = $(section).offset().top;
        $('html, body').stop().animate({
            scrollTop: offset
        }, 600, function(){
           window.location.hash = section;
        });
    }
    
    // The Click() function
    $('nav ul a').click(function(event){
        event.preventDefault();
        var section = $(this).attr('href');
        if(isSection(section)){
            scrollToSection(section);
        }
        return false;
    })​
    

    http://jsfiddle.net/adamzr/p5L57/

    另一种方法是让链接像往常一样更改哈希值。但是,我们可以使用 onhashchange 事件在 hash 变化时进行滚动。

    将您的点击处理程序替换为:

    function locationHashChanged(event) {
        event.preventDefault();
        var section = location.hash;
        if(isSection(section)){
            scrollToSection(section);
        }
    }
    
    window.onhashchange = locationHashChanged;
    

    http://jsfiddle.net/adamzr/XDWuS

    这种方法更好,但我在 jsfiddle 散列中使用它的方式除了使用 nav 转到部分之外将不起作用。如果您在页面上有其他哈希值,并且您也希望滚动为它们工作,您可以删除部分特定代码。

    另外,它只适用于支持 onhashchange 事件的浏览器。http://caniuse.com/hashchange

    【讨论】:

    • 好建议。但这会导致同样的问题。它会立即跳转到该部分,一秒钟后它仍然会执行滚动动画。
    • @Bob 我想我通过只在动画完成后更改哈希来解决这个问题。
    • 啊,是的,谢谢你的例子!我没有做 return false,我认为这导致了奇怪的跳跃问题。我认为 preventDefault() 会解决这个问题。但是那部分被覆盖了!谢谢!要求 3 和 4 对我来说仍然是个谜。
    • 我添加了另一种方法。那应该让你获得第 3 和第 4 名
    • 嗯,你的#3 和#4 方法对我不起作用。不在我的网站或 jsfiddle 示例中。它就像一个普通的哈希链接。 Here 是我正在处理的实际站点。 javascript 是here。我是不是误会了什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    相关资源
    最近更新 更多