FROM CACHE - jp_header

ローディングアニメーションについて

8910
遊覧客
41 0 2

 

使用テーマは「Dawn」です。

こちらのサイトを参考にローディングアニメーションを実装したいと考えております。

参考サイト 

 

実装することはできたのですが、サイトに入る初回だけローディングアニメーションが表示されるようにしたいです。

(サイト通りに作業を進めると、画面が切り替わるごとにローディングアニメーションが表示されてしまい、逆に鬱陶しい)

具体的な対応策を知っている方がいましたら、ご教示いただけると嬉しいです。

 

サイトを参考にして行なったコード編集内容を記述しておきます。

①新しいスニペット「loader.liquid」を追加

②loader.liquidに以下を記述

 

<aside id="loader" aria-hidden="true">
 <div class="loader">
   <div class="loader__inner">

     <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
       style="margin: auto; background: rgba(0, 0, 0, 0) none repeat scroll 0% 0%; display: block; shape-rendering: auto;"
       width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
       <path d="M10 50A40 40 0 0 0 90 50A40 42 0 0 1 10 50" fill="#544747" stroke="none">
         <animateTransform attributeName="transform" type="rotate" dur="1s" repeatCount="indefinite" keyTimes="0;1"
           values="0 50 51;360 50 51"></animateTransform>
       </path>
     </svg>
   </div>
 </div>

 <style>
   @keyframes fadeInloader {
     0% {
       opacity: 0;
       visibility: hidden;
     }

     100% {
       opacity: 1;
       visibility: visible;
     }
   }

   @keyframes fadeOutloader {
     0% {
       opacity: 1;
       visibility: visible;
     }

     100% {
       opacity: 0;
       visibility: hidden;
     }
   }

   .loader {
     position: fixed;
     z-index: 2147483647;
     top: 0;
     left: 0;
     background-color: rgba(230, 230, 230, 1);
     width: 100vw;
     height: 100vh;
     opacity: 1;
     visibility: visible;
     will-change: opacity, visibility;
     animation: fadeOutloader 1s forwards;
     animation-delay: 6s;
     pointer-events: none;
   }

   .loader--fadeOut {
     animation: fadeInloader 1s forwards;
   }

   .loader__inner {
     width: 100%;
     height: 100%;
     display: flex;
     align-items: center;
     justify-content: center;
   }

   .loader__image {
     opacity: 98%;

     width: 150px;
     height: auto;
     max-height: 100%;

   }
 </style>

 <script>
   (function () {


     if (window.NodeList && !NodeList.prototype.forEach) {
       NodeList.prototype.forEach = Array.prototype.forEach;
     }

     function removeLastSlash(str) {
       let retStr = str;
       if (str.charAt(str.length - 1) === '/') {
         retStr = str.slice(0, -1);
       }
       return retStr;
     }

     function containsExcluded(class_list, excluded_classes) {
       for (let el of class_list) {
         for (let elExcluded of excluded_classes) {
           if (el.includes(elExcluded)) return true;
         }
       }
       return false;
     }

     document.addEventListener('DOMContentLoaded', () => {
       const links = document.querySelectorAll('a');
       const preloaderHtml = document.getElementsByClassName('loader')[0];
       const windowLocationPathnameTrim = removeLastSlash(window.location.pathname);
       const domain = '{{shop.domain}}';
       const permanent_domain = '{{shop.permanent_domain}}';
       const excluded_classes = ["js-", "cart", "ajax", "toggle"];
       if (preloaderHtml) {
         links.forEach(link => {
           const isExcluded = containsExcluded(link.classList, excluded_classes);
           const url = link.getAttribute('href');
           const isNewWindow = link.getAttribute('target');
           const isSameDomain = (link.hostname === domain || link.hostname === permanent_domain);
           const linkPathnameTrim = removeLastSlash(link.pathname);
           let navigatingWithinPage = true;
           if (isSameDomain) {
             navigatingWithinPage = url.startsWith('#') ||
               (linkPathnameTrim === windowLocationPathnameTrim && url.includes((link.pathname + '#')));
           }
           if (!isNewWindow && isSameDomain && !navigatingWithinPage && !isExcluded) {
             link.addEventListener('click', function (event) {
               event.preventDefault();
               const url = this.getAttribute('href');
               preloaderHtml.classList.add('loader--fadeOut');
               setTimeout(() => window.location.href = url, 1 * 1000)
             })
           }
         })
       }
     });
     // fix for safari
     window.addEventListener('pageshow', function (event) {
       if (event.persisted) {
         const preloaderHtml = document.getElementsByClassName('loader')[0];
         preloaderHtml.classList.remove('loader--fadeOut');
       }
     });


   })();
 </script>

</aside>

③「theme.liquid」の<body 〜〜>タグ直後に以下のコードを挿入

{% include 'loader' %}

 

ご協力頂ける方いましたら、よろしくお願いします!

 

9件の返信9

Qcoltd
Shopify Partner
1051 431 418

もっといい方法があるかもしれませんが、

セッションストレージを使用するのはいかがでしょうか?

 

[参考]

https://into-the-program.com/execution-firsttime-access/

https://hidekazu-blog.com/javascript-web-storage/

 

具体的に言いますと下記のようにコードを編集します。

loader.liquidの下記の部分を、

     document.addEventListener('DOMContentLoaded', () => {
       const links = document.querySelectorAll('a');
       const preloaderHtml = document.getElementsByClassName('loader')[0];
       const windowLocationPathnameTrim = removeLastSlash(window.location.pathname);
       const domain = '{{shop.domain}}';
       const permanent_domain = '{{shop.permanent_domain}}';
       const excluded_classes = ["js-", "cart", "ajax", "toggle"];
       if (preloaderHtml) {
         links.forEach(link => {
           const isExcluded = containsExcluded(link.classList, excluded_classes);
           const url = link.getAttribute('href');
           const isNewWindow = link.getAttribute('target');
           const isSameDomain = (link.hostname === domain || link.hostname === permanent_domain);
           const linkPathnameTrim = removeLastSlash(link.pathname);
           let navigatingWithinPage = true;
           if (isSameDomain) {
             navigatingWithinPage = url.startsWith('#') ||
               (linkPathnameTrim === windowLocationPathnameTrim && url.includes((link.pathname + '#')));
           }
           if (!isNewWindow && isSameDomain && !navigatingWithinPage && !isExcluded) {
             link.addEventListener('click', function (event) {
               event.preventDefault();
               const url = this.getAttribute('href');
               preloaderHtml.classList.add('loader--fadeOut');
               setTimeout(() => window.location.href = url, 1 * 1000)
             })
           }
         })
       }
     });
     // fix for safari
     window.addEventListener('pageshow', function (event) {
       if (event.persisted) {
         const preloaderHtml = document.getElementsByClassName('loader')[0];
         preloaderHtml.classList.remove('loader--fadeOut');
       }
     });

 下記のようにします。

     const keyName = 'visited';
     if (!sessionStorage.getItem(keyName)) {
     
     document.addEventListener('DOMContentLoaded', () => {
       const links = document.querySelectorAll('a');
       const preloaderHtml = document.getElementsByClassName('loader')[0];
       const windowLocationPathnameTrim = removeLastSlash(window.location.pathname);
       const domain = '{{shop.domain}}';
       const permanent_domain = '{{shop.permanent_domain}}';
       const excluded_classes = ["js-", "cart", "ajax", "toggle"];
       if (preloaderHtml) {
         links.forEach(link => {
           const isExcluded = containsExcluded(link.classList, excluded_classes);
           const url = link.getAttribute('href');
           const isNewWindow = link.getAttribute('target');
           const isSameDomain = (link.hostname === domain || link.hostname === permanent_domain);
           const linkPathnameTrim = removeLastSlash(link.pathname);
           let navigatingWithinPage = true;
           if (isSameDomain) {
             navigatingWithinPage = url.startsWith('#') ||
               (linkPathnameTrim === windowLocationPathnameTrim && url.includes((link.pathname + '#')));
           }
           if (!isNewWindow && isSameDomain && !navigatingWithinPage && !isExcluded) {
             link.addEventListener('click', function (event) {
               event.preventDefault();
               const url = this.getAttribute('href');
               preloaderHtml.classList.add('loader--fadeOut');
               setTimeout(() => window.location.href = url, 1 * 1000)
             })
           }
         })
       }
     });
     // fix for safari
     window.addEventListener('pageshow', function (event) {
       if (event.persisted) {
         const preloaderHtml = document.getElementsByClassName('loader')[0];
         preloaderHtml.classList.remove('loader--fadeOut');
       }
     });

     sessionStorage.setItem(keyName, true);
     } else {
       document.getElementById("loader").style.display = "none";
     }

インデントが適当ですので、

気になるようでしたら適宜ご修正ください。

 

タブを閉じたり、新しいタブでサイトを開くと「初回」と判定されます。

もし、任意の時間を1回の訪問と見做したい場合はCookieを利用する方法に変えればそのようにできるはずです。

 

なお、

{% include 'loader' %}

こちらで利用されているincludeは、非推奨となっていますので、

https://shopify.dev/docs/api/liquid/tags/include

{% render 'loader' %}

とされた方がより良いです。

 

ご参考まで。

(キュー田辺)

株式会社Q (キュー)
グラフィックデザイン、アパレル事業、Web制作など色々やっている渋谷区代々木の会社です。ShopifyでのECサイトの運営・開発も行なっています。
私たちについて: https://web.q-co.jp/ テックブログ: https://techlab.q-co.jp/
8910
遊覧客
41 0 2

お忙しい中返信ありがとうございます!

 

コードを編集してみたところ、だいたい5クリック目くらいから表示されなくなりました。(ばらつきあり)

大変恐縮なのですが、キッパリと2クリック目から表示されないようにする為に、他に方法を知っていましたらご教示頂きたいです!

 

お忙しいとは思いますが、ご返信お待ちしております。

Qcoltd
Shopify Partner
1051 431 418

@8910 様

 

サーバーキャッシュの影響でページによって、

追加したJavaScriptの処理が反映されていたりいなかったりするかもしれません。

それで、ばらつきが発生している可能性があります。

 

サーバーキャッシュはしばらくするとリセットされるはずですので、

時間経過とともにバラつきがなくなっていき、

初回以外はローディングアニメーションが表示されなくなるはずです。

 

解消しない場合ですが、

私の開発環境では質問者様がおっしゃっているような状態を再現できませんので、

これ以上のご提案は難しいです。

 

もし、よろしければ、

プライベートメッセージで、

現象が発生している状態を確認できるURLをお送りいただければ、

もう少し調査できるかもしれません。

 

ご参考まで。

(キュー田辺)

株式会社Q (キュー)
グラフィックデザイン、アパレル事業、Web制作など色々やっている渋谷区代々木の会社です。ShopifyでのECサイトの運営・開発も行なっています。
私たちについて: https://web.q-co.jp/ テックブログ: https://techlab.q-co.jp/
Qcoltd
Shopify Partner
1051 431 418

@8910 様

 

申し訳ございません、

元の実装のJavaScriptをしっかり読めていなかったのですが、

どうやら、参考にされたサイトのやり方ですと、

ページ内の全てのリンクにイベントを追加していまして、

リンク先が別ページだった場合、

ページ遷移が発生する前に、ローディングアニメーションが走るようでした。

 

loader.liquidの<script>を全て削除し、

下記に置き換えてみていただけないでしょうか?

 <script>
   (function () {
     const keyName = 'visited';
     if (!sessionStorage.getItem(keyName)) {
      sessionStorage.setItem(keyName, true);
     } else {
      document.getElementById("loader").style.display = "none"; 
     }
   })();
 </script>

 

上手くいかない場合はまたご連絡ください。

(キュー田辺)

株式会社Q (キュー)
グラフィックデザイン、アパレル事業、Web制作など色々やっている渋谷区代々木の会社です。ShopifyでのECサイトの運営・開発も行なっています。
私たちについて: https://web.q-co.jp/ テックブログ: https://techlab.q-co.jp/
8910
遊覧客
41 0 2

ご返信ありがとうございます!

 

今更新してみたのですが、希望通り初回のみ表示されるようになりました!

 

本当にいつもありがとうございます!

いつも返信早いですし、必ず要件を実現してくれるので感激しています、、

 

これからも何かあった際はよろしくお願いします。

r_kyu
観光客
4 0 0

お世話になります。

(横から申し訳ございません。)

 

こちらを参考にさせていただいたのですが、

私の環境では何度もアニメーションが表示されてしまいます...。

その他の原因等ありますでしょうか...?

 

現在は質問者様のコードのスクリプトの部分とローディングの際に表示する画像の部分だけ変更した状態です。

Qcoltd
Shopify Partner
1051 431 418

@r_kyu 様

 

返信が遅くなり申し訳ございません。

 

よろしければ、プライベートメッセージでやりとりさせていただき、問題が発生する状態を再現したテーマをプレビューさせていただけないでしょうか?

(必ずの解決はお約束できませんが、善処いたします。)

 

よろしくお願いいたします。

(キュー田辺)

株式会社Q (キュー)
グラフィックデザイン、アパレル事業、Web制作など色々やっている渋谷区代々木の会社です。ShopifyでのECサイトの運営・開発も行なっています。
私たちについて: https://web.q-co.jp/ テックブログ: https://techlab.q-co.jp/
r_kyu
観光客
4 0 0

お世話になります。

 

とんでもございません。ご返信いただきまして誠にありがとうございます!

ちなみにプライベートメッセージとはどこから送るものでしたでしょうか..?(無知で申し訳ございません。)

宜しくお願い致します。

 

Qcoltd
Shopify Partner
1051 431 418

@r_kyu 様

 

https://community.shopify.com/c/user/viewprofilepage/user-id/1166105

弊社のプロフィールページにアクセスいただくと、

「メッセージを送信する」

というボタンがありますので、そちらからプライベートメッセージをお送りいただけます。

 

しかし、

私から、R_kyu様にプライベートメッセージをお送りしましたので、

そちらにご返信いただければ大丈夫です。

 

よろしくお願いします。

(キュー田辺)

 

株式会社Q (キュー)
グラフィックデザイン、アパレル事業、Web制作など色々やっている渋谷区代々木の会社です。ShopifyでのECサイトの運営・開発も行なっています。
私たちについて: https://web.q-co.jp/ テックブログ: https://techlab.q-co.jp/