1
0

More than 1 year has passed since last update.

アンカーリンクの smooth scroll の実装

Posted at

概要

smooth scroll(ページ内のリンク先に、スルスルとスクロールする動き)の実装についてのメモ。

jQueryで実装

jQeryの場合は、animateメソッドで、実装できる。
animateの第一引数で動作、第2引数でduration(動作にかかる時間)、第3引数にeasing を指定する。

サンプル

index.html
<p><a class="js-scroll" href="#hoge">ページ内リンク</a></p>

index.js
$(function() {
  $('.js-scroll').on('click',(e) => {
    e.preventDefault();
    let $target = $($(e.currentTarget).attr('href'));
    if ($target.length > 0) {
      $('html, body').animate({
        scrollTop: $target.offset().top
      }, 500, 'swing');
    }
  })
})

JavaScriptのみで実装(IE非対応)

scrollIntoView()は、ターゲットとなる要素が見えるまで、親要素をスクロールさせるメソッド。
optionで、behavior: "smooth"を指定すると、スルスルの実装が簡単にできる。(IEは非対応。。)

サンプル

index.js
document.addEventListener('DOMContentLoaded', () => {
  let elms = document.querySelectorAll('.js-scroll');
  if (elms) {
    elms.forEach((elm) => { 
      elm.addEventListener('click', (e) => {
        e.preventDefault();
        const target = document.querySelector(e.currentTarget.getAttribute('href'));
        if (target) {
          target.scrollIntoView({
            behavior: "smooth",
          });
        }
      })
    })
  }
})

参考

scrollIntoView: https://developer.mozilla.org/ja/docs/Web/API/Element/scrollIntoView

JavaScriptのみで実装(IE対応)

setTimeoutを駆使して実装。
setTImeoutの第1引数に所定の時間がすぎた後に実行する関数を指定し、第2引数でdelayを指定する。第3引数以降は、第1引数で指定した関数に渡す引数。下の例だと、500msecを100分割した5msecをintervalとして定義し、5msec毎に、doScroll関数を実行している。

サンプル

index.js
document.addEventListener('DOMContentLoaded', () => {
  var elms = document.querySelectorAll('.js-scroll');
  var speed = 500;    //スクロール時間
  var divisor = 100;  //分割数
  var tolerance = 5;  //誤差
  var headerHeight = 0;  //ヘッダなどのオフセットを必要に応じ指定
  var interval = speed / divisor;  // speedを指定したかずで分割

  Array.prototype.forEach.call(elms, function(elm) { 
    elm.addEventListener('click', function(e) {
      e.preventDefault();
      var nowY = window.scrollY;  //Y方向の現在のスクロール量
      var href = e.currentTarget.getAttribute('href');
      var target = document.querySelector(href);
      if (target) {
        var targetRectTop = target.getBoundingClientRect().top;
        var targetY = targetRectTop + nowY - headerHeight;  //ターゲットの位置
        var minY = Math.abs((targetY - nowY) / divisor);  //現在の位置からターゲットまでのスクロール量を分割
        doScroll(minY, nowY, targetY, tolerance, interval);
      }
    })
  })
  var doScroll = function (minY, nowY, targetY, tolerance, interval) {
    var toY;
    if (targetY < nowY) {
      toY = nowY - minY;
    } else {
      toY = nowY + minY;
    }
    window.scrollTo(0, toY);
    if (targetY - tolerance > toY || toY > targetY + tolerance) {
      window.setTimeout(
        doScroll,
        interval,
        minY,
        toY,
        targetY,
        tolerance,
        interval
      );
    } else {
      return false;
    }
  };

}

DEMO

上記、3パターンのDEMOです。

See the Pen Sample Smooth Scroll by iiishokoiii (@iiishokoiii) on CodePen.

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0