「TAURI」で「画像ビューア」のサンプルアプリを作ろう

2023年12月1日(金)
大西 武 (オオニシ タケシ)
第6回の今回は、本格的に「TAURI」を使ってpngやjpgファイルなどを読み込んで表示する「画像ビューア」のサンプルアプリを作っていきます。

はじめに

今回は、やっと本格的に「TAURI」アプリを開発していきます。今後は、まずWebページをデザインして、そこからフロントエンドの「JavaScript」とバックエンドの「Rust」との間でメッセージをやり取りしてプログラミングしていきます。

今回完成させる画像ビューアは、図1のように「タイトル」「新規ボタン」「開くボタン」「保存ボタン」「画像ビュー」だけがあるWebページです。画像ファイルを読み込んだり書き出したりするにはバックエンドのRustの「image」クレートを使います。

読み込む画像は、皆さんのパソコンに入っている任意のpngやjpg、bmpファイルなどを開いてみてください。

図1:今回のサンプルの完成図

プロジェクトの作成と設定

既に第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のような画面が表示されましたね。まだ「開く」ボタンをクリックしても「保存」ボタンをクリックしても何も起きません。

図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に関しては作りこんでいく際にこだわれば良いので、後回しでも特に構いません。

図3:CSSで何も装飾しない場合のWebデザイン

・「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上ならすべてプログラムが正常に動作し、エラーなく実行できます。

図4:Webブラウザでindex.htmlを実行してもコンソールにエラーが出る

・「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」関数は呼ばれてもまだ何もしません。

著者
大西 武 (オオニシ タケシ)
1975年香川県生まれ。大阪大学経済学部経営学科中退。プログラミング入門書など30冊以上を商業出版。Microsoftで大賞やNTTドコモでグランプリなど20回以上全国区のコンテストに入賞。オリジナルの間違い探し「3Dクイズ」が全国放送のTVで約10回出題。

連載バックナンバー

開発言語技術解説
第10回

「TAURI」と「Rust」の「Option型」と「Result型」を使いこなそう

2024/2/27
第10回の今回は「TAURI」や「Rust」で値なしを場合分けする「Option型」と、例外処理の代わりをする「Result型」について解説します。
開発言語技術解説
第9回

「Ace」を使って「TAURI」で「テキストエディタ」アプリを作ろう

2024/2/6
第9回の今回は、JavaScriptライブラリ「Ace」を使って、「TAURI」でテキストエディタのデスクトップアプリを開発していきます。
開発言語技術解説
第8回

「TAURI」で「ピアノ音楽」アプリを作ろう

2024/1/16
第8回の今回は、「TAURI」でピアノのUIを演奏するとピアノのサウンドが鳴るデスクトップアプリを開発していきます。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています