LoginSignup
6
9

More than 5 years have passed since last update.

AngularJS+spin.jsでOverlay(後編)

Posted at

前回はspin.jsとangular-spinnerでAngularJSでぐるぐるアニメーションを出すところまでやった。
今回は、それを出しながら、背景を黒の半透明にして操作を不能にするようにする。

サービス化する

前回ではコントローラの中でangular-spinnerを呼び出していたけど、毎回コントローラに処理を書くのはめんどいのでfactoryを使ってサービス化しちゃおう。

overlay.js
angular.module('overlayModule',['ui.bootstrap','angularSpinner'])
    .factory('overlay',function($uibModal,usSpinnerService){
        return {
            show:function(){
                /*ここに表示処理*/
            },
            hide:function(){
               /*ここに停止処理*/
            }
        }
    }
);

このようにサービスを定義しておくことで、他のコントローラから使いやすくする。
また、今回の処理にはui.bootstrapのuibModalを使いますので依存モジュールとサービスを指定。
今、さらっと出しちゃいましたが、UI Bootstrapを使ってますので、そちらもダウンロードして配置と読込を。

表示処理

まず、普通にモーダルを呼んで、spinnerを起動するような処理を作る。

overlay.js
modalInstance = $uibModal.open({
                    templateUrl: '/overlay.html',
                    backdrop: 'static',//クリックしても閉じないようにしたいのでstatic
                });
usSpinnerService.spin("overlay-spinner");
overlay.html
<div>
    <span us-spinner="{radius:30, width:8, length: 16}" spinner-key="overlay-spinner"></span>
</div>

んで、コントローラから読んでみる

angular.module("App",["angularSpinner"])
    .controller("appController",
            ["overlayModule",
                function(overlay){
                    overlay.show();
                }
            ]
    );

すると
overlay2.png

あるぇ?黒の半透明にはなって、クリックとかは効かなくなったけどアニメーションが出ていない。

描画タイミングの問題

実はモーダルの処理として、呼び出し元のhtmlに表示させるhtmlの中身を読み込んでいるみたいなんだけど、非同期に動いているのかusSpinnerService.spin("overlay-spinner");が呼び出された後に読み込んでいるみたい。
つまり、spin処理が呼ばれたタイミングではovarlya.htmlの中身が読み込まれていないことになる。

これを解決するためにはモーダルの描画後に呼ばれるrenderedイベントを使ってspin処理を呼び出す。

modalInstance.rendered.then(function(){
                    usSpinnerService.spin("overlay-spinner");
                });

こうすれば、モーダルの描画後にspin処理が動くはず。
image

おおっと、アニメーションは表示されたけど、画面上部が埋まっていたり、変な線が出ていたりする。

レイアウト問題

どうやら、モーダルの内容表示箇所の位置が画面上部だったり、表示すべき内容がないために線みたいになっていたりするようです。
解決策としては、cssで位置を調整してやればOK。
モーダルとして埋め込まれたhtmlは.modal-contentをクラスに持つdivの中に入るようなので、これに対してスタイルを定義してやればいい。

ただし、そうすると今度はモーダルの上にオーバーレイを出したいときに、(隠される方の)モーダルも影響を受けて表示が崩れることが考えられる。
そのため、modalのopenのオプションとしてwindowClass: 'overlay'を指定してやり、.overlay .modal-contentに対して、スタイルを指定していくと綺麗にモーダル上のoverlayも上手くいきます。
overlay.png

hideの方の処理はそんなに語ることもなく、spinを止めてモーダルを閉じるだけ。

結論

最終的にはこんなコードになります。

overlay.js
angular.module('overlayModule',['ui.bootstrap','angularSpinner'])
    .factory('overlay',function($uibModal,usSpinnerService){
        var modalInstance = null;
        return {
            show:function(){
                modalInstance = $uibModal.open({
                    templateUrl: '/overlay.html',
                    backdrop: 'static',
                    windowClass: 'overlay'
                });

                //レンダリング終了後にspinner起動
                modalInstance.rendered.then(function(){
                    usSpinnerService.spin("overlay-spinner");
                });
            },
            hide:function(){
                usSpinnerService.stop("overlay-spinner");
                modalInstance.close();
            }
        }
    }
);
overlay.html
<style>
    .overlay .modal-content{
        margin-top:40%;
        background-color:transparent;
        border:none;
    }
</style>

<div>
    <span us-spinner="{radius:30, width:8, length: 16}" spinner-key="overlay-spinner"></span>
</div>

これで、コントローラ側から呼び出してオーバーレイができるようになるので、ajax処理中など時間がかかる処理の時に使えます。

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9