45

ページの先頭に 4 つのボタン/リンクを配置し、その下にコンテンツを配置したいと考えています。

ボタンに次のコードを配置します。

<a href="#idElement1">Scroll to element 1</a>
<a href="#idElement2">Scroll to element 2</a>
<a href="#idElement3">Scroll to element 3</a>
<a href="#idElement4">Scroll to element 4</a>

リンクの下にはコンテンツがあります。

<h2 id="idElement1">Element1</h2>
content....
<h2 id="idElement2">Element2</h2>
content....
<h2 id="idElement3">Element3</h2>
content....
<h2 id="idElement4">Element4</h2>
content....

現在は機能していますが、より滑らかに見せることはできません。

このコードを使用しましたが、動作させることができません。

$('html, body').animate({
    scrollTop: $("#elementID").offset().top
}, 2000);

助言がありますか?ありがとうございました。

編集:およびフィドル:http://jsfiddle.net/WxJLx/2/

4

12 に答える 12

95

超スムーズrequestAnimationFrame

スクロール アニメーションをスムーズにレンダリングするには、通常のソリューションよりもレンダリングで優れwindow.requestAnimationFrame()たパフォーマンスを発揮するものを使用できます。setTimeout()

基本的な例は次のようになります。関数stepはブラウザのすべてのアニメーション フレームに対して呼び出され、再描画の時間管理を改善し、パフォーマンスを向上させます。

function doScrolling(elementY, duration) { 
  var startingY = window.pageYOffset;
  var diff = elementY - startingY;
  var start;

  // Bootstrap our animation - it will get called right before next frame shall be rendered.
  window.requestAnimationFrame(function step(timestamp) {
    if (!start) start = timestamp;
    // Elapsed milliseconds since start of scrolling.
    var time = timestamp - start;
    // Get percent of completion in range [0, 1].
    var percent = Math.min(time / duration, 1);

    window.scrollTo(0, startingY + diff * percent);

    // Proceed with animation as long as we wanted it to.
    if (time < duration) {
      window.requestAnimationFrame(step);
    }
  })
}

要素の Y 位置については、他の回答の関数または下記のフィドルの関数を使用してください。

イージングのサポートと最下部の要素への適切なスクロールを使用して、もう少し洗練された機能をセットアップしました: https://jsfiddle.net/s61x7c4e/

于 2016-09-14T15:25:09.530 に答える
21

スムーズなスクロール - jQuery を見て

itnewb.com の記事に基づいて、外部ライブラリなし でスムーズにスクロールするデモ プランクを作成しました。

JavaScript は非常に単純です。最初のヘルパー関数は、現在の位置を特定するためのクロス ブラウザー サポートを改善します。

function currentYPosition() {
    // Firefox, Chrome, Opera, Safari
    if (self.pageYOffset) return self.pageYOffset;
    // Internet Explorer 6 - standards mode
    if (document.documentElement && document.documentElement.scrollTop)
        return document.documentElement.scrollTop;
    // Internet Explorer 6, 7 and 8
    if (document.body.scrollTop) return document.body.scrollTop;
    return 0;
}

次に、目的の要素の位置 (スクロールしたい場所) を決定する関数です。

function elmYPosition(eID) {
    var elm = document.getElementById(eID);
    var y = elm.offsetTop;
    var node = elm;
    while (node.offsetParent && node.offsetParent != document.body) {
        node = node.offsetParent;
        y += node.offsetTop;
    } return y;
}

そして、スクロールを行うコア機能

function smoothScroll(eID) {
    var startY = currentYPosition();
    var stopY = elmYPosition(eID);
    var distance = stopY > startY ? stopY - startY : startY - stopY;
    if (distance < 100) {
        scrollTo(0, stopY); return;
    }
    var speed = Math.round(distance / 100);
    if (speed >= 20) speed = 20;
    var step = Math.round(distance / 25);
    var leapY = stopY > startY ? startY + step : startY - step;
    var timer = 0;
    if (stopY > startY) {
        for ( var i=startY; i<stopY; i+=step ) {
            setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
            leapY += step; if (leapY > stopY) leapY = stopY; timer++;
        } return;
    }
    for ( var i=startY; i>stopY; i-=step ) {
        setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
        leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
    }
    return false;
}

それを呼び出すには、次のようにします。宛先アンカーの参照として id を使用して、別の要素を指すリンクを作成します。

<a href="#anchor-2" 
   onclick="smoothScroll('anchor-2');">smooth scroll to the headline with id anchor-2<a/>
...
...  some content
...
<h2 id="anchor-2">Anchor 2</h2>

著作権

itnewb.com のフッターには次のように書かれています: The techniques, effects and code demonstrated in ITNewb articles may be used for any purpose without attribution (although we recommend it)(2014-01-12)

于 2013-07-18T18:58:37.563 に答える
8

CSS scroll-behaviorプロパティを使用しない理由

html {
  scroll-behavior: smooth;
}

ブラウザのサポートも良好 https://caniuse.com/#feat=css-scroll-behavior

于 2020-05-09T05:09:54.350 に答える
5

私はこれを長い間使用してきました:

function scrollToItem(item) {
    var diff=(item.offsetTop-window.scrollY)/8
    if (Math.abs(diff)>1) {
        window.scrollTo(0, (window.scrollY+diff))
        clearTimeout(window._TO)
        window._TO=setTimeout(scrollToItem, 30, item)
    } else {
        window.scrollTo(0, item.offsetTop)
    }
}

使用法: scrollToItem(element)は、たとえばですelementdocument.getElementById('elementid')

于 2016-07-05T14:44:53.520 に答える
4

@tominko 回答のバリエーション。アニメーションが少しスムーズになり、一部の要素がビューポートの上部に配置できない場合に setTimeout() が無限に呼び出される問題が解決されました。

function scrollToItem(item) {
    var diff=(item.offsetTop-window.scrollY)/20;
    if(!window._lastDiff){
        window._lastDiff = 0;
    }

    console.log('test')

    if (Math.abs(diff)>2) {
        window.scrollTo(0, (window.scrollY+diff))
        clearTimeout(window._TO)

        if(diff !== window._lastDiff){
            window._lastDiff = diff;
            window._TO=setTimeout(scrollToItem, 15, item);
        }
    } else {
        console.timeEnd('test');
        window.scrollTo(0, item.offsetTop)
    }
}
于 2016-11-06T22:15:37.237 に答える
4

スムーズなスクロールの方法のより包括的なリストについては、こちらの回答を参照してください。


正確な時間内に特定の位置にスクロールするには、window.requestAnimationFrame毎回適切な現在位置を計算して使用できます。要素までスクロールするには、y 位置を に設定するだけelement.offsetTopです。

/*
   @param pos: the y-position to scroll to (in pixels)
   @param time: the exact amount of time the scrolling will take (in milliseconds)
*/
function scrollToSmoothly(pos, time) {
    var currentPos = window.pageYOffset;
    var start = null;
    if(time == null) time = 500;
    pos = +pos, time = +time;
    window.requestAnimationFrame(function step(currentTime) {
        start = !start ? currentTime : start;
        var progress = currentTime - start;
        if (currentPos < pos) {
            window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
        } else {
            window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
        }
        if (progress < time) {
            window.requestAnimationFrame(step);
        } else {
            window.scrollTo(0, pos);
        }
    });
}

デモ:

function scrollToSmoothly(pos, time) {
    var currentPos = window.pageYOffset;
    var start = null;
    if(time == null) time = 500;
    pos = +pos, time = +time;
    window.requestAnimationFrame(function step(currentTime) {
        start = !start ? currentTime : start;
        var progress = currentTime - start;
        if (currentPos < pos) {
            window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
        } else {
            window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
        }
        if (progress < time) {
            window.requestAnimationFrame(step);
        } else {
            window.scrollTo(0, pos);
        }
    });
}

document.getElementById("toElement").addEventListener("click", function(e){
  scrollToSmoothly(document.querySelector('div').offsetTop, 500 /* milliseconds */);
});
document.getElementById("backToTop").addEventListener("click", function(e){
  scrollToSmoothly(0, 500);
});
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
  <button id="backToTop">Scroll back to top</button>
</div>

SmoothScroll.js ライブラリを使用することもできます。これは、ページ上の要素へのスクロールに加えて、垂直方向と水平方向のスムーズなスクロール、他のコンテナー要素内のスクロール、さまざまなイージング動作、現在の位置からの相対的なスクロールなどのより複雑な機能をサポートします。 、 もっと。

document.getElementById("toElement").addEventListener("click", function(e){
  smoothScroll({toElement: document.querySelector('div'), duration: 500});
});
document.getElementById("backToTop").addEventListener("click", function(e){
  smoothScroll({yPos: 'start', duration: 500});
});
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll@1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script>
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
  <button id="backToTop">Scroll back to top</button>
</div>

window.scrollまたは、特定の x および y 位置window.scrollByにスクロールし、現在の位置から一定量スクロールする options オブジェクトを渡すことができます。

// Scroll to specific values
// scrollTo is the same
window.scroll({
  top: 2500, 
  left: 0, 
  behavior: 'smooth' 
});

// Scroll certain amounts from current position 
window.scrollBy({ 
  top: 100, // could be negative value
  left: 0, 
  behavior: 'smooth' 
});

ドキュメント内の特定の位置ではなく、要素までスクロールする必要がある場合はElement.scrollIntoViewbehaviorset to を使用できますsmooth

document.getElementById("elemID").scrollIntoView({ 
  behavior: 'smooth' 
});
于 2018-08-04T20:42:28.957 に答える
2

このプラグインを使用できます。まさにあなたが望むことをします。

http://flesler.blogspot.com/2007/10/jqueryscrollto.html

于 2013-07-18T11:48:58.200 に答える
0

div 内の要素にスクロールする必要がある場合は、 Andrzej Sala の回答に基づく私の解決策があります。

function scroolTo(element, duration) {
    if (!duration) {
        duration = 700;
    }
    if (!element.offsetParent) {
        element.scrollTo();
    }
    var startingTop = element.offsetParent.scrollTop;
    var elementTop = element.offsetTop;
    var dist = elementTop - startingTop;
    var start;

    window.requestAnimationFrame(function step(timestamp) {
        if (!start)
            start = timestamp;
        var time = timestamp - start;
        var percent = Math.min(time / duration, 1);
        element.offsetParent.scrollTo(0, startingTop + dist * percent);

        // Proceed with animation as long as we wanted it to.
        if (time < duration) {
            window.requestAnimationFrame(step);
        }
    })
}
于 2018-06-25T17:54:59.790 に答える
-1

jQuery.ScrollTo によるスムーズなスクロール

jQuery ScrollTo プラグインを使用するには、次の手順を実行する必要があります

  1. href別の elements.id を指すリンクを作成する
  2. スクロールしたい要素を作成する
  3. jQuery と scrollTo プラグインを参照
  4. スムーズなスクロールを行う必要がある各リンクのクリック イベント ハンドラーを必ず追加してください。

リンクの作成

<h1>Smooth Scrolling with the jQuery Plugin .scrollTo</h1>
<div id="nav-list">
  <a href="#idElement1">Scroll to element 1</a>
  <a href="#idElement2">Scroll to element 2</a>
  <a href="#idElement3">Scroll to element 3</a>
  <a href="#idElement4">Scroll to element 4</a>
</div>

ここでターゲット要素を作成すると、最初の 2 つのみが表示され、他の見出しは同じように設定されます。別の例を見るために、ナビゲーションに戻るリンクを追加しましたa.toNav

<h2 id="idElement1">Element1</h2>    
....
<h2 id="idElement1">Element1</h2>
... 
<a class="toNav" href="#nav-list">Scroll to Nav-List</a>

スクリプトへの参照を設定します。ファイルへのパスは異なる場合があります。

<script src="./jquery-1.8.3.min.js"></script>
<script src="./jquery.scrollTo-1.4.3.1-min.js"></script>

すべてを配線する

以下のコードは、 jQuery イージング プラグインから借用したものです。

jQuery(function ($) {
    $.easing.elasout = function (x, t, b, c, d) {
        var s = 1.70158;  var p = 0; var a = c;
        if (t == 0) return b;
        if ((t /= d) == 1) return b + c;
        if (!p) p = d * .3;
        if (a < Math.abs(c)) {
            a = c;   var s = p / 4;
        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
        // line breaks added to avoid scroll bar
        return a * Math.pow(2, -10 * t)  * Math.sin((t * d - s) 
                 * (2 * Math.PI) / p) + c + b;
    };            

    // important reset all scrollable panes to (0,0)       
    $('div.pane').scrollTo(0); 
    $.scrollTo(0);    // Reset the screen to (0,0)
    // adding a click handler for each link 
    // within the div with the id nav-list
    $('#nav-list a').click(function () {             
        $.scrollTo(this.hash, 1500, {
            easing: 'elasout'
        });
        return false;
    });   
    // adding a click handler for the link at the bottom
    $('a.toNav').click(function () { 
        var scrollTargetId = this.hash;
        $.scrollTo(scrollTargetId, 1500, {
            easing: 'elasout'
        });
        return false;
    });    
});

plnkr.co で完全に動作するデモ

デモのソースコードをご覧ください。

2014 年 5 月の更新

別の質問に基づいて、 kadajから別のソリューションに出会いました。ここでは、 jQuery animateを使用して、a 内の要素にスクロールします。<div style=overflow-y: scroll>

 $(document).ready(function () {
    $('.navSection').on('click', function (e) {
        debugger;
        var elemId = "";    //eg: #nav2
        switch (e.target.id) {
        case "nav1":
            elemId = "#s1";
            break;
        case "nav2":
            elemId = "#s2";
            break;
        case "nav3":
            elemId = "#s3";
            break;
        case "nav4":
            elemId = "#s4";
            break;
        }
        $('.content').animate({
            scrollTop: $(elemId).parent().scrollTop() 
                    + $(elemId).offset().top 
                    - $(elemId).parent().offset().top
        }, {
            duration: 1000,
            specialEasing: { width: 'linear'
                    , height: 'easeOutBounce' },
            complete: function (e) {
                //console.log("animation completed");
            }
        });
        e.preventDefault();
    });
  });
于 2013-07-19T09:01:15.907 に答える