Javascript 单击可平滑滚动至特定div

Javascript 单击可平滑滚动至特定div,javascript,jquery,Javascript,Jquery,我想做的是,如果你点击一个按钮,它就会向下(平滑地)滚动到页面上的一个特定div 我需要的是,如果你点击按钮,它会平滑地滚动到div'second' 。首先{ 宽度:100%; 高度:1000px; 背景:#ccc; } .第二{ 宽度:100%; 高度:1000px; 背景:#999; } 点击我! 您好请执行以下操作: 更新了有许多使用JS库的平滑滚动示例,如jQuery、Mootools、Prototype等 下面的示例是关于纯JavaScript的。如果您在页面上没有jQuery/Mo

我想做的是,如果你点击一个按钮,它就会向下(平滑地)滚动到页面上的一个特定div

我需要的是,如果你点击按钮,它会平滑地滚动到div'second'

。首先{
宽度:100%;
高度:1000px;
背景:#ccc;
}
.第二{
宽度:100%;
高度:1000px;
背景:#999;
}
点击我!
您好
请执行以下操作:


更新了

有许多使用JS库的平滑滚动示例,如jQuery、Mootools、Prototype等

下面的示例是关于纯JavaScript的。如果您在页面上没有jQuery/Mootools/Prototype,或者您不想用繁重的JS库使页面过载,那么这个示例会有所帮助

HTML部分:

<div class="first"><button type="button" onclick="smoothScroll(document.getElementById('second'))">Click Me!</button></div>
<div class="second" id="second">Hi</div>
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);
}

我对尼科的回答有点胡思乱想,感觉有些紧张。做了一些调查,发现了
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);
}
我使用了的版本,并将其调整为允许向上滚动

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);
};
var smoothScroll=函数(elementId){
var最小像素每步=16;
var MAX_SCROLL_STEPS=30;
var target=document.getElementById(elementId);
var scrollContainer=目标;
做{
scrollContainer=scrollContainer.parentNode;
如果(!scrollContainer)返回;
scrollContainer.scrollTop+=1;
}而(scrollContainer.scrollTop==0);
var-targetY=0;
做{
如果(目标===scrollContainer)中断;
targetY+=target.offsetTop;
}while(target=target.offsetParent);
var pixelsPerStep=Math.max(每一步的最小像素数,
abs(targetY-scrollContainer.scrollTop)/MAX\u SCROLL\u步骤);
var isUp=targetY
如果使用scrollIntoView功能怎么办

var elmntToView = document.getElementById("sectionId");
elmntToView.scrollIntoView(); 

也有{行为:“平滑”};)

您可以使用基本css实现平滑滚动

html {
  scroll-behavior: smooth;
}

内德·洛克森基本上回答了这个问题。然而,他的解决方案中有一个致命的缺陷。当目标元素比视口高度更接近页面底部时,函数不会到达其exit语句并将用户困在页面底部。这可以通过限制迭代次数来简单地解决

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 iterations = 0;
    var stepFunc = function() {
        if(iterations > MAX_SCROLL_STEPS){
            return;
        }
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

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

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}

我正在使用这个,效果很好。我如何使滚动速度变慢?你知道如何在这段代码中为固定导航条添加偏移量吗?下面是我做的一个例子,5点后仍然有用years@Alfonso见上文。这只是前面回答中nico代码的优化版本。@NedRockson不适用于我,给出控制台消息“Uncaught TypeError:无法读取null的属性'parentNode',但nico的代码正在工作,我应该怎么做才能应用干净的动画?@KartikWatwani这意味着在读取
scrollContainer=scrollContainer.parentNode
的行中,scrollContainer为空。这可能意味着您在调用此函数时没有传递正确的
elementId
。也可能是您在一个不存在elementId的页面上运行此脚本。@NedRockson如果
elementId
是错误的,我会在@nico的示例中收到相同的错误,但在这种情况下,滚动工作正常,但不顺畅。使用
requestAnimationFrame
而不是
setTimeout
是一个好办法
setTimeout
不应该用于动画。您是在这里使用javaScript还是jQuery?@Fahaudddin它的jQuery。@SudhirBastakoti:为什么JSFIDLE没有在该页面上包含jQuery库?@Sudhir Bastakoti,但许多用户抱怨它的滚动不平滑。您可以尝试一下,尽管它对用户友好得多。您几乎只需在标题中链接JS文件,并适当更改标记即可使其正常工作
html {
  scroll-behavior: smooth;
}
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 iterations = 0;
    var stepFunc = function() {
        if(iterations > MAX_SCROLL_STEPS){
            return;
        }
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

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

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}