「TAURI」で「画像ビューア」のサンプルアプリを作ろう
はじめに
今回は、やっと本格的に「TAURI」アプリを開発していきます。今後は、まずWebページをデザインして、そこからフロントエンドの「JavaScript」とバックエンドの「Rust」との間でメッセージをやり取りしてプログラミングしていきます。
今回完成させる画像ビューアは、図1のように「タイトル」「新規ボタン」「開くボタン」「保存ボタン」「画像ビュー」だけがあるWebページです。画像ファイルを読み込んだり書き出したりするにはバックエンドのRustの「image」クレートを使います。
読み込む画像は、皆さんのパソコンに入っている任意のpngやjpg、bmpファイルなどを開いてみてください。
プロジェクトの作成と設定
既に第1回と第2回の設定が済んでいる前提で話を進めます。まだの方は第1回のRustの設定と、第2回のTAURIの設定を先に済ませてください。第2回でも説明したように公開するつもりなら、念のためにアイコンも変更しておいた方が良いでしょう。
まず、プロジェクトを新規作成してクレートの読み込みを追記します。次のページまでクレートは使いませんが、とりあえず先にクレートの追記を済ませておきます。
プロジェクトの作成
「Tauri」フォルダなどをカレントディレクトリにして、次のコマンドで「viewer」プロジェクトを新規作成します。ビルドには「cargo-tauri」コマンドを使いますが、とっかかりのプロジェクトの作成には従来のRustの「cargo」コマンドを使います。
・viewerプロジェクトの新規作成$ cargo create-tauri-app viewer
このコマンドを実行して作成されたviewerフォルダをカレントディレクトリにします。
ダイアログへのアクセスを許可する
TAURIの設定ファイル「src-tauri」→「tauri.conf.json」で"tauri"の"dialog"の"all"と"open"と"save"を「true」にします。これでTAURIでファイルを開くと保存するダイアログが使えるようになります。
・「src-tauri」→「tauri.conf.json」に記述{ "build": { "beforeDevCommand": "", "beforeBuildCommand": "", "devPath": "../src", "distDir": "../src", "withGlobalTauri": true }, "package": { "productName": "viewer", "version": "0.0.0" }, "tauri": { "allowlist": { "all": false, "dialog": { "all": true, "open": true, "save": true } }, (後略)
クレート読み込みの設定
この画像ビューアのバックエンドのRustではimageクレートをさらに追加します。追加するのはimageクレートの1行です。また、ダイアログも使えるように「tauri」クレートの「features」を["dialog-all"]に変更します。imageクレートのバージョンは最新バージョンでもおそらく動作すると思います。他のクレートは初期設定のままですが、第2回のTAURIのバージョンによってはこのサンプルと「tauri」クレートなどのバージョンが異なる可能性もあります。
・「src-tauri」→「Cargo.toml」ファイルに追記[package] name = "viewer" version = "0.0.0" description = "A Tauri App" authors = ["you"] license = "" repository = "" edition = "2021" [build-dependencies] tauri-build = { version = "1.5", features = [] } [dependencies] tauri = { version = "1.5", features = ["dialog-all"] } # ダイアログも使えるように serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" image = "0.23.14" # 画像を扱うクレートを追加 [features] custom-protocol = ["tauri/custom-protocol"]
Webページの作成
まず画面を作成していきます。「index.html」ファイルでWebページにタグを配置し、「styles.css」でWebページのタグを装飾して「main.js」でWebページの動作をプログラミングします。
これら3つのファイルのコードを書いたら「cargo-tauri dev」でデバッグして実行してみてください。おそらく図2のような画面が表示されましたね。まだ「開く」ボタンをクリックしても「保存」ボタンをクリックしても何も起きません。
「viewer」→「src」→「index.html」ファイル
メインの画面になるWebページ「index.html」ファイルに、次のサンプルコードを書きます。本文の「body」タグ内に「header」「h1」「button」「div」「canvas」タグを追記します。canvasタグに関してはJavaScriptからプログラミングしないと何も表示されません。
・「index.html」のサンプルコード(前略) <body> <header> <h1>画像ビューアー</h1> <button onClick="newImage()">新規</button> <button onClick="openImage()">開く</button> <button onClick="saveImage()">保存</button> </header> <div id="canvas"> <canvas></canvas> </div> <script src="main.js"></script> </body> </html>
【サンプルコードの解説】
「新規」ボタンをクリックすると、JavaScript「main.js」ファイルの「newImage」関数が呼ばれます。
「開く」ボタンをクリックすると、JavaScript「main.js」ファイルの「openImage」関数が呼ばれます。
「保存」ボタンをクリックすると、JavaScript「main.js」ファイルの「saveImage」関数が呼ばれます。
「canvas」タグで自由にグラフィックスがプログラミングできます。
「script」タグでmain.jsファイルを読み込みます。
「viewer」→「src」→「styles.css」ファイル
次のサンプルコードのように、スタイルシート「CSS」でセレクタを指定して装飾を施します。特に「こうしなければいけない」というWebデザインはないので、任意のWebデザインで構いません。例えばCSSを全く指定しないと図3のようなWebデザインになります。CSSに関しては作りこんでいく際にこだわれば良いので、後回しでも特に構いません。
・「styles.css」のサンプルコードhtml, body { font-family: "メイリオ"; color: #fff; margin: 0; padding: 0; } header { width: 100%; background-color: #000; } h1 { float: left; padding: 0 20px 0 20px; margin-top: 10px; } button { color: #000; background-color: #fff; margin: 10px 0 10px 10px; padding: 5px 10px; font-size: 20px; } #canvas { clear: both; float: left; border: solid 1px #000; margin: 10px; font-size: 0; }
【サンプルコードの解説】
「html」「body」セレクタで全体のフォントを“メイリオ”にします。フォントはmacOSやLinux向けにも設定した方が良いでしょう。
「header」セレクタで画面最上部のヘッダーに黒いバーを表示します。
「h1」セレクタでタイトル文字の位置を微調整します。
「button」セレクタで白いボタンを黒文字で装飾します。
「#canvas」セレクタで1ピクセルの太さの枠線を描画します。
「viewer」→「src」→「main.js」ファイル
次のJavaScriptのサンプルコードのようにcanvasセレクタを「_canvas」変数に保持し、2Dグラフィックスを扱う「コンテキスト」を「_context」変数に保持します。
図4のようにローカルのWebブラウザでindex.htmlファイルを開くと、TAURIやコンテキストを使おうとしてもエラーが出ますが、「cargo-tauri dev」コマンドでTAURI上ならすべてプログラムが正常に動作し、エラーなく実行できます。
・「main.js」のサンプルコードconst { invoke } = window.__TAURI__.tauri; //ファイルダイアログを扱う関数 const { open,save } = window.__TAURI__.dialog; //canvasセレクタを取得 let _canvas = document.querySelector('canvas'); //コンテキストを取得 let _context = _canvas.getContext('2d'); //新規キャンバス function newImage() { let img = _context.createImageData(_canvas.width, _canvas.height); _context.putImageData(img,0,0); } //画像ファイルを開く function openImage() { } //画像ファイルを保存 function saveImage() { }
【サンプルコードの解説】
index.htmlから呼ばれた「newImage」「openImage」「saveImage」関数を宣言します。
「newImage」関数だけcanvasを新規作成して真っ白にします。他の「openImage」「saveImage」関数は呼ばれてもまだ何もしません。