SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Windowsで進化するマルチプラットフォームGUI開発

初めての「.NET MAUI Blazor」──デスクトップとモバイルに対応した簡単なアプリを作成しよう

Windowsで進化するマルチプラットフォームGUI開発 第4回

  • X ポスト
  • このエントリーをはてなブックマークに追加

SVGアニメーションページ

 テンプレートアプリのMain.razorでは、さらに、サイドメニューを持つレイアウトのページが定義されています。今回は、 新規ページを作成して、メニューから表示するようにします。

 作成するページは、SVG画像を使った時計のようにアニメーションするページです。

SVGアニメーションページ(Windows)
SVGアニメーションページ(Windows)

新規ページ

 プロジェクトのPagesフォルダに、Razorコンポーネントとして、Svg.razorファイルを新規作成します。

Razorコンポーネントの追加
Razorコンポーネントの追加

 Svg.razorのコードは、次のようにしました。

[リスト4]Svg.razor
@page "/svg"
@implements IDisposable

<svg width="400" height="260">
    <circle cx="150" cy="150" r="100" stroke="yellow" stroke-width="3" fill-opacity="0" />
    <line x1="150" y1="150" x2=@cx y2=@cy stroke="black" />
    <circle cx=@cx cy=@cy r="10" stroke-width="0" fill="red" />
</svg>

@code {
    // 円周の座標
    private int cx = 0;
    private int cy = 0;

    // 角度
    private int angle = -90;

    private Timer aTimer;

    // 0秒後、1秒毎にCallbackが実行される(1)
    protected override void OnInitialized() =>
        aTimer = new Timer(Callback, null, 0, 1000);

    // 座標の更新(2)
    private void Callback(Object _)
    {
        cx = (int)(Math.Cos(angle * Math.PI / 180f) * 100f) + 150;
        cy = (int)(Math.Sin(angle * Math.PI / 180f) * 100f) + 150;

        angle += 6;

        InvokeAsync(StateHasChanged);
    }

    public void Dispose() => aTimer.Dispose(); // timerオブジェクトの破棄
}

SVG要素

 <svg>から始まる要素が、SVG要素となります。SVG(Scalable Vector Graphics)は、ベクターイメージ用の画像形式の1つで、XMLベースで記述します。モダンブラウザであれば、SVGの描画をサポートしていて、HTML要素として記述するだけで、画像を描画することができます。今回は、赤と黄の円画像<circle>と、黒の直線<line>を記述しています。SVG要素の属性についての詳細は、参考文献で確認してください。

タイマー処理

 今回は、1秒毎に円画像と直線の座標を計算して描画しています。1秒毎の処理には、Timerクラス(System.Threading.Timer)を用いました。.NETで提供されるTimerクラスはいくつかありますが、ここでは、System.Threading.Timerクラスを選択しました。

 System.Threading.Timerクラスでは、コンストラクタで、呼び出されるメソッドとそのメソッドに渡すパラメータ、それと最初の実行までの時間と、実行される周期を指定します。先ほどのSvg.razorでは、Callbackメソッドを0秒後と1秒間隔で呼び出されるようにしています(1)。時間の単位は、ミリ秒です。

 円周に表示する赤い円画像の座標は、三角関数から求めます。また、1秒ごとに中心と円画像の座標との角度を6°加算し、1分で1周(360°)するようにしました(2)。

 なお、IDisposableインターフェイスを実装して(@implements IDisposable)、ページが破棄される際に、Disposeメソッドでtimerオブジェクトのリソースを破棄するようにしています。

SVGアニメーション(Android)
SVGアニメーション(Android)

メニュー追加

 メニューに、先ほど作成したページを表示する項目を追加します。

[リスト5]NavMenu.razor
~略~
<nav class="flex-column">
~略~
    <div class="nav-item px-3">
        <NavLink class="nav-link" href="svg">
            <span class="oi oi-list-rich" aria-hidden="true"></span> SVGの描画
        </NavLink>
    </div>
</nav>
~略~

 これで、以下のようにメニューに追加されます。

メニュー表示(Android)
メニュー表示(Android)

開始、停止ボタン

 メニューの「SVGページの描画」を選ぶと、アニメーションがすぐに開始されたはずです。これを少し変更して、ボタンのクリックで、開始/停止するようにしてみましょう。

 まず、HTML部分に、次のような開始と停止ボタンを追加します。

[リスト6]Svg.razor
~略~
<button class="btn btn-primary" @onclick="OnStart">開始</button>
<button class="btn btn-primary" @onclick="OnStop">停止</button>
~略~
ボタン追加
ボタン追加

 button要素の@onclick属性で、ボタンクリック時に実行されるメソッドを定義しています。ここでは、開始ボタンでOnStart、停止ボタンでOnStopメソッドが呼び出されます。この2つのメソッドの定義は、次のようになります。

[リスト7]Svg.razor
~略~
@code {
    // 0秒後のみCallbackが実行される(3)
    protected override void OnInitialized() =>
        aTimer = new Timer(Callback, null, 0, Timeout.Infinite);

~略~

    // 0秒後、1秒毎にCallbackが実行される
    private void OnStart() => aTimer.Change(0, 1000);

    // Callbackが実行されない
    private void OnStop() => aTimer.Change(Timeout.Infinite, Timeout.Infinite);
}

 TimerクラスのChangeメソッドは、タイマーの開始されるまでの時刻と、メソッドの呼び出し周期を変更することができます。パラメータにTimeout.Infiniteを設定すると、メソッドがまったく呼び出されなくなり、アニメーションが停止します。

 なお、ページの初期化時にタイマーが開始されないように、Timerオブジェクトのコンストラクタの周期のパラメータを変更します(3)。

ボタンクリックで開始
ボタンクリックで開始

最後に

 .NET MAUI Blazorでは、BlazorWebViewコントロールを用いて、Razorコンポーネントをレンダリングしています。Webサーバやブラウザを介することなく、直接.NETコンポーネントが利用できます。

 (MAUIではない)Blazorアプリケーションでは、PWA(Progressive Web Apps)と呼ばれる、Webアプリをネイティブアプリのようにインストールできる技術に対応していますが、.NET MAUI Blazorでは、Web技術を活用したネイティブアプリの開発が可能です。

参考文献

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Windowsで進化するマルチプラットフォームGUI開発連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16737 2022/11/07 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング