キャンバスアプリ 脳トレ漢字の間違い探しアプリの作り方 その③ 色変え・ランキング・キャッシュ

コンテンツ

はじめに

先日、夜思い付いて脳トレでよくある漢字の間違い探しのアプリをつくってみました。
その①の記事でベータ版の作成を記載しその②では拡張機能を追加しました。
その③では残りの色変えやランキング機能、ローカルキャッシュ機能の追加の部分の紹介です。

サンプル動画

YouTubeに①ベータ版と②拡張版と本記事の部分も込みの動画をアップしてます(その②と同じ動画です)


漢字間違いを探すアプリの機能について

その①、その②で以下以外の機能は実装していますので、そちらをご参考ください。
以下残った部分の実装サンプルをご紹介していきます。

  • ユーザー好みのカラーを選択できる
  • ランキング一覧を追加する
  • CLEAR履歴や選択カラーをキャッシュで保持する

ユーザー好みのカラーを選択

こちらの実装は以前の記事でご紹介もしていて、先日JPPGBで作成した「ぴーたの異世界大冒険~最後のDX~」でも使っているテクニックです。
簡単には、モダンテーマ8種をプルダウンで指定して切り替えれるようにする実装です。カスタムテーマを作ってそちらを選択することも可能です。詳細は以下の記事をご参考ください。

使用するテーマを一旦選択する

トップページの上部の空いているエリアにプルダウン(サンプルではクラシック)を追加します。

TIPS★上記記事にも書いていますが、既定のPowerApps Thema 以外のテーマは一旦選択しないと指定出来ない(インテリセンスに出てこない、指定してもエラーになる)ので、各テーマを一度選択します。

そうすると以下のように未選択時はエラーとなっているのですが、すべて選択して指定出来るようになります。

サイドリンク>テーマ(モダンをオンが前提)で表示される既定の8つのテーマをそれぞれ選択しましょう。

プルダウンにテーマを指定

選択後はすべてのテーマを指定できるようになるので、プルダウンを追加して Itemsに以下を指定します。

Code//モダンテーマを配列として指定
[PowerAppsTheme,TeamsTheme,SharePointTheme,SteelTheme,RedTheme,OrangeTheme,GreenTheme,PlatinumTheme]


次にラベルで「テーマ変更:」というのを追加します。

OnChangeで変数を設定、App.Themeに指定する

次にプルダウンのOnChangeプロパティに以下のように選択値を変数に設定します。

CodeSet(ThemaColor,Self.Selected);

App.Themeに上記の変数を指定します。

プルダウンの値を変更してそれぞれのテーマカラーとなればバッチリです。簡単ですね。

TIPSこの段階ではブラウザキャッシュの処理は入れていないので都度初期化されますが、後でキャッシュすれば選択したカラーが残った状態でスタートします。

ランキング一覧を追加する

続いてランキング機能ですが、簡単にはゲーム終了時にデータをコレクションに格納して、ランキングページを追加してそこにギャラリー表示するという内容です。

終了画面のOnVisibleに数式を追加

終了画面を開き、OnVisibleに以下数式を入れましょう。
RankingColというコレクションにユーザー名や点数、時間、現在日時、モードとサイズ(難易度)を指定してます。

CodeCollect(RankingCol,{name:User().FullName,score:Score,time:Timer.Value, date:Now(),mode:Max,size:galsize});

ランキングページを追加

終了画面を複製してランキングページを作ります。不要なものは削除して以下のようにレイアウトします。

・真ん中のコンテナーを残してランキングのラベルに修正、タブ一覧を追加してその下にギャラリーを追加
タブでどのモードの結果を出すかやモードはボタン表示で色で難易度を表すような内容にしています。

→こちらは好みなどもありますし一般的なギャラリー作っている感じなので、いかにYAMLコードを貼っておきます。真ん中のギャラリーが入っているコンテナー部分です。これを貼り付ければ再現できるはず!です。たぶん。。

ランキング画面コード
- Container2_3:
    Control: GroupContainer
    Variant: manualLayoutContainer
    Properties:
      Height: =1080
      Width: =768
      Y: =127
    Children:
    - Container4_3:
        Control: GroupContainer
        Variant: manualLayoutContainer
        Properties:
          DropShadow: =DropShadow.Bold
          Height: =955
          Width: =635
          X: =72
          Y: =62
        Children:
        - Gallery1_1:
            Control: Gallery
            Variant: BrowseLayout_Vertical_TwoTextOneImageVariant_ver5.0
            Properties:
              Items: |-
                =SortByColumns(
                Filter(RankingCol,mode=TabList1.Selected.id || TabList1.Selected.id =1)
                ,"score",SortOrder.Descending,"time",SortOrder.Ascending)
              BorderColor: =App.Theme.Colors.Darker40
              DelayItemLoading: =true
              Height: =765
              Layout: =Layout.Vertical
              LoadingSpinner: =LoadingSpinner.Data
              TemplatePadding: =0
              TemplateSize: =104
              Width: =635
              Y: =190
            Children:
            - ButtonCanvas2_1:
                Control: Button
                Properties:
                  OnSelect: =
                  BasePaletteColor: =If(ThisItem.size=5,RGBA(156, 220, 79, 1),ThisItem.size=7,RGBA(5, 102, 178, 1),ThisItem.size=9,RGBA(249, 83, 109, 1))
                  FontSize: =30
                  Text: =If(ThisItem.mode=0,"TA",ThisItem.mode)
                  Height: =57
                  Width: =81
                  X: =195
                  Y: =25
            - InfoButtonCanvas2:
                Control: InfoButton
                Properties:
                  OnSelect: =Select(Parent)
                  Content: =Text(ThisItem.date,"yyyy/mm/dd HH:mm:ss")
                  FontSize: =24
                  Height: =40
                  Width: =40
                  X: =573
                  Y: =33
            - Title1_2:
                Control: Label
                Properties:
                  OnSelect: =Select(Parent)
                  Text: =Round(ThisItem.time/1000,1) & " 秒"
                  Align: =Align.Right
                  Font: =App.Theme.Font
                  FontWeight: =If(ThisItem.IsSelected, FontWeight.Semibold, FontWeight.Normal)
                  Height: =57
                  PaddingBottom: =0
                  PaddingLeft: =0
                  PaddingRight: =0
                  PaddingTop: =0
                  Size: =30
                  VerticalAlign: =VerticalAlign.Top
                  Width: =129
                  X: =414
                  Y: =25
            - Title1_1:
                Control: Label
                Properties:
                  OnSelect: =Select(Parent)
                  Text: =ThisItem.score &" 問"
                  Align: =Align.Right
                  Font: =App.Theme.Font
                  FontWeight: =If(ThisItem.IsSelected, FontWeight.Semibold, FontWeight.Normal)
                  Height: =57
                  PaddingBottom: =0
                  PaddingLeft: =0
                  PaddingRight: =0
                  PaddingTop: =0
                  Size: =30
                  VerticalAlign: =VerticalAlign.Top
                  Width: =100
                  X: =284
                  Y: =25
            - Rectangle1:
                Control: Rectangle
                Properties:
                  OnSelect: =Select(Parent)
                  BorderColor: =App.Theme.Colors.Darker40
                  Fill: =App.Theme.Colors.Darker30
                  Height: =Parent.TemplateHeight - Separator1.Height
                  Visible: =ThisItem.IsSelected
                  Width: =4
            - Separator1:
                Control: Rectangle
                Properties:
                  OnSelect: =Select(Parent)
                  BorderColor: =App.Theme.Colors.Darker40
                  Fill: =RGBA(255, 255, 255, 1)
                  Height: =8
                  Width: =Parent.TemplateWidth
                  Y: =Parent.TemplateHeight - Self.Height
            - Subtitle1:
                Control: Label
                Properties:
                  OnSelect: =Select(Parent)
                  Text: =ThisItem.name
                  Font: =App.Theme.Font
                  FontWeight: =If(ThisItem.IsSelected, FontWeight.Semibold, FontWeight.Normal)
                  Height: =65
                  PaddingBottom: =0
                  PaddingLeft: =0
                  PaddingRight: =0
                  PaddingTop: =0
                  VerticalAlign: =VerticalAlign.Top
                  Width: =78
                  X: =110
                  Y: =21
            - Image1:
                Control: Image
                Properties:
                  OnSelect: =Select(Parent)
                  Image: =User().Image
                  BorderColor: =App.Theme.Colors.Darker40
                  Height: =72
                  RadiusBottomLeft: =8
                  RadiusBottomRight: =8
                  RadiusTopLeft: =8
                  RadiusTopRight: =8
                  Width: =72
                  X: =16
                  Y: =17
        - Label1_9:
            Control: Label
            Properties:
              Text: ="ランキング"
              Align: =Align.Center
              BorderColor: =App.Theme.Colors.Darker40
              Color: =App.Theme.Colors.PrimaryForeground
              Fill: =App.Theme.Colors.Primary
              Font: =Font.Verdana
              FontWeight: =FontWeight.Bold
              Height: =113
              Size: =40
              Width: =635
        - TabList1:
            Control: TabList
            Variant: pcfdataset
            Properties:
              FontSize: =24
              Items: =[{id:1,Text:"すべて"},{id:10,Text:"10 問"},{id:20,Text:"20 問"},{id:30,Text:"30 問"},{id:0,Text:"タイムアタック"}]
              Height: =77
              Width: =635
              Y: =113
            Children:
            - TextInput1:
                Control: PowerApps_CoreControls_TabListTemplate_dataField
                Variant: textualColumn
                Properties:
                  FieldDisplayName: ="Text"
                  FieldName: ="Text"
                  FieldType: ="s"
                  Order: =1

以下のようにランキングのギャラリーが出来ればOKかと思います。
追加で「クリア」ボタンを上部に追加しています。クリアボタンのOnSelectには以下を指定。ランキングをクリアします(併せてキャッシュもクリア)

CodeClear(RankingCol);ClearData();

トップへランキングページへのリンクを追加

トップページのフッダーエリアにランキングページへの遷移ボタンを追加します。

CodeランキングへボタンのOnSelect
Navigate(ScreenRanking)

ブラウザキャッシュ(スマホキャッシュ)を実装する

こちらについても以前の記事で何度か実装例を書いてますので併せてご参考ください。
SaveDataを使ってコレクションをローカルデータに保持し、アプリ起動時にLoadDataを使って復元します。
そうすることによりデータソースに繋がないでも一時データを保持・復元できます。

NOTE※ブラウザや機種が異なると維持されません。しばーらくすると勝手に消えますので、簡易的に一時データ保持が出来る機能とお考えください。

参考記事:

SaveDataの処理を入れる(ランキング)

まず、終了画面のOnVisibleでランキングを登録している場所で合わせてSaveDataでコレクションをキャッシュします。※名前は任意に決めてます。

Code//キャッシュに保存
IsError(SaveData(RankingCol,”localRanking”));

TIPSIsErrorで囲っているのは公開時にのみ有効に動作する数式ですので、編集時はSaveDataやLoadDataを使うとランタイムエラーが出るのでそれを防ぐためです。出てもスルーしてよいエラーなので無くてもいいですが一応入れてます。

SaveDataの処理を入れる(テーマカラー)

トップ画面のテーマ選択プルダウンのOnChangeに以下の実装を追加します。

Code//テーマ変更時にコレクションに保持
IsError(SaveData(ClearCollect(ThemaCol,{value:ThemaColor}),”localThema”));

App.OnStartにLoadDataを指定して読み込む

次にLoadDataを使ってローカルデータからコレクションに戻します。
テーマの初期値もなければPowerAppsThemeとしあれば保持したテーマを復元します。

CodeSet(galsize,5);
Set(ThemaColor,PowerAppsTheme);

//キャッシュ読み込み
IsError(
    LoadData(RankingCol,”localRanking”,true);
    LoadData(ThemaCol,”localThema”,true);
    Set(ThemaColor,Coalesce(First(ThemaCol).value,PowerAppsTheme));
)

動作を確認する

上記でランキングとテーマカラーを適用してブラウザキャッシュに保持、復元する実装が出来ました。
公開して動作確認してましょう。アプリ再起動時に前回のテーマやランキングデータが残っていればOKです。

おわりに

ということでここまでで完成です。その③は今までも記事にしたような実装だったのでざっくりな紹介でしたが、もし間違いあればご指摘くださいm(__)m

ちなみにその④をすでに作っておりそこでは絵文字モードを追加しました。子供と共同開発して結果、子供や海外の方も出来るなかなかグローバルなゲームアプリになったんじゃない?と満足です。

今回のアプリは脳トレとして自分用にローカルデータキャッシュにしてますが、チームに共有してSPOでランキングを保持したりすれば皆で競って遊べる(脳トレ出来る)ものにも出来ると思います。興味があればぜひ作成トライしてみてください!そのうちハンズオンでもやろーかなーとも思っていたりもします。それでは!

関連記事:

この記事は役に立ちましたか?

もし参考になりましたら、下記のボタンで教えてください。

ヨウセイ

ヨウセイ

一般職からSharePoint、C#、.NET系技術者へ、そこからPower App、Power Automate技術者へと転身。 ワンランク上のおっさんはPower Appsでシステム開発が出来る〜! qiitaや自社HPでも技術ブログを書いていました。

関連記事

コメント

この記事へのコメントはありません。

コンテンツ

CONTENTS