サーバー構築不要!スマートフォンアプリ向けの新クラウド

トップ >ドキュメント >チュートリアル(JavaScript):Monacaでクイズアプリを作る(後半)

チュートリアル(JavaScript)

ドキュメント内検索

Monacaでクイズアプリを作る(後半)

概要

前半では、データの保存と会員登録を実装していきました。
チュートリアルの後半では、前半の内容も利用して簡単なクイズアプリを作成していきます。

クイズアプリの機能は以下のとおりです。

  • クイズに挑戦する
  • クイズを作成する
  • 連続正解数のランキングを表示する(会員登録が必要)

クイズの作成・会員登録については前半で実装したデータの保存・会員登録と
同じ内容なため、機能を実装している状態からチュートリアルを開始していきます。

プロジェクトをインポートしてくる

すでにクイズの投稿部分と、会員登録・ログイン画面が実装済みの
プロジェクトをインポートしていきます。

こちらからzip形式のプロジェクトファイルをダウンロードします。

Monacaの画面にて左上にあるMonacaのロゴをクリックし、「プロジェクトの作成」をクリックすると、
プロジェクトの作成画面が開きます。

右上にある「Import Project」ボタンをクリックすると、
プロジェクトのインポート画面が開くので、

  1. プロジェクト名に「quiz」と入力
  2. ダウンロードしたzipファイルのパッケージアップロード

を行ってインポートを実行してください。
インポートに成功すると、プロジェクト一覧画面に
quizプロジェクトが作成されるので、IDEを開きます。

インポート完了

mobile backendのダッシュボードを開き、
左メニューの「設定」をクリックするとキーが表示されます。

mobile backendのキーを確認

Monacaに戻ってquiz.jsを開き、mobile backendのアプリケーションキーと
クライアントキーを設定してください。

キーの設定

ここまででMonacaデバッガーを起動してください。

スタートボタンをクリックし、会員登録することができます。
メニュー画面が表示されたら、mobile backendの会員管理を開き、
会員登録がされているか確認しましょう。

スタート画面

クイズ画面を作成する

サンプルコードを参考に、
以下のファイルを編集してください。(済み)

  • quiz.js:クイズの処理を記述しているJavaScriptファイル
    • selectQuizメソッド:クイズをmobile backendから取得するメソッド
  • answerQuiz.html:問題やクイズの判定を行う画面

を書き換えてください。(済み)
コーディングが終わったら、Monacaデバッガーで動作を確認してみてください。

【動作確認手順】

  1. 会員登録/ログインをする
  2. クイズをいくつか登録する
  3. クイズを解く

クイズ画面

正解すれば、次の問題を開くボタンが表示されます。
間違えれば、メニューボタンが表示されます。

クイズ画面

ここまでの解説

前半と異なるページ遷移の方法について

後半のクイズアプリでは、ページスタック方式を用いて画面遷移を管理しています。
ベースとなるindex.htmlの上に、遷移するページをスタックしていきます。

  • pushPage("ページ名"):現在表示されているページに指定したページを重ねる
  • popPage():現在表示されているページを取り除いて、下にあるページを表示する

pushPageとpopPageは、index.htmlにあるons-navigatorタグの中で
ページ遷移させるためのオブジェクトを用意することで実行することができます。

以下のサンプルコードはクイズアプリのindex.htmlですが、
ons-navigator内でquizNaviというオブジェクトを用意しています。
こうすることで、任意の箇所でquizNaviオブジェクトが利用できるようになります。

<body>
    <ons-navigator title="Navigator" var="quizNavi" page="home.html">
    </ons-navigator>
</body>

menu.htmlでは、クイズに挑戦するための画面
(さっきコーディングしたanswerQuiz.htmlです)に遷移する処理と
クイズを作成する画面(createQuiz.html)に遷移する処理が
ボタンを押された時に実行されるよう記述されています。

<ons-button id="answer_quiz_button" onclick="quizNavi.pushPage('answerQuiz.html')">
クイズを解く!
</ons-button>
<br/>
<br/>
<ons-button id="create_quiz_button" onclick="quizNavi.pushPage('createQuiz.html')">
クイズを作る!
</ons-button>

OnsenUIの要素をJavaScriptで動的に表示する場合

OnsenUIのボタンなどを、JavaScriptなどで動的に配置したい場合は
そのままjQueryのappendメソッドなどを実行してもスタイルが適用されないため、
以下の手順でコンポーネントのコンパイルが必要です。

  1. 表示させたいコンポーネントをDOMツリーに配置する
  2. ons.compileメソッドを実行する

クイズに正解したときや間違えたときのボタンは上記の手順に従って表示しています。
そのコードが以下となります。

//メニュー画面に遷移するボタンを表示させる
var btn = $("<ons-button onclick='quizNavi.resetToPage(\"menu.html\")'>メニューに戻る</ons-button>");
btn.appendTo($("#question"));
ons.compile(btn[0]);

端末の機能を利用してみる

クイズに間違えた場合、端末が振動するようにしています。
バイブレーションの制御を使用する場合には、Monaca クラウド IDE の [ Cordova プラグインの管理 ] 上で、Vibration プラグインを 有効 にします。

バイブレーション

処理を実装しているのは以下の1行だけです。
(端末の振動を確認する場合は、実機で行ってください。)

//間違い時に端末を振動させる(振動する時間(ミリ秒単位))
navigator.vibrate(1000);

他にもカメラや端末のセンサーなどを簡単にアプリに組み込めるのも、Monacaの特徴です。

クイズの取得

mobile backendからクイズの取得(=データの検索)を行う場合は、
NCMB.Query(クエリ=検索要件を設定したもの)を利用します。

var quizSize = 0;
//クイズを検索する
function selectQuiz(){
    //クイズを検索するncmb.Queryクラスのインスタンスを作成する
    var QuizClass = ncmb.DataStore("Quiz");

    //指定された条件に合致するクイズの件数を調べる
    QuizClass.count().fetchAll()
                     .then(function(objects){
                            //登録されたクイズの数を保持する
                            quizSize = objects.count;                          
                     })
                     .catch(function(error) {
                            // エラー
                            console.log("error:" + error.message);                          
                     });

    //作成したクエリに条件を設定する
    QuizClass.skip(Math.floor(Math.random() * quizSize))
             .fetch()
             .then(function(result){
                displayQuiz(result);      
             })
             .catch(function(error) {
                console.log("error:" + error.message);
             });
}

上のサンプルコードは、作成していただいたselectQuizメソッドです。
今回のクイズアプリでは、skipやlimitなどの条件を設定したあとに、
findメソッドでクイズを検索して取得しています。
ほかにも「値が○○と一致するか」や、「○○以上・以下」などの検索条件を設定することができます。

(発展)ジャンルを絞って出題してみる

以下の手順を行って、ジャンルを絞ってクイズを表示してください。
ジャンルを指定するためのクエリの利用方法については、
こちらのドキュメントをご覧ください。

【手順】
1. 登録されているクイズにジャンルのフィールドを追加する
2. 各クイズにジャンルを設定する。
3. クイズを検索するときの条件にジャンルを指定する

連続正解数のランキングを表示する

サンプルコードを参考に、
以下のファイルを編集してください。(済み)

  • quiz.js
  • menu.html

コーディングが終わったら、Monacaデバッガーで動作を確認してみてください。

クイズに挑戦して、間違えた時に連続正解数が保存されるようになります。
このスコアはクイズに間違える度に更新されます。

自分のスコア表示

ここまでの解説

イベントの登録について

ボタンのクリック時などにメソッドの呼び出しをしていないのに実行される処理があります。
それはページの読み込み時にクイズを表示する処理やランキングを表示する処理などです。

OnsenUIの子ページは、読み込みが完了すると「pageinit」というイベントを発生させます。
このpageinitイベントの発生に合わせてクイズの表示やランキング表示を行うことで、
ページの読み込み完了時に実行されるようになっています。

イベントの登録は以下のように、onメソッドを利用して

  • 発生を監視するイベント名
  • 処理を実行したいページid
  • イベント発生時に実行する処理

を登録しておくと、実行されるようになります。

//mobile backendのAPIキーを設定
var ncmb = new NCMB("YOURAPPKEY","YOURCLIENTKEY");

//ページの初期化が完了したら実行される
$(function (){

    //クイズを表示するイベントを登録
    $(document.body).on('pageinit', '#answer_page', function() {refreshQuiz();});

    //クイズ作成ボタンを表示するイベトを登録
    //HTMLに記述したボタンはJSで操作できない
    $(document.body).on('pageinit', '#create_quiz_page', function() {displayButton();});

    //スコアを表示するイベントを登録★
    $(document.body).on('pageinit', '#menu_page', function() {findScore();});

});
友達(他ユーザー)のスコアも表示するにはACLの設定が必要

mobile backendから各ユーザーのスコアを検索する部分のコードは以下の通りです。

//会員クラスを検索するクエリを作成
    ncmb.User.order("score", true)
        .limit(5)
        .fetchAll()
        .then(function(results){
                //検索が成功した場合は会員情報のリストをdisplayRankingメソッドに渡す
                displayRanking(results);              
        })
        .catch(function(error){
                console.log("error:" + error.message);   
                if(error.status == "401") {
                    logout();
                    //未ログインの場合はログイン画面を表示
                    quizNavi.pushPage("login.html", options);
                }
        });

ここで、ほかの会員として再ログインして複数のスコアを表示してみてください。

クイズを表示するためにmobile backendからクイズデータを検索した時とほぼ同じで、
スコアの降順でソートしたデータを取得することと、5件のデータを取得する条件以外は
設定していないにも関わらず、現在の動作では自分のスコアのみが表示されるだけの状態です。

これは、各ユーザーデータがそのユーザーとしてログインしている場合にしか
アクセスできないようにデータストアで制御されているからです。
このようなアクセス制御を行なう仕組みをmobile backendではACLと呼んでいます。

他のユーザーデータも検索してランキングを表示するためには、ACLを「全員が読み取り可能」に設定します。

ダッシュボードの会員管理を開き、表の一番右側にある「acl」フィールドに書かれている「パーミッション編集」をクリックしてください。
以下のようにACLを設定する画面がポップアップするので、
新しいパーミッションを作成し、全員が読み取り可能になるよう設定してください。

パーミッション設定

この設定は、アプリでも可能です。
以下のコードは、会員登録を行なう処理の部分です。

//会員のインスタンスを作成
    var user = new ncmb.User();

    //ユーザー名とパスワードとスコアをインスタンスに設定
    user.set("userName", userName)
        .set("password", password)
        .set("score", 0);

    //会員登録を実行し、上で設定されたコールバックが実行される
    user.signUpByAccount(callBack_Account);

上のコードでは、会員のインスタンスにユーザー名とパスワード、スコアをセットしていますが、
以下のようにACLをセットすることで会員登録時にACLの設定を行います。

//ログインを実行したあとのコールバックを設定
    var callBack_Login = function(error, obj) {
        if (error) {
            //エラーコードの表示
            $("#login_error_msg").text("errorCode:" + error.code + ", errorMessage:" + error.message);
        } else {

            // ----------------------------------> ここから追加するコード 
            //現在の登録ユーザー取得
            var user = ncmb.User.getCurrentUser();
            //ACLの設定を行う
            var acl = new ncmb.Acl();
            //登録ユーザーに対するアクセス制御(読み込みと更新可能)
            acl.setUserWriteAccess(user,true);
            acl.setUserReadAccess(user,true);
            //全員に対するアクセス制御(読み込み可能のみ)
            acl.setPublicReadAccess(true);
            user.set("acl", acl);
            user.update()
                .then(function(obj){
                    //なし
                })
                .catch(function(error){
                    console.log("error:" + error.message);
                });
            // ----------------------------------> ここまで追加するコード
                 
            //メニュー画面に遷移
            quizNavi.pushPage("menu.html");
        }
    }

ACLの設定をアプリで行う場合は、NCMB.Userクラスを引数にセットしたり、
上のサンプルコードのようにJSON形式でACLをセットしていきます。
「*(アスタリスク)」を指定することで、全ユーザーに対するアクセス制御を設定することも可能です。

ACLの設定が完了すると、以下のように連続正解数のランキングが表示されます。

ランキング表示

まとめ

今回のチュートリアルでは、

  • データストアを利用したクイズの実装
  • 会員管理を利用したランキングの実装

を行ってきました。他にもmobile backendの機能を利用するとクイズアプリを以下のように工夫することができます。

  • 写真を使ったクイズ
  • Facebookアカウントでの登録
  • イベント発生時のプッシュ通知配信(Monacaで実装するには有料プランが必要)

Monacaで効率的にハイブリッドアプリを開発し、ニフティクラウドmobile backendを利用することで
バックエンド機能の構築・運用のコストを削減していきましょう!

参考URL

お探しの内容が見つからなかった場合はユーザーコミュニティ もご活用ください。(回答保証はいたしかねます)
なお、 Expertプラン以上のお客様はテクニカルサポートにてご質問を承らせて頂きます。

推奨画面サイズ1024×768px以上

ページの先頭へ