Chapter 08

Part 6 テーマ改修 ~新規セクションを作成(Liquid編)~

hiroki
hiroki
2021.12.14に更新
このキャプチャーでは、Part5で作成したモックアップをShopify用に書き換えていきます。Part5で作成したスライダーセクションは、Shopify(管理画面)の設定を変更しても反映されません。Shopifyとスライダーセクションを紐づけていきます。

Liquidで紐づける。

このキャプチャーは、Part5の続きになります。
schemaで設定したShopifyの管理画面の設定をスライダーセクションに反映します。
ひとつひとつ丁寧に解説していきます。

スライダーセクションの設定

- スライダーの高さ

メニューは、「最初の画像の高さに対応、小、中、大」があります。
モックアップの時点では、「小」に設定されています。

<div class="swiper-container slideshow--small">

slideshow--smallクラスを書き換えることでスライダーの高さを設定できます。
前回、貼り付けたスタイルシート(CSS)を確認してみましょう。

.slideshow--small {
  height: 175px; 
}
@media only screen and (min-width: 750px) {
    .slideshow--small{
      height: 475px; 
    } 
}
.slideshow--medium {
    height: 270px; 
}
@media only screen and (min-width: 750px) {
    .slideshow--medium{
      height: 650px; 
    }
}
.slideshow--large{
    height: 375px; 
}
@media only screen and (min-width: 750px) {
    .slideshow--large {
      height: 775px; 
    } 
}

「小(small)、中(medium)、高(large)」とクラス名がありますね。「最初の画像の高さに対応」はJavaScriptでの対応になるので、後ほど解説いたします。
Shopifyで設定した高さに合わせるように書き換えます。HTMLを以下のように書き換えてください。

<div class="swiper-container slideshow--{{ section.settings.slide_height }}">

{{}}でLiquidのオブジェクトを表示することができます。section.settings.slide_heightでschemaの画像の高さ項目の選択した値を取得することができます。

{% schema %}
    {
        "name": "スライダー",
        "class": "slide-wrap",
        "settings": [
            {
                "type": "select",
                "id": "slide_height",
                "label": "スライドの高さ",
                "default": "adapt",
                "options": [
                    {

Shopify側で値を変更して、画像(スライダー)の高さが変更されるのか確認してみてください。

- 文字サイズ

メニューは、「中、大」があります。
モックアップの時点では、「大」に設定されています。

 <h2 class="mega-title--large">Slide Title 1</h2>
 <p class="mega-desc--large">Lorem ipsum dolor sit amet, consectetur</p>

選択がメニューが2つ(中、大)しかないので、mega-title--largeクラスがあるかないかで出し分けて行きたいと思います。

if文でメニューが「大」の場合だけ、クラスをつけて対応します。

<h2 class="{% if section.settings.text_size == 'large' %} mega-title--large{% endif %}">Slide Title 1</h2>
<p class="{% if section.settings.text_size == 'large' %} mega-desc--large{% 
	  endif %}">Lorem ipsum dolor sit amet, consectetur</p>

- テキストアラインメント

メニューは、「中央、右中央、左中央」です。
モックアップの時点では、「中央」になっています。

<div class="slide-content center">
	*** 省 ***
</div>

centerのセンターの部分です。少し長いですが、以下のように書き換えてください。

<div class="slide-content 
{% if section.settings.text_alignment == 'center center' %} center {% endif %}
{% if section.settings.text_alignment == 'left center' %} left {% endif %}
{% if section.settings.text_alignment == 'right center' %} right {% endif %}
">

schemaで設定したvalueも見ておいてください。デフォルト中央に設定してあります。
valueの値が、条件分岐に使用されています。

{
	"type": "select",
	"id": "text_alignment",
	"label": "テキストアラインメント",
	"default": "center center",
	"options": [
	    {
		"label": "中心",
		"value": "center center"
	    },
	    {
		"label": "左中央",
		"value": "left center"
	    },
	    {
		"label": "右中央",
		"value": "right center"
	    }
	]
	},

- オーバーレイを表示する

オーバーレイは、画像の上に不透明の背景を表示することです。
設定すると、視覚的に見出しテキストが見やすくなるのがメリットです。
オーバーレイのHTMLは以下です。

	<div class="slide-overlay">
	</div>

「オーバーレイを表示する」はセレクトボックスタイプなので、trueとfalseで出し分けます。以下のように修正してください。

{% if section.settings.show_overlay == true %}
    <div class="slide-overlay">
    </div>
{% endif %}

外側に、条件のif文をつけることでオーバーレイ全体を表示・非表示にできます。

「スライドの自動切り替え」と「スライドの変更する間隔」は、ほとんどLiquidが関係ありませんので、後で解説いたします。

画像ブロックの設定

ブロックのschemaを確認してみます。"limit": 3と画像ブロックは、3つまで追加することができるようになっています。

        "blocks": [
            {
                "type": "slide",
                "name": "画像スライド",
                "limit": 3,
                "settings": [

ブロック数は、1つの場合もあるし、2、3つの場合もあります。
ブロック1つ分のHTMLは以下です。ブロックHTMLを管理画面で設定したブロック数分出力しなければなりません。

     <div class="swiper-slide">
         <div class="slide-overlay">
         </div>
             <img src="https://picsum.photos/500/300">
             <div class="slide-content center">
                 <h2 class="mega-title--large">Slide Title 1</h2>
                 <p class="mega-desc--large">Lorem ipsum dolor sit amet, 
   consectetur</p>
                <a href="#" class="btn slideshow__btn">ボタンのラベル</a>
             </div>
      </div>

for文で必要な数だけ回して、出力する方法が最適です。

  <div class="swiper-wrapper">
+    {%- for block in section.blocks -%}

       <div class="swiper-slide">
	     <div class="slide-overlay">
	     </div>
             <img src="https://picsum.photos/500/300">
             <div class="slide-content center">
                 <h2 class="mega-title--large">Slide Title 1</h2>
              <p class="mega-desc--large">Lorem ipsum dolor sit amet,consectetur</p>
                <a href="#" class="btn slideshow__btn">ボタンのラベル</a>
             </div>
	</div>
	
+      {%- endfor -%}
   </div>

{%- for block in section.blocks -%}を追加します。section.blocks内に設定された梶数だけ格納され、for block inのblockに1つだけ格納されていると考えてください。
なので、今後ブロック内の情報を出力するときはblock.***から書き出されていることを確認してください。

- 画像

画像は、モックの時点でサンプルの画像URLが入っています。Shopify用に書き換えます。

<img src="https://picsum.photos/500/300">

以下のように書き換えます。

{%- if block.settings.image != blank -%}
	<img src="{{ block.settings.image | img_url: '2049x' }}"  loading="lazy">
{%- else -%}
	{{ 'image' | placeholder_svg_tag: 'placeholder-svg' }}
{%- endif -%}

[画像スライドを追加する]をクリックすると画像ブロックには、画像がないのでif文で画像ありなしを分けて出し分けます。
画像がある場合は、block.settings.imageで表示します。img_urlセレクターで画像の大きさを設定します。本書で、画像の大きさはスライダーの高さで決まるので2049xに設定しています。

画像が設定されていない場合は、placeholder_svg_tagでShopifyで提供されているSVGを使用します。その他のSVGを確認したい場合は、以下のリンクを確認してください。

https://www.shopify.com/partners/blog/placeholder-images

- 見出し

モックアップは、以下のようになっています。h2タグ内のテキストをShopify用に書き換えていきます。

<h2 class="mega-title--large">Slide Title 1</h2>

以下のように書き換えてください。

<h1 class="{% if section.settings.text_size == 'large' %} mega-title--large{% endif %}">{{ block.settings.slide_title }}</h1>

※文字サイズは上記で解説しています。

- 小見出し

モックアップは、以下のようになっています。

<p class="mega-desc--large">Lorem ipsum dolor sit amet, consectetur</p>

以下のように書き換えてください。

<p class="{% if section.settings.text_size == 'large' %} mega-desc--large{% endif %}">{{ block.settings.subheading }}</p>

※文字サイズは上記で解説しています。

- ボタンのラベルとURL

モックアップの時点では、以下のようになっています。

<a href="#" class="btn slideshow__btn">ボタンのラベル</a>

以下のように書き換えてください。

<a href="{{ block.settings.button_link }}" class="slideshow__btn">{{ block.settings.button_label | escape }}</a>

URLは、aタグのhref属性内に指定してください。ラベルは、aタグ内にテキストを指定します。
さらに、ラベルやリンク先が空の場合は、ボタンを非表示にします。
以下のように条件を書き足してください。

+ {%- if block.settings.button_label != blank and block.settings.button_link != + blank -%}
   <a href="{{ block.settings.button_link }}" class="slideshow__btn">{{ block.settings.button_label | escape }}</a>
+ {%- endif -%}

JavaScriptとLiquid

スライダーのプラグイン自体にもShopifyの設定から変更を反映することができます。
スライダーセクションの「スライドの変更する間隔」の設定は、プラグインの設定を書き換えます。

- スライドの変更する間隔

スライドの変更する間隔は、Shopifyの管理画面で、3秒から9秒までを設定できるようにしてあります。

スライダーの間隔時間は、swiperのautoplayオブジェクトで設定することができます。
モックの時点では、9秒になっています。時間間隔は、ミリ秒単位で設定するようになっています。なので、9000ミリ秒を記述しています。

const swiper = new Swiper('.swiper-container', {
    // 自動再生(true:自動再生する、false:自動再生しない)
     autoplay: {
         delay: 9000,
     },

以下のように書き換えください。

const swiper = new Swiper('.swiper-container', {
    // 自動再生(true:自動再生する、false:自動再生しない)
        autoplay: {
            delay: {{ section.settings.speed }} * 1000,
        },

{{ section.settings.speed }} は3から9までの値が入ります。

以上です。間隔時間を変更して長くなったり短くなることを確認してください。

スライダーのページネーション、ナビゲーション。

Debutのスライダーをみると、まだ足りない部分があります。スライダーのページネーションとナビゲーションです。

本書の完成形は、画像のようになっています。
下部のページネーションとナビゲーションを追加していきます。

ページネーション、ナビゲーション用のHTMLを貼り付けます。

 </div><!-- swiper-wrapper -->
+ <div class="slider-other-menu">
+	<!-- 前ページボタン -->
+	<div class="swiper-button-prev"></div>
+	<div class="swiper-pagination"></div>
+	<!-- 次ページボタン -->
+	<div class="swiper-button-next"></div>
+ </div>
 </div><!-- slider-container -->
 <script>

以下をslider.liquidの<style>に貼り付けます。

+ /*ナビゲーションのカスタマイズ*/
+	.slider-other-menu{
+	    position: absolute;
+	    bottom: 10px;
+	    transform: translateX(50%);
+	    right: 50%;
+	    left: auto;
+	    width: 151px;
+	    height: 44px;
+	    background-color: rgba(0,0,0,.4);
+	    color: rgba(255,255,255,.5);
+	    z-index: 1;
+	}
+	.swiper-pagination-clickable .swiper-pagination-bullet{
+	    margin: -4px 10px;
+	}
+	.swiper-pagination {
+	    top: 4px;
+	    left: 32px;
+	}
+	.swiper-pagination-bullet-active{
+	    background: #fff;
+	}
+	.swiper-pagination-bullet{
+	    background: rgb(255,255,255);
+	}
+	.swiper-button-prev, .swiper-button-next{
+	    display: block !important; 
+	    bottom: -10px;
+	    top: auto;
+	    color: rgba(255,255,255,.5);
+	}
+	.swiper-button-next:after, .swiper-button-prev:after{
+	    font-size:15px;
+	}
+	.swiper-button-prev{
+	    left: calc(50% - 125px / 2);
+	}
+	.swiper-button-next{
+	    right: calc(50% - 155px / 2);
+	}
+

スライダーの設定(JS)も変更します。
pagination,navigationはモックの段階では、falseにしてあります。これから使用するので設定しましょう。

const swiper = new Swiper('.swiper-container', {
    // 自動再生(true:自動再生する、false:自動再生しない)
        autoplay: {
            delay: {{ section.settings.speed }} * 1000,
        },
    // スライド方向(水平方向)
    direction: 'horizontal',
    // エフェクト(true:フェードアニメーション、false:スライドアニメーション)
    effect: 'fade',
    // ループ
    loop: true,
    // 表示枚数
    slidesPerView: 1,
+    // ページネーション(true:表示、false:非表示)
+   pagination: {
+            el: '.swiper-pagination',
+            type: 'bullets',
+            clickable: true
+        },
+    // ページ送りボタン(true:表示、false:非表示)
+   navigation: {
+        nextEl: '.swiper-button-next',
+        prevEl: '.swiper-button-prev'
+   }
 });	

以上で、完了です。

DebutのスライダーでもShopifyの管理画面用のスクリプトで対策しています。確認してみてください。

https://shopify.dev/themes/architecture/sections/integrate-sections-with-the-theme-editor

スライダーの再生ボタン

まだスライダーの再生ボタンも実装していないので、実装したいと思います。
セクションの設定に、「スライドの自動切り替え」があるので再生ボタン自体を表示・非表示も実装します。

再生ボタンのHTMLを追加します。

 <div class="slider-other-menu">
        <!-- 前ページボタン -->
        <div class="swiper-button-prev"></div>
        <div class="swiper-pagination"></div>
        <!-- 次ページボタン -->
       i <div class="swiper-button-next"></div>
    </div>
+    {% if section.settings.auto == true %}
+        <p class="stopbtn stop" id="playBtn"></p>
+    {% endf %}
 </div>	

条件分岐は、「スライドの自動切り替え」のチェックボックスがtrueになっているか確認しているだけです。

以下をslider.liquidの<style>に貼り付けます。

+ /* 再生ボタン */
+ .stopbtn {
+    cursor: pointer;
+    position: absolute;
+    bottom: 10px;
+    transform: translateX(50%);
+    right: calc(50% - 220px / 2);
+    width: 44px;
+    height: 44px;
+    margin: 0px;
+    background-color: rgba(0,0,0,.4);
+    z-index: 1;
+}
+
+.stopbtn.stop {
+    display: inline-block;
+}
+.stopbtn.stop:before, .stopbtn.stop:after {
+    position: absolute;
+    top: 15px;
+    content: '';
+    width: 3px;
+    height: 15px;
+    background-color: #FFF;
+}
+.stopbtn.stop:before {
+    left: 55%;
+  }
+  .stopbtn.stop:after {
+    left: 35%;
+  }
+
+.stopbtn.start {
+  display: inline-block;
+}
+.stopbtn.start:before {
+    position: absolute;
+    top: 15px;
+    right: 13px;
+    content: '';
+    width: 0;
+    height: 0;
+    border-style: solid;
+    border-width: 7px 0 7px 14px;
+    border-color: transparent transparent transparent #FFF;
+  }
+  .stopbtn.start:after {
+    display: none;
+  }
+  @media only screen and (max-width: 750px) {
+    .slider-other-menu{
+        height: 30px;
+    }
+    .swiper-pagination{
+        top: -2px;
+    }
+    .swiper-button-prev, .swiper-button-next{
+        bottom: -17px;
+    }
+    .stopbtn {
+        right: calc(50% - 195px / 2);
+        width: 30px;
+        height: 30px;
+    }
+    .stopbtn.stop:before, .stopbtn.stop:after{
+        top: 8px;
+    }
+    .stopbtn.start:before {
+        top: 9px;
+        right: 8px;
+    }
+  }

Javascriptも追加します。再生ボタンをクリックしたら、クラス名で再生・一時停止を判断しています。その後、swiper.autoplay.stop();swiper.autoplay.start();で再生・一時停止をしています。

+    let button = document.getElementById('playBtn');
+    button.addEventListener('click', butotnClick);
+
+    function butotnClick(){
+        var _class = this.getAttribute('class');
+        if (_class == 'stopbtn stop') {
+            this.classList.add("start");
+            this.classList.remove("stop");
+            swiper.autoplay.stop();
+        } else {
+            this.classList.add("stop");
+            this.classList.remove("start");
+            swiper.autoplay.start();
+        }
+    }

再生ボタンは、以下のサイトを参考にしました。
以下のサイトは、JQueryを使用されていますが、本書ではSwiper.jsを使用しているので非JQueryに書き換えておきました。

https://naolife.online/swiper-paused-button/

以下の項目がちゃんと動作しているか確認してみてください。

  • 「スライドの自動切り替え」で、表示・非表示ができているか。
  • 再生ボタン・一時停止ボタンがちゃんと動作しているか。

スライダーの高さ

「スライダーの高さ」メニューの「最初の画像の高さに対応」を飛ばしていたので解説いたします。スライダーの高さを決めないと、再生ボタン・ページネーションの位置が不安定になってしまいます。

<style>のしたに以下のliquidを追加してください。

 </style>
+{%- if section.settings.slide_height == 'adapt' -%}
+  {%- assign first_block = section.blocks[0] -%}
+  {%- if first_block.settings.image.aspect_ratio == blank -%}
+    {%- assign min_aspect_ratio = 2.0 -%}
+  {%- else -%}
+    {%- assign min_aspect_ratio = first_block.settings.image.aspect_ratio -%}
+  {%- endif -%}
+  {% assign wrapper_height = 100 | divided_by: min_aspect_ratio %}
+{%- endif -%} 
 <div class="swiper-container slideshow--{{ section.settings.slide_height }}">

.swiper-conatinerクラスも変更します。

 <div class="swiper-container slideshow--{{ section.settings.slide_height }}" {% if section.settings.slide_height == 'adapt' %} data-min-aspect-ratio="{{ min_aspect_ratio }}"
    style="height: {{- wrapper_height -}}vw"{% endif %} id="sliderContainer">

まず、条件分岐で二つのこと確認します。

  • 「スライダーの高さ」メニューが「最初の画像の高さに対応」になってるか
  • スライダーの最初の画像が設定されているのか

Liquidでは{assgin}は変数です。
min_aspect_ratioは、画像のアスペクト比を格納しています。first_block.settings.image.aspect_ratioで最初の画像のアスペクト比を取得しています。詳細はShopifyのリファレンスをご確認ください。

https://shopify.dev/api/liquid/objects/image#image-aspect_ratio

wrapper_heightは、100をアスペクト比を割った数値がstyle="height: {{- wrapper_height -}}vwでスライダーの高さになります。
実際に、画像を登録してShopifyでプレビューでどのような値が入力されたのか確認してください。

<div class="swiper-container slideshow--adapt swiper-container-fade swiper-container-initialized swiper-container-horizontal" data-min-aspect-ratio="1.0" style="height:100.0vw" id="sliderContainer">

上記は、縦横の長さが同じ画像を登録した場合です。スタイルで高さを指定しているので再生ボタンやページネーションの位置が固定されると思います。

しかし、まだ未完成です。ページを読み込んだときはうまく動作しますが、ウィンドウサイズを変更すると縦横比が崩れてしまいます。(スタイルにheightを設定するのがページ読み込み時しか動作しないため)

以下のスクリプトいれて、対応してください。

+    var sliderContainer = document.getElementById('sliderContainer');
+    var minAspectRatio = sliderContainer.getAttribute('data-min-aspect-ratio');
+    function sliderChangeHeight(){
+        sliderContainer.style.height = 
+        document.documentElement.offsetWidth / minAspectRatio + 'px';
+    }
+    window.onresize = function(){
+        sliderChangeHeight();
+    }

ウィンドウのサイズを変更して動作を確認してください。
window.onsizeはサイズを変更するたびに発火するためブラウザがメモリーリークする可能性があります。DebutのスライダーのほうでsetTimeoutなどで対応されているのでそちらを参照してみてください。

セクションの大まかな追加手順は、

  1. schemaを記述してShopify管理画面の見た目・項目を完成させる
  2. セクション内のHTMLの雛形を記述する。
  3. css.jsを追加してモック上で動作するようにする
  4. 雛形をShopifyと関連付けたい箇所をLiquidで書き換える。