質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.52%

スライドショーをループさせたい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,440

miyabeam

score 14

 やりたいこと

下記サイトの「Single Item」のようなループするスライドショーを作成したいです。
http://kenwheeler.github.io/slick/

 困っていること

スライドとドットを順番に動かすところまでは出来ました。
その先ループさせていくにはどうしたらいいかわからず困っております。
3枚目のあとに1枚目に戻る(左方向の動き)というよりは、参考サイトのように3枚目の次に1枚目が来る(右方向の動き)形にしたいです。

 現状のソース

<div class="slideBlock">
    <ul class="slider">
        <li><img src="http://placehold.jp/24/cc9999/000/300x150.png" alt=""></li>
        <li><img src="http://placehold.jp/24/99cc99/000/300x150.png" alt=""></li>
        <li><img src="http://placehold.jp/24/9999cc/000/300x150.png" alt=""></li>
    </ul>
</div>

<ul class="dots">
    <li class="is-active"></li>
    <li></li>
    <li></li>
</ul>

<button class="is-next">次へ</button>
.slideBlock {
    position: relative;
    height: 150px;
}

.slider {
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    transition: .8s all;
}

.dots {
    display: flex;

    > li {
        color: black;

        &.is-active {
            color: red;
        }
    }
}
function slideShow() {
    const slider = $('.slider');
    const slides = slider.find('li');
    const slideLength = slides.length;
    const slideWidth = slides.width();
    let slideNumber = 0;

    const dots = $('.dots li');
    const activeClass = 'is-active';

    const nextBtn = $('.is-next');

    nextBtn.on('click', () => {
        // 現在のスライド番号を更新
        slideNumber++;

        // スライドの動き
        const sliderPosition = slideWidth * slideNumber;
        slider.css('left', `-${ sliderPosition }px`);

        // ドットの付け替え
        dots.removeClass(activeClass);
        dots.eq(slideNumber).addClass(activeClass);
    });
}

slideShow();
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

「次へ」ボタン押下時に、先頭のスライドを末尾に再配置するようにすれば、実現できるかと思います。
具体的なコードは、以下の通りです。

コード

<!-- 修正なし -->
/* 修正部分のみ抜粋 */
.slider {
    position: relative;         /* absolute -> relative */
    top: 0;
    left: 0;
    display: flex;
    /* transition: .8s all; */ /* 削除 */
}

.slider li {
  position: absolute;        /* 追加 */
  /* transition: .8s all; */ /* 削除 */
}
function slideShow() {
    const slider = $('.slider');
    const slides = slider.find('li');
    const slideLength = slides.length;
    const slideWidth = slides.first().width();
    let slideNumber = 0;

    const dots = $('.dots li');
    const activeClass = 'is-active';

    const nextBtn = $('.is-next');

    //初期位置の設定
    //予め、末尾の要素を先頭に移動しておく
    const lastSlide = slides.last();
    slider.prepend(lastSlide);

    const currentSlides = slider.find('li');

    for(let i = 0; i < currentSlides.length; i++){
     const slide = currentSlides.eq(i);
     const slidePosition = slideWidth * (i - 1);
     slide.css('left', `${ slidePosition }px`)
    }


    nextBtn.on('click', () => {

        //現在のli要素を取得する
        const currentSlides = slider.find('li');

        //先頭の要素を末尾に再配置する
        const lastSlide = currentSlides.first();
        slider.append(lastSlide);

        const lastSlidePosition = slideWidth * (slideLength - 1)
        lastSlide.css('left', `${ lastSlidePosition }px`)


        //先頭~末尾1つ前(旧2番目~末尾)の要素を移動する
        for(var i = 1; i < slideLength; i++){
          const slide = currentSlides.eq(i);
           const slidePosition = slideWidth * (i - 2);
          slide.animate({left: `${ slidePosition }px`}, 800);
        }

        //末尾の要素(旧先頭の要素)も移動する
        const movedLastSlidePosition = slideWidth * (slideLength - 2)
        lastSlide.animate({left: `${ movedLastSlidePosition }px`}, 800)

        //スライド番号はループするようにする
        slideNumber++;
        slideNumber %= slideLength;

        // ドットの付け替え
        dots.removeClass(activeClass);
        dots.eq(slideNumber).addClass(activeClass);
    });
}

slideShow();

補足

元のコードは、スライドを含むul要素自体を移動していましたが、このコードでは、li要素(スライド)自体を動かすようにしています。
「次へ」ボタンを押すと、先頭のスライドを末尾に再配置し、その後、jQueryのanimate関数を使って、全てのスライドを左に動かしています。CSSのtransitionを使用しなかった理由は、先頭のスライドをappendで末尾に再配置する際に、意図しないアニメーションが発生するからです。

なお、このコードには2つの問題があります。
1つは、「次へ」ボタンを押した際に、1番左の要素がすぐに消えてしまうことです。これを解決するには、スライドの表示を適切に制御し、真ん中のスライドのみ見えるようにする必要があります。
もう1つは、「次へ」ボタンを連打できてしまうことです。スライドが移動を終える前に、さらに「次へ」ボタンが押されると、先頭のスライドが末尾に移動する際に、他のスライドの上を横切って移動するように見えます。これを解決するには、スライドが移動している間は、ボタンを反応しないようにする必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/18 09:18

    くわしくありがとうございます!

    appendがうまくいかず、原因がtransitionとは思いませんでした。
    `slideNumber %= slideLength` でループできるのはスマートでいいですね。
    大変参考になりました!

    キャンセル

-1

失礼しました
公式ドキュメント読んでます?

中学生レベルの英語で書いてあるので一度読んで見る事をオススメします。
わかんなかったらもう一度聞いて下さい。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/17 22:20

    概要欄読んでます?
    Slickを使うなんて一言も言ってないです。

    キャンセル

  • 2018/10/17 22:25

    失礼しました。自前で作っているんですね。
    ちょっと動かしてみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる