6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

watnow Advent Calendar 2024

Day 20

JavaScriptを用いた横スクロールの作り方

Last updated at Posted at 2024-12-20

はじめに

はじめまして~
学生IT団体watnow所属しています、いとうです。
開発についてはまだまだ知識足らずですがどうぞよろしくお願いします!

この記事はwatnow アドベントカレンダー2024 20日目です
(訳あって当日投稿になりました…本当に申し訳ありません...)

今回はJavaScriptを用いた横スクロールアクションの実装方法について話していこうと思います。

初投稿、初コーディング時の内容となっている為、稚拙な文ではありますがどうぞお付き合い願います。

やりたかったこと

主に左から右に画面が動く通常の横スクロールと大差ありません。
ただ、操作する際は画面を横スワイプするのではなく縦スクロールと同じ縦スワイプで横に移動する仕様を目指しました。

なぜわざわざその仕様にしたかというと、
今回制作したサイトでは最初縦スクロールから始まるようにしているので、操作の切り替えで迷って横スクロールに移った瞬間画面が動かない!...となることを無くしたかったから。
あとは純粋な「やってみたかった」好奇心が6割です。

実装してみる

基本構造

1.HTML

写真を3枚横並びで出すコードを以下のように書きました(一部省略)

index.html
<section class="picture" id="scroll">

            <div class="contents">
                <div class="horizontal_scroll">

                    <div class="picture">
                        <img src="./image/1.png" alt="1">
                        <img src="./image/2.jpg" alt="2">
                        <img src="./image/3.jpg" alt="3">
                    </div>

                </div>
            </div>

</section>
...
<script src="scroll.js"></script>

大雑把な構造としては

<section> ← idでJSと紐づけ
   <div> ← 横スクロール画面
     <div> ← 中身

で最低3つタグを用意をしていた方が見返した時に分かりやすいし、この後のCSSが書きやすくなるのでおすすめです。ページ構成を見ながら分けていきましょう!

2.CSS

cssでは、画面サイズの大きさがスクロールにとって重要な要素になります。
画面外までスクロールするため最初は感覚がつかみにくいですが、1回慣れると簡単に書くことができます!
上記(HTML記載)部分のみのコード↓

style.css
.picture {

    height: 320vh;

    .contents{
        overflow: hidden;
        position: sticky;  /* 固定 */
        top: 0;
        height: 100vh;
    }

    .horizontal_scroll {
        position: absolute;
        top: 0;
        height: 100%;
        width: 320vw;
        display: flex;
    }
    
    .pic {
        margin: auto 0px;
    }

    img {
        width: 400px;
        height: 500px;
        margin: -7px;
        border-radius: 50%;
    }
    
}

注意
ここではsectionクラスのheightは横スクロールの分も合わせて大きく取る必要があります

仕組み

簡易的な図で表すと以下の通りです。
黒=外側、白=内側

固定された外側のdivで画面のheightを設定し、内側のdiv(横スクロール部分)でwidthをsectionクラスのheightに合わせて非常に広い幅を持たせます。
外の箱が縦移動するのに合わせて内の箱を横移動させていくと画面が水平移動しているように見せることができます。

よって横スクロールでもスクロール量は window.scrollY が変化します。

これで最低限のCSSは用意できました。
次にJavaScriptを使って実際に横スクロールを行っていきます!

3.JavaScript

上記(HTML記載)部分のみのコード↓

scroll.js

const stickySections = [...document.querySelectorAll('.contents')]


window.addEventListener('scroll', (e) => {
  for (let i = 0; i < stickySections.length; i++) {
    transform(stickySections[i])
  }
})

function transform(section) {

  const offsetTop = section.parentElement.offsetTop;

  const scrollSection = section.querySelector('.horizontal_scroll')

  let percentage = ((window.scrollY - offsetTop) / window.innerHeight) * 100;

  percentage = percentage < 0 ? 0 : percentage > 300 ? 300 : percentage;

  scrollSection.style.transform = `translate3d(${-(percentage)}vw, 0, 0)`
}

コメントを忘れていたので、上から順に大まかな説明をしていきます!

1.  contents クラスを持つすべての要素を取得し、stickySections配列に格納

2. スクロールイベントが発生すると、stickySections配列内の各要素に対してtransform関数を呼び出す

transform関数は、特定のセクション要素のスクロール位置に基づいて、そのスタイルを変更するための関数です

3. offsetTop
section 要素の親要素のオフセットトップ(ページの上端からの距離)を取得

4. scrollSection
section 内の .horizontal_scrollクラスを持つ要素を取得

5. percentage
現在のスクロール位置 (window.scrollY)offsetTop の差を計算し、それをウィンドウの高さ (window.innerHeight) で割ってパーセンテージを計算し任意の範囲に制限

6. scrollSection.style.transform = translate3d(${-(percentage)}vw, 0, 0);

scrollSection の 要素を水平方向に移動
translate3d を使用して、要素を -(percentage) vw(ビューポート幅)だけ移動

この関数によって、スクロールイベントに応じて特定の要素を水平に移動させることができます。

基本的な横スクロールの説明は以上です!
JavaScriptとCSSの組み合わせで横スクロールアクションを作ることができました。

おわりに

ここまでお付き合いくださり、ありがとうございました。
今回JavaScriptを初めて触りましたが、動的表示のWebページを簡単に構築できるので思うがまま創意工夫を凝らすことができてとても面白かったです!

今回は横スクロールのみの紹介となりましたが、実は今回制作したサイトには他のイベントリスナーも多く組み合わせているので次回はそちらも紹介できたらいいなと思います!

6
0
1

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
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?