单击时平滑滚动到特定div


91

我正在尝试做的是使它成为可能,如果您单击一个按钮,它将向下(平滑地)滚动到页面上的特定div。

我需要的是,如果单击该按钮,它将平滑滚动到div的“ second”。

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}
<div class="first"><button type="button">Click Me!</button></div>
<div class="second">Hi</div>


你可以试试这个插件虽然,这一次是更为人性化。您几乎只需要在标头中链接JS文件,并适当地更改您的标记即可使用。
2013年

Answers:


177

做:

$("button").click(function() {
    $('html,body').animate({
        scrollTop: $(".second").offset().top},
        'slow');
});

更新的Jsfiddle


您在这里使用JavaScript还是jQuery?

1
@FahadUddin其jQuery。
Sudhir Bastakoti

@SudhirBastakoti:为什么JsFiddle没有在该页面上包含它的jquery库?

@Sudhir Bastakoti,但许多用户抱怨滚动不流畅。
Maulik

39

使用jQuery库(例如jQuery,Mootools,Prototype等)进行平滑滚动的例子很多。

以下示例基于纯JavaScript。如果您的页面上没有jQuery / Mootools / Prototype,或者您不想使用繁重的JS库重载页面,那么该示例将有所帮助。

http://jsfiddle.net/rjSfP/

HTML部分:

<div class="first"><button type="button" onclick="smoothScroll(document.getElementById('second'))">Click Me!</button></div>
<div class="second" id="second">Hi</div>

CSS部分:

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}

JS部分:

window.smoothScroll = function(target) {
    var scrollContainer = target;
    do { //find scroll container
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do { //find the top of target relatively to the container
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    scroll = function(c, a, b, i) {
        i++; if (i > 30) return;
        c.scrollTop = a + (b - a) / 30 * i;
        setTimeout(function(){ scroll(c, a, b, i); }, 20);
    }
    // start scrolling
    scroll(scrollContainer, scrollContainer.scrollTop, targetY, 0);
}

我正在使用它,效果很好。我如何使滚动速度变慢?
jamescampbell,2015年

任何想法如何在此代码中为固定导航栏添加偏移量?这是我制造小提琴的
Plavookac

3
5年后仍然有帮助
Owaiz Yusufi '18

9

我玩了一下nico的答案,感觉有些不高兴。进行了一些调查,发现window.requestAnimationFrame在每个重绘周期中调用了哪个函数。这样可以使动画看起来更简洁。仍在尝试为步长调整好的默认值,但对于我的示例,使用此实现看起来很不错。

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var stepFunc = function() {
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}

1
@Alfonso参见上文。这只是先前答案中nico代码的优化版本。
内德·罗克森

@NedRockson对我不起作用,显示控制台消息“ Uncaught TypeError:无法读取null的属性'parentNode'”,但nico的代码有效,我该怎么做才能应用干净的动画?
Kartik Watwani

@KartikWatwani这意味着在读取的行上scrollContainer = scrollContainer.parentNode,scrollContainer为null。这可能意味着您elementId在调用此函数时未传递正确的信息。也有可能在不存在那个elementId的页面上运行此脚本。
内德·罗克森

@NedRockson如果elementId是错的话,在@nico的示例中,我会收到相同的错误,但在这种情况下,滚动工作正常,但不顺利。
Kartik Watwani

使用requestAnimationFrame替代setTimeout方法是可行的。setTimeout不应用于动画。
tsnkff


2

我采用了内德·罗克森Ned Rockson)的版本,并对其进行了调整以允许向上滚动。

var smoothScroll = function(elementId) {
  var MIN_PIXELS_PER_STEP = 16;
  var MAX_SCROLL_STEPS = 30;
  var target = document.getElementById(elementId);
  var scrollContainer = target;
  do {
    scrollContainer = scrollContainer.parentNode;
    if (!scrollContainer) return;
    scrollContainer.scrollTop += 1;
  } while (scrollContainer.scrollTop === 0);

  var targetY = 0;
  do {
    if (target === scrollContainer) break;
    targetY += target.offsetTop;
  } while (target = target.offsetParent);

  var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
    Math.abs(targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

  var isUp = targetY < scrollContainer.scrollTop;

  var stepFunc = function() {
    if (isUp) {
      scrollContainer.scrollTop = Math.max(targetY, scrollContainer.scrollTop - pixelsPerStep);
      if (scrollContainer.scrollTop <= targetY) {
        return;
      }
    } else {
        scrollContainer.scrollTop = Math.min(targetY, scrollContainer.scrollTop + pixelsPerStep);

      if (scrollContainer.scrollTop >= targetY) {
        return;
      }
    }

    window.requestAnimationFrame(stepFunc);
  };

  window.requestAnimationFrame(stepFunc);
};

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.