ピュアJavaScriptで
スムーススクロール

プログラム概要
要素のフロート処理と、スムーススクロールの処理を組み合わせたものを、ピュアJavaScriptで制作しました。
任意の位置でフロートさせつつ、上スクロールのときだけ要素を表示させるなど、各種オプション機能を組み込んでいます。また、ヘッダ側に固定表示される要素を登録することで、要素の高さを考慮してスクロール距離が算出されますので、停止位置のズレを気にせずに手軽に済ませることができます。
機能の紹介
- フロートの機能
-
- フロートのタイミングを、数値または任意の要素のIDで指定
- ヘッダ側に積み重なるようにフロートさせる
- 特定の位置に来たらフロートを解除する
- 上スクロール時だけ表示させる
- スムーススクロールの機能
-
- アニメーション (easing 関数) の選択
- スクロール速度の調整
- 動的要素のサポートの選択
- ヘッダ側にフロートする要素分のスクロール量の調整
- イベント発火タイミングをバブリングフェーズ、キャプチャフェーズから選択
- 各タイミングで付与されるクラス
- フロート可能時:is-float_activated
フロート時:is-float_floated
スムーススクロール時:is-scrolled
| id | フロートさせる要素のID名 ※必須 [ID名] |
|---|---|
| switchPosition | 要素がフロートする位置を指定する [数値]・[対象のID名]・[null (常時表示)]・[記述無し ( 常時表示)] |
| stackId | ヘッダ側に先行して固定表示されている要素の ID 名を指定すると、その下にツライチとなるタイミングでフロートされる。 [対象の ID 名]・[記述無し] |
| float | 任意のブラウザ幅でフロート要素を活性化するか否かを指定する |
| – enabled | フロートさせるか否か [true (初期値)]・[false] |
| – range | 適用するブラウザの幅 0番目の要素:[‘max-width’]・[‘min-width’] 1番目の要素:[数値] [記述無し (常時表示)] |
| addHeight | フロート要素がフロートしているときに、フロートする前の高さを任意の要素に付け足す。 |
| – id | [対象の ID 名] |
| – direction | 高さを付け足す方向 [top]・[bottom] |
| cancel | 条件に合致したときにフロートを解除するか否かを指定する |
| – enabled | 指定のブラウザ幅のときに解除するか否か [true (初期値)]・[false] |
| – range | 適用するブラウザの幅 0番目の要素:[‘max-width’]・[‘min-width’] 1番目の要素:[数値] [記述無し (常時表示)] |
| – feature | 解除対象のフロート要素が、メインコンテンツ・サイドコンテンツどちらにあるか。 メインコンテンツ:要素が元々あった位置で解除される サイドコンテンツ:メインコンテンツの下端で解除される [main]・[side] |
| cancel – sideOptions | feature で [side] を選択時のオプション |
| – mainId | [メインコンテンツの ID 名] |
| – coordinate | イベントが発火する座標を調整するためのパラメータ [数値] |
| – absolute | side の要素に指定する position absolute の top の座標調を整用するためのパラメータ [数値] |
| scrollUp | フロート要素が上スクロールのときにだけ表示されるようにする |
| – enabled | 指定のブラウザ幅のときに、上スクロール判定を有効にするか否か。 [true (初期値)]・[false] |
| – range | 適用するブラウザの幅 0番目の要素:[‘max-width’]・[‘min-width’] 1番目の要素:[数値] [記述無し (常時表示)] |
| – feature | 要素の表示方法 マージンで調整するか、クラスを付与するか。 [changeMargin]・[addClass] |
| – marginDirection | feature で [changeMargin] を選択時に必要 マージンを調整する方向 [top]・[bottom] |
フロートプログラムのオプション記入例
var setFloatOptions = function() {
var floatOptions = [
{
id: 'floatHeader',
switchPosition: 'floatHeader',
addHeight: {
id: 'header',
direction: 'bottom',
},
},
{
id: 'floatPageLink',
switchPosition: 'floatPageLink',
addHeight: {
id: 'floatPageLinkWrap',
direction: 'top',
},
stackId: 'floatHeader',
},
{
id: 'floatFooter',
float: {
enabled: true,
},
addHeight: {
id: 'footer',
direction: 'bottom',
},
scrollUp: [
{
range: ['max-width', 767],
enabled: true,
feature: 'changeMargin',
marginDirection: 'bottom',
},
],
cancel: [
{
range: ['max-width', 767],
enabled: true,
feature: 'main',
},
],
},
{
id: 'floatToTop',
switchPosition: 300,
},
{
id: 'floatToFooter',
switchPosition: 0,
}
];
floatContent(floatOptions);
};
setFloatOptions();| easing | アニメーションの選択 [linear]・[easeOutExpo]・[easeInQuad]・[easeOutQuad]・[easeInOutQuad]・[easeInSine]・[easeOutSine]・[easeInOutSine]・[easeInCubic]・[easeOutCubic]・[easeInOutCubic]・[記述無し (linear)] |
|---|---|
| eventUseCapture | イベントの発火タイミングを、バブリングフェーズからキャプチャフェーズに変更する。 addEventListener() の第3引数『capture』を[true]にする [true]・[false]・[記述無し (false)] |
| duration | 移動速度のプロパティ |
| – anchor | リンク先への移動速度 [数値]・[記述無し (1000)] |
| – urlHash | URLハッシュリンクでの移動速度 [数値]・[記述無し (anchorで指定した数値 or 1000)] |
| dynamic | 動的要素対応のプロパティ |
| – support | 動的要素をサポートするか否か [true]・[false]・[記述無し] |
| – parentId | 動的要素を取得するためのイベントの起点 [id名]・[記述無し] [記述無し] で初期値の [document] となる |
| floatTopElem | head側にフロートする要素のプロパティ |
| – id | head 側にフロートする要素のID名 [ID名]・[記述無し] |
| – alwaysFloated | 常時フロートしているかどうか [true]・[false]・[記述無し] |
| addClass | スムーススクロール中に指定要素に [is-scrolled] クラスを付与する |
| – id | [対象の ID 名] |
| floatStatus | フロート要素に付与するクラス名のプロパティ |
| – floatedClass | フロート要素がフロートしているときに付与されるクラス [class名]・[記述無し (is-float_floated)] |
| – enabled | フロート要素として有効化させたいブラウザ幅のときに付与されるクラス [class名]・[記述無し (is-float_enabled)] |
スムーススクロールプログラムのオプション記入例
var setSmoothScrollOptions = function() {
var options = {
easing: 'linear',
duration: {
anchor: 600,
urlHash: 0,
},
floatTopElem: [
{
id: 'floatHeader',
alwaysFloated: false,
},
{
id: 'floatPageLink',
alwaysFloated: false,
}
],
addClass: {
id: ['floatFooter', 'floatPageLink'],
},
eventUseCapture: false
};
smoothScroll(options);
};
setSmoothScrollOptions();デモページについて
デモページではプルダウンから、スムーススクロール用のアニメーション(easing関数)を変更できます。
また、ヘッダ側にフロートする要素を2つ設けており、どちらも不透明になっていますので、フロートするタイミングやスクロール停止位置にずれがないかを確認できます。
制作について
- 制作目的
- 職場で利用しているスクロールスクリプトが、jQueryのよく見かけるシンプルな作りのものでしたので、ページの構成次第では望んだ位置で止まらなかったり、上から下へのスクロールは問題ないのに、下から上にスクロールすると、停止位置がずれる…といったことがあり、どうにかしたいと思いこのスクリプトを制作しました。
動的要素への対応や途中でフロートを解除する機能など、欲しい機能を思いつくたびに、少しずつ改良しています。
- 苦労したところ
- フロート要素にtransitionが掛かっていて、且つ高さが変化するスタイルが対象に含まれている場合、スクロール停止位置に誤差が出てしまうというトラブルで手こずりました。
当時は原因が全く分からず、何故か誤差が出るときと出ないときがあり、一時は諦めていました。
ですが、たまたまtransitionに原因があることを特定でき、高さを取得する際にtransitionを無効にすることで、何とか改善することができました。
- 開発環境
-
- フロントエンド
- 言語: HTML5 CSS3, JavaScript
- エディタ
- Visual Studio Code
- 製作期間
- 2018年6月~2019年10月まで随時機能を追加 (計1カ月半ほど)