nativeなJavaScript(Vanilla JS)を使って速度が変動するスムーズスクロールを実装してみた

Keisuke Ota

こんにちは、けいすけです。

今回は、nativeなJavaScript(Vanilla JS)を使って、ページ内リンクをクリックしたときに、速度が変動する(正弦波の動きで動作する)スクロールを実装したので、共有してみたいと思います。

※ここでの正弦波の動きとは、リンク元とリンク先付近が最も遅く、中間地点が最も早い動きのことを指します。

目次 [表示する]

  1. スクロールの実装
    1. 完成形
    2. スクロール実装の考え方

スクロールの実装

完成形

完成形がこちらです。

JavaScript

                            
const scrollBtn = document.getElementsByClassName('scroll-btn');

for(let i = 0; i < scrollBtn.length; i++){
    scrollBtn[i].addEventListener('click', function(event) {
        event.preventDefault();
        let myHref = this.getAttribute('href');
        let scrollStop = document.querySelector(myHref);
        let scrollStopTop = scrollStop.getBoundingClientRect().top;
        let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
        let start = new Date();
        let time = 400;
        let intervalID = setInterval(function() {
            let elapsed = new Date() - start;
            if (elapsed > time) {
                clearInterval(intervalID);
                elapsed = time;
            }
            window.scrollTo(0, scrollStopTop * ((-1) * Math.cos((elapsed / time) * Math.PI) + 1) / 2 + scrollTop);
        }, 10);
    });
}
                            
                        

上記を実装したものがこちらです。すぐ下の見出しまで移動します。

スクロール実装の考え方

それでは、順に説明していきます。

まず最初に以下のようにして、クリックしたときに処理が行われるような記述をしていきます。

ちなみに、“getElementsByClassName()”で取得した値は、配列となるため、for文を使用しています。

今回は、スクロールによるページ遷移を行うため、リンクによるページ遷移は、”preventDefault()”を使って無効にします。

                            
const scrollBtn = document.getElementsByClassName('scroll-btn');

for(let i = 0; i < scrollBtn.length; i++){
    scrollBtn[i].addEventListener('click', function(event) {
        event.preventDefault();
        // ここにリンクをクリックしたときの処理を記述する
    });
}
                            
                        

具体的な処理内容を記述する前に、リンク先となる要素のトップの位置と、現在のスクロールの位置を以下のようにして取得します。

                            
let myHref = this.getAttribute('href');
let scrollStop = document.querySelector(myHref);
let scrollStopTop = scrollStop.getBoundingClientRect().top;
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
                            
                        

nativeなJavaScriptでアニメーションを実装するときは、以下のように“setInterval()”を使用して繰り返し処理を実装します。

以下の場合だと、10ミリ秒毎に400ミリ秒かけて、指定の処理が繰り返し行われます。

                            
let start = new Date();
let time = 400;
let intervalID = setInterval(function() {
    let elapsed = new Date() - start;
    if (elapsed > time) {
        clearInterval(intervalID);
        elapsed = time;
    }
    // ここにアニメーションさせたい処理を記述する
}, 10);
                            
                        

実装したい処理はスクロールのため、”scrollTo(x, y)”を使用します。

スクロールは、正弦波のような動きで動作させたいので、y方向のスクロール位置を経過時間に対する三角関数で記述しています。

この関数を編集することで、様々な動きのアニメーションを実装することが可能です。

                            
window.scrollTo(0, scrollStopTop * ((-1) * Math.cos((elapsed / time) * Math.PI) + 1) / 2 + scrollTop);
                            
                        

ここで、それぞれの変数は以下です。

  • scrollStopTopは、リンク先となる要素のトップの位置
  • elapsedは、イベント発生後の経過時間
  • timeは、アニメーション時間
  • scrollTopは、現在のスクロールの位置

今回は、nativeなJavaScript(Vanilla JS)を使って実装しましたが、スクロールのようなアニメーションは、jQueryを使うともっと簡単に実装することが可能です。

しかし、jQueryは、簡単に実装できる分使用量が多いと、nativeなJavaScriptに比べてファイルサイズが大きくなったり、Webページの表示速度が遅くなったりします。

Related