こんにちは!
今回はAdobe Commerce及びMagento(以下まとめてMagentoと呼びます)での、画面のローディングマスクの制御について書いてみたいと思います。
ローディングマスク(ローディングオーバーレイとも呼ばれます)は、言わずもがな、Ajax処理や時間のかかる処理を待っている間に表示されるアニメーションとその間、画面操作を抑制する目的で画面にマスクをかけるあの機能の事です。
自前で実装するのは結構面倒なのですが、Magentoには標準でこの機能が備わっていますので簡単にローディングマスクを行うことが出来ます。
基本編
Magentoのローディングマスクは、lib/web/mage/loader.jsというjQuery UI widgetで実装されています。
mage/loaderの使用方法は、
$(セレクタ).loader({初期化の設定});
showやhideを実行して表示と非表示を行う
$(セレクタ).loader('show'); // 表示
$(セレクタ).loader('hide'); // 解除
という感じです。
また、バインドしているオブジェクトのイベントに反応して駆動するようにもなっているので、processStartイベントやprocessStopイベントがトリガーされると表示と解除が行われます。
Magentoでは既にmage/loaderウィジェットがbodyに対してバインドされており、いつでも簡単にローディングマスクを表示させることが出来ます。bodyに対して各イベントをトリガーする事で表示と解除が行えます。
$('body').trigger('processStart'); // ローディングマスクが表示される
$('body').trigger('processStop'); // ローディングマスクが解除される
※ .loader('show')の方法とprocessStartイベントの方法がありますが、Magentoではイベントを使用するのが一般的です。
試してみる
簡単なソースコードで試してみましょう。テスト用のボタンを用意して、ボタンが押されたら3秒間ローディングマスクを表示するようにしてみます。
※モジュールの構築方法については割愛(ディレクトリ構成、module.xml、registration.phpの記述など)
ブロックのテンプレート
app/code/FutureSpirits/LoadingOverlay/view/frontend/templates/loading-overlay.phtml
<p>
<button type="button" id="fs-loading-overlay-btn">
ローディングのテスト
</button>
</p>
<script type="text/javascript">
require(['jquery', 'FutureSpirits_LoadingOverlay/js/loading-overlay']);
</script>
レイアウト定義
app/code/FutureSpirits/LoadingOverlay/view/frontend/layout/default.xml
<!-- filepath: app/code/FutureSpirits/LoadingOverlay/view/frontend/layout/default.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template" name="loading.overlay" template="FutureSpirits_LoadingOverlay::loading-overlay.phtml"/>
</referenceContainer>
</body>
</page>
Javascriptソースコード
app/code/FutureSpirits/LoadingOverlay/view/frontend/web/js/loading-overlay.js
define([
'jquery'
], function ($) {
'use strict';
$('#fs-loading-overlay-btn').on('click', function () {
// ローディングを表示
$('body').trigger('processStart');
// 3秒後にローディングを非表示
setTimeout(function () {
$('body').trigger('processStop');
}, 3000);
});
});
サーバーにアップロードして適用します。
画面にボタンが追加されています。
ボタンを押すと3秒間ローディングマスクが表示されて、その後解除される事が確認できました。
mage/loaderの便利なところ。多重呼び出しでも安心。
このローディングマスクの便利なところは多重の呼び出しがあっても正しく表示と解除がされるところです。
非同期処理でプロセスAとプロセスBが処理されるとき、それぞれの表示と解除の順序を特に考える必要はありません。
mage/loaderの内部ではprocessStartで呼び出しのカウントが加算され、processStopで減算されるようになっており全ての呼び出しがprocessStopされた時点で初めてローディングマスクが解除されます。
このように、複数のプロセスから様々なタイミングでローディングマスクの表示や解除が呼び出されても不用意に解除されたり、表示されっぱなしになったりする心配がありません。
また、これを応用すると、いくつもの非同期処理が続けて処理されるような場面でローディングマスクが瞬断してチラつくのを防ぐことも出来ます。一連の処理を包括するようにして開始と終了のタイミングにprocessStartとprocessStopを入れておくと全ての処理が終わるまではローディングマスクがかかったままになるので、その間にprocessStartとprocessStopが繰り返されても画面がチラつくことがありません。
次回は、Ajax編
いかがでしたか。基本編では、ローディングマスクを表示と解除について解説しました。
processStartをトリガーするだけでローディングマスクを表示する事が出来るので簡単ですね。
次回はもう少し実践に近いところでAjaxで利用する場合について解説してみたいと思います。
勘のいい方は、processStartをしてから$.ajaxのcompleteコールバック(またはPromiseインターフェイスのalways)でprocessStopをする。みたいな想像はされているかもしれませんが、実はもっと簡単です。この続きは次回に書いてみたいと思います。