概要
smooth scroll(ページ内のリンク先に、スルスルとスクロールする動き)の実装についてのメモ。
jQueryで実装
jQeryの場合は、animate
メソッドで、実装できる。
animate
の第一引数で動作、第2引数でduration(動作にかかる時間)、第3引数にeasing を指定する。
サンプル
<p><a class="js-scroll" href="#hoge">ページ内リンク</a></p>
$(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は非対応。。)
サンプル
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
関数を実行している。
サンプル
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.