見出し画像

【shopify】ループスライドショーを作る方法(複数設置対応・swiper使用)

こんにちは。shopifyエンジニアのはまの(@hamanokeitarou)です。

shopifyでは標準でスライド機能がついているテーマは多いですが、ループするスライド機能がついているテーマがあまりないので、swiperを使用して作ってみました。

swiper公式サイト

swiperを使用すれば簡単に作れますが、スライドショーセクションを複数設置した時に画面幅分の表示アイテムがないと表示に不具合が出ます。
この不具合の解決法もあわせて解説しますのでよければ参考にしてみてください!

✅本記事の内容
・swiperでループするスライドショーを作る
・スライドショーセクションを複数設置する際の不具合解決法

実装完成イメージ


ループするスライドショーを作る設定手順3つ

✅設定の手順
手順1:swiperのCDN設置
手順2:htmlにswiperのclass名付与
手順3:jsファイルにswiperの設定を記述

手順1:swiperのCDN設置


まずはswiperを読込みます!
swiperをインストールする方法と、cdnを使ってライブラリを読込む方法がありますが今回はcdnを使います。
(詳しく知りたい方は「swiper 設置方法」などでググるとたくさん解説記事が出てきます!)

コチラの公式サイトからcdnをコピーしてください!

コピーしたcdn読込みコードを「theme.liquid」に貼り付けます。

✅貼付け位置
・swiper-bundle.min.cssは内に貼り付け
・swiper-bundle.min.js読み込み用コードは直前に貼り付け

wiper-bundle.min.css
swiper-bundle.min.js

これでcdnの読込はオッケーです!

手順2:htmlにswiperのclass名付与


<div class="swiper">
   <div class="swiper-wrapper">
    <div class="swiper-slide">Slide 1</div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
  </div>
</div>

これがいちばん基本の形になります!
必ずこの階層構造にしなければ機能しません。
"swiper”は任意のclass名に変更できますが、"swiper-wrapper”と"swiper-slide”は変更できないので注意!

あらかじめ横並びのセクションを作っておき、上のswiperのclass名を当てこんでいきます!
※今回はテーマエディタから選択されたコレクションの商品を表示させます。
お好みでcssを当ててください。

{% assign collection = section.settings.collection %}

<div class="swiper slide-container">
 <div class="swiper-wrapper slide-wrapper">
  {% for product in collection.products limit: 10 %}
  <div class="swiper-slide ranking-slide slide-item">
   <a href="{{ product.url | within: collection }}">
    <img src=" {{ product.featured_image | img_url:'240x' }}" alt="slide_image">
     <div class="slide-product--title">
      {{product.title}}
     </div>
   </a>
  </div>
  {% endfor %}
 </div>
 <div class="swiper-pagination swiper-pagination-card"></div>
 <!-- 前後の矢印 -->
 <div class="{% if item_count > 5 %}swiper-button-prev{% endif %}"></div>
 <div class="{% if item_count > 5 %}swiper-button-next{% endif %}"></div>
</div>


{% schema %}
 {
  "name": "slide-item-self",
  "class": "slide-item-self",
  "settings": [
   {
    "type": "text",
    "id": "title",
    "label": "title"
   },
   {
    "type": "collection",
    "id": "collection",
    "label": "Collection"
   }
  ],

 "presets": [
  {
   "name": "slide-item-self"
  }
 ]
}
{% endschema %}

これでswiperのclass名付与はオッケーです!

手順3:jsファイルにswiperの設定を記述


const swiper = new Swiper(".swiper",{
 // ここにオプションを記述
});

これが基本のコードでこれだけでスライドが機能します!
ここにオプション機能を追加していきます。

swiperは非常に多くのオプションが用意されており、全部は把握できないので必要に応じて調べて使います。
今回は以下のオプションを使用します。

const swiper = new Swiper('.swiper', {
 // ページネーション
 pagination: {
  el: '.swiper-pagination-card',
  clickable: true,
 },
 // 前後の矢印
 navigation: {
  nextEl: ".swiper-button-next",
  prevEl: ".swiper-button-prev",
 },
 // スライドのループ
 loop: true,
 // アイテムの左右はみだし
 slidesPerView: 'auto',
});

これでswiperの設定もオッケーです!
プレビューで確認するときちんとスライドショーが機能していると思います!

スライドショーセクションを複数設置する際の不具合


shopifyではお客様がテーマエディタからセクションを追加・削除できるので、当然このスライドショーセクションを複数設置することも考えられますね。
その際、表示するアイテムが画面幅に満たなければ以下のような不具合がでます。

キッズというコレクションはアイテムが2つだけです。
スライドするアイテムがないので、こんな表示崩れになってしまいます、、、

複数設置する際の不具合解消手順2つ

✅設定の手順
手順1:liquidでslide機能有無のコード出し分け
手順2:jsで画面幅を取得してswiperのclass名付与(スマホ対応)

手順1:liquidでslide機能有無のコード出し分け


いろいろ試しましたが、シンプルにliquidでコードを出し分けるのが間違いなかったです!
コードが重複してるのでムダがあるかと思いますがお許しください、、、

コレクションのアイテム5個以上はスライド有、5個以下はスライド無にします!

{%- comment -%} 5個以上商品がある商品はswiper{%- endcomment -%}
 {% if item_count > 5 %}
  <div class="swiper slide-container">
   <div class="swiper-wrapper slide-wrapper">
   {% for product in collection.products limit: 10 %}
    <div class="swiper-slide ranking-slide slide-item">
     <a href="{{ product.url | within: collection }}">
     <img src=" {{ product.featured_image | img_url:'240x' }}" alt="slide_image">
      <div class="slide-product--title">
       {{product.title}}
      </div>
     </a>
    </div>
   {% endfor %}
  </div>
  <div class="swiper-pagination swiper-pagination-card"></div>
   <!-- 前後の矢印 -->
   <div class="{% if item_count > 5 %}swiper-button-prev{% endif %}"></div>
   <div class="{% if item_count > 5 %}swiper-button-next{% endif %}"></div>
  </div>
{%- comment -%} 5個未満の商品は通常表記{%- endcomment -%}
{% else %}
<div class="slide-container">
 <div class="slide-wrapper">
 {% for product in collection.products limit: 10 %}
  <div class="swiper-slide ranking-slide slide-item">
   <a href="{{ product.url | within: collection }}">
   <img src=" {{ product.featured_image | img_url:'240x' }}" alt="slide_image">
    {% if product.metafields.custom._brand != blank %}
     <div class="slide-product--brand">
      {{ product.metafields.custom._brand }}
     </div>
    {% endif %}
    <div class="slide-product--title">
     {{product.title}}
    </div>
   </a>
  </div>
 {% endfor %}
 </div>
</div>
{% endif %}

これでPCだとスライド有のセクションと無のセクションが想定通り表示されます。
ただこのままだと、スマホやタブレットで画面幅を超えるアイテムがあっても5個以下ならスライドが機能しません、、、

手順2:jsで画面幅を取得してswiperのclass名付与(スマホ対応)


ここはjsを使ってスライドショーの幅を取得し、画面幅を超えていたらswiperのclass名を付与する処理をします。

//要素が画面幅を超えたらswiperのクラス名を付与する処理
const slideWrapper = document.querySelectorAll('.slide-wrapper');
 slideWrapper.forEach(el => {
  if(el.clientWidth > document.body.clientWidth) {
   el.classList.add('swiper-wrapper');
   const children = el.children; //.slide-wrapperの子要素
   const parent = el.parentNode; //.slide-wrapperの親要素

   for (var i = 0, len = children.length; i < len; i++) {
    // 子要素全てにclassを付与
    children[i].classList.add("swiper-slide");
   };
    // 親要素全てにclassを付与
    parent.classList.add("swiper");
 }
});

これでスマホやタブレットでも画面幅に応じてスライドショーの出し分けができるようになりました!
完成です!!

まとめ

既存テーマのスライド機能では実装できない時、swiperを使うとかなりいろいろなパターンのスライドが簡単に作れるので便利です!
この形を基本にいろいろ変形して使い回せると思うのでぜひ試してみてください!


この記事が気に入ったらサポートをしてみませんか?