Liquid、JavaScriptなどに関する質問
使用テーマは「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' %}
ご協力頂ける方いましたら、よろしくお願いします!
もっといい方法があるかもしれませんが、
セッションストレージを使用するのはいかがでしょうか?
[参考]
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' %}
とされた方がより良いです。
ご参考まで。
(キュー田辺)
お忙しい中返信ありがとうございます!
コードを編集してみたところ、だいたい5クリック目くらいから表示されなくなりました。(ばらつきあり)
大変恐縮なのですが、キッパリと2クリック目から表示されないようにする為に、他に方法を知っていましたらご教示頂きたいです!
お忙しいとは思いますが、ご返信お待ちしております。
@8910 様
サーバーキャッシュの影響でページによって、
追加したJavaScriptの処理が反映されていたりいなかったりするかもしれません。
それで、ばらつきが発生している可能性があります。
サーバーキャッシュはしばらくするとリセットされるはずですので、
時間経過とともにバラつきがなくなっていき、
初回以外はローディングアニメーションが表示されなくなるはずです。
解消しない場合ですが、
私の開発環境では質問者様がおっしゃっているような状態を再現できませんので、
これ以上のご提案は難しいです。
もし、よろしければ、
プライベートメッセージで、
現象が発生している状態を確認できるURLをお送りいただければ、
もう少し調査できるかもしれません。
ご参考まで。
(キュー田辺)
@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>
上手くいかない場合はまたご連絡ください。
(キュー田辺)
ご返信ありがとうございます!
今更新してみたのですが、希望通り初回のみ表示されるようになりました!
本当にいつもありがとうございます!
いつも返信早いですし、必ず要件を実現してくれるので感激しています、、
これからも何かあった際はよろしくお願いします。
お世話になります。
(横から申し訳ございません。)
こちらを参考にさせていただいたのですが、
私の環境では何度もアニメーションが表示されてしまいます...。
その他の原因等ありますでしょうか...?
現在は質問者様のコードのスクリプトの部分とローディングの際に表示する画像の部分だけ変更した状態です。
@r_kyu 様
返信が遅くなり申し訳ございません。
よろしければ、プライベートメッセージでやりとりさせていただき、問題が発生する状態を再現したテーマをプレビューさせていただけないでしょうか?
(必ずの解決はお約束できませんが、善処いたします。)
よろしくお願いいたします。
(キュー田辺)
お世話になります。
とんでもございません。ご返信いただきまして誠にありがとうございます!
ちなみにプライベートメッセージとはどこから送るものでしたでしょうか..?(無知で申し訳ございません。)
宜しくお願い致します。
@r_kyu 様
https://community.shopify.com/c/user/viewprofilepage/user-id/1166105
弊社のプロフィールページにアクセスいただくと、
「メッセージを送信する」
というボタンがありますので、そちらからプライベートメッセージをお送りいただけます。
しかし、
私から、R_kyu様にプライベートメッセージをお送りしましたので、
そちらにご返信いただければ大丈夫です。
よろしくお願いします。
(キュー田辺)
サポートの選択肢が増えていく中、最適となる選択の判断が難しくなっているかと存じます。今回は問題の解決に最適となるサポートの選択方法を、紹介させて頂きます。 選択肢のご紹介...
By Mirai Oct 6, 20242023年初頭、Shopifyペイメントアカウント、及びShopifyアカウント全体のセキュリティを強化する為の変更が適用されました。ユーザーのアカウントセキュリティを強化す...
By Mirai Sep 29, 2024概要: 年末/年明けは、消費者が最もショッピングを行う時期の一つです。特に、ブラックフライデー・サイバーマンデー(BFCM)は、世界中で注目される大規模なセールイベントであ...
By JapanGuru Sep 25, 2024