【jQuery】jQueryでカルーセルパネルを作る

jQueryでカルーセルパネルを作る方法を勉強したので、記録しておきます。
そもそもカルーセルパネルとは、画像などを横に並べて回転するように表示させるようなデザインのことを指すらしいです。初めて知りました。
#1 準備
HTML

```html
        <div id="wrap">
            <p id="prev">戻る</p>
            <p id="next">進む</p>
            <div id="panel">
                <ul id="inner">
                    <li class="item">
                        <a href="#"><img src="images/pic1.png"></a>
                    </li>
                    <li class="item">
                        <a href="#"><img src="images/pic2.png"></a>
                    </li>
                    <li class="item">
                        <a href="#"><img src="images/pic3.png"></a>
                    </li>
                </ul>
            </div>
        </div>
```
CSS(途中まで)

```css
#wrap {
    margin: 100px auto;
    width: 250px;
    height: 250px;
    position: relative;
}
#prev {
    position: absolute;
    top: 0;
    left: -50px;
    font-size: 24px;
    cursor: pointer;
}
#next {
    position: absolute;
    top: 0;
    right: -50px;
    font-size: 24px;
    cursor: pointer;
}
```
`#wrap`で要素全体のレイアウトを設定し、両サイドに戻る・進むボタン(ボタン的な装飾はしていませんが)を配置します。
結果。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912003/c8c85e45-89e7-a627-43e6-07f2e1227c6a.png" width=50%>
完成形にはほど遠いですね。
(画像はフリー素材を適当に使っているだけで、特に意味はありません)
#2 CSSの続き
CSSの続きを書いていきます。
画像が表示されるパネル部分が`#panel`、表示されないものも含めて画像全てを包括するのが`#inner`です。画像は横並びにしておきます。

```css
#panel {
    width: 100%;
    height: 100%;
    border: 1px solid black;
    overflow: hidden;
}
#inner {
    margin: 0;
    padding: 0;
}
#inner li.item {
    list-style: none;
    float: left;
}
#inner li.item img {
    width: 250px;
}
```
`#panel`について、`overflow: hidden;`として、枠の外にはみ出た画像を表示しないようにしています。

結果。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912003/3988db6d-d2d3-9e94-4e88-dc3d45275ab9.png" width=50%>
パネルの枠内に画像を収めることができました。
画像は3枚が横並びになっていますが、一番左の1枚しか枠に収まっていないので、他は表示されていない状況です。
#3 JavaScriptの記述
戻る・進むボタンを押すと画像がスライドする機能を実装します。
そのために、`#inner`の`margin-left`を増減させる、という方法を使います。
現在はマージンが0なので、`#inner`の左端は`#panel`の左端に揃っている状態です。
ここからマージンを増やせば`#inner`は右にずれ、マージンを減らせば左にずれます。

それから、先頭の画像が表示されているときに戻るボタンを押した場合のために、最後の画像を先頭画像の左側にもっていく必要もあります。最後の画像が表示されているときに進むボタンを押した場合も同様です。

これらの「マージンの増減」「画像の移動」ができるよう、コードを書いていきましょう。

```javascript
$(function(){
    //初期設定
    $("#inner").css("width", 250 * $("#inner li.item").length + "px");
    $("#inner li.item:last").prependTo("#inner");
    $("#inner").css("margin-left","-250px");

    //戻るボタンを押した場合
    $("#prev").click(function(){

    });

    //進むボタンを押した場合
    $("#next").click(function(){

    });
});
```
初期設定1行目で、`#inner`の幅を画像1個の幅(250px)×画像の枚数に設定しています。
2行目で、最後の画像を先頭に移動しています。
3行目で、`#inner`の`margin-left`を-250pxにしています。
これにより、元は画像1,2,3の順に並んでいたものを、3,1,2の順に変更しています。
マージンが減ったため、`#inner`つまり画像全体が左にずれて、真ん中の画像だけが`#panel`枠内に収まるようになりました。
表示される画像は1なので、見た目は変わっていません。

次にボタンを押した場合の機能を加えていきます。

```javascript
    //戻るボタンを押した場合
    $("#prev").click(function(){
        //一時的にボタンを隠す
        $("#next,#prev").hide();

        //マージンを増やして画像を右にずらす
        $("#inner").animate({
            "margin-left": parseInt($("#inner").css("margin-left")) + 250 + "px"
        }, "slow", "swing", 

        //それが終わったら・・・
        function(){
            //マージンを元の-250pxに戻す
            $("#inner").css("margin-left", "-250px");
            //そのままだと画像が左にずれて戻ってしまうので・・・

            //最後の画像を先頭に持っていく
            $("#inner li.item:last").prependTo("#inner");
            //こうすれば表示されている画像が変わらない！

            //最後に、ボタンを再表示
            $("#next,#prev").show();
        });
    });
```
説明はコメントに書いたとおりです。
マージンの増減と画像の移動により、画像の表示変更を実現していますね。

進むボタンも似たような感じです。

```javascript
    //進むボタンを押した場合
    $("#next").click(function(){
        $("#next,#prev").hide();
        $("#inner").animate({
            "margin-left": parseInt($("#inner").css("margin-left")) - 250 + "px"
        }, "slow", "swing", 
        function(){
            $("#inner").css("margin-left", "-250px");
            $("#inner li.item:first").appendTo("#inner");
            $("#next,#prev").show();
        });
    });
```
コメントなしです。
戻るボタンと共通点が多いので、もしかしたらコードを集約して短くできるかもしれません。

さて、これで画像をスライドして変更させることができるようになりました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912003/595645b3-294c-8578-15ad-949336a08359.png" width=50%>

#4 おまけ
画像のスライドを、マージンの増減で実現するというアイデアが面白いですね。
しかし、`#wrap`,`#panel`,`#inner`といった様々な要素が重なっており、それがどうやって動いていくのかイメージするのは難しいものです。
そこで、CSSを以下のようにしておくと、仕組みがわかりやすくなります。

```css
#panel {
    width: 100%;
    height: 100%;
    border: 1px solid black;
    /* overflow: hidden; */
}
```
はみ出た要素も表示するようにすれば・・・
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912003/ba248ea8-5b2d-5e42-59f2-c90c200b3f72.png" width=70%>
どのように動いているか、よくわかります。
#5 おわり
ちなみに私はこの本でjQueryを勉強しています。初心者でもわかりやすいです。
[Web制作の現場で使うjQueryデザイン入門](https://www.amazon.co.jp/Web制作の現場で使うjQueryデザイン入門-改訂新版-Web-Professional-Books/dp/4048913913/)