
Flutterを使ったDesktop基盤アトラス化アプリ作成
-
2023年9月12日
こんにちは。サービス基盤開発室でクライアントエンジニアをしているSです。
今回はFlutterを使ってアプリケーションを作った結果と感想を皆さんに共有したいと思います。
開発環境はVisual Studio Code1.80.2、Flutterは3.10.0です。
Flutterとは?
Googleから2017年に公開されたmobile/web/desktopクロスプラットフォームSDKです。
一つのコードベースでandroid、ios、 macOS、 windowsで動作するアプリを作ることができるのが特徴です。
言語はGoogleがデザインしたDartを使います。
Flutterの特徴
クロスプラットフォーム
上述のように、Flutterは一つのコードで色んなプラットフォームのアプリを作ることができます。
もちろん特定のプラットフォームのみ対応したパッケージなどもありますが、ほとんどの機能はすべてのプラットフォームに対応しているので生産性が高いといえます。
Hot Reload
Flutterはコード修正後確認するとき、再実行の代わりにホットリロード機能を使うことができます。
Visual Studio Codeの場合、キーボードのrを押すことでFlutterに修正項目が自動的に反映されます。
pub.devの存在
pub.devはFlutterの公式リポジトリサイトです。
必要なパッケージや一番人気のパッケージなどを探すことができます。
Unityを使っている方は、Asset Storeのようなものを想像して貰えればいいかと思います。
Flutterでイメージをアトラス化するアプリを作ってみた
複数の画像を1つの画像にまとめるアプリが必要だったので、Flutterを使って作ってみました。
例えば、5つのpngファイルがあるとすれば、このpngを1つにまとめてアトラス化させるアプリです。
アトラス化するためには何が必要なのか
画像を1つにまとめるためには以下のロジックが必要でした。
- イメージ変更のためのピクセル操作
- 完成イメージサイズ、座標設定のためのNative Cコードの呼び込み
- サンプル画像を見せるためのマルチウィンドウ
そのため主に使ったパッケージは以下になります。
image.dart // イメージファイルを操作できるようにしてくれるパッケージ
dart.ffi //native c apiを呼び出すプラグイン
desktop_multi_window // マルチウィンドウ表示パッケージ
イメージのピクセル操作はimage.dartで
今回作成したアプリでは画像の変更をする場合があったため、画像をピクセル単位で操作できる必要がありました。
そのためにimage.dart
を使って画像を変形、操作しました。
以下はピクセルを操作して画像の上下左右を反転させたコードです。
import 'package:image/image.dart' as img;
//pngファイルのパスからbytes取得
...
var oriImage = img.decodePng(bytes) as img.Image;
Pixel pixel = oriImage.getPixel(x, y);
for (int y = 0; y < oriImage.height; y++) {
for (int x = 0; x < oriImage.width; x++) {
var pixel = oriImage.getPixel(x, y);
oriImage.setPixel(oriImage.width - x, oriImage.height - y, pixel);
}
}
Native Cコード使用のためにはffiで
アトラス化したイメージ完成画像のサイズの設定や空画像にイメージを付けるための座標計算作業がかなり複雑だったため、以下のC++コードを使いました。
このC++コードを使うために使ったのがdart.ffi
です。
Dart FFI (Foreign Function Interface)はDart言語内でC/C++のようなnative言語を相互に呼び出すことができるライブラリです。
- Webの場合
dart.ffiが動かない
のでJavaScriptなどを使って別対応をする必要があります。
以下はイメージからwidth、heightをもらってx, y座標をreturnするコードです。
import 'dart:ffi';
class FlutterRect extends Struct {
@Int32()
external int x;
@Int32()
external int y;
@Int32()
external int width;
@Int32()
external int height;
}
typedef GetMyStructC = FlutterRect Function(Int32, Int32, Int32, Int32);
typedef GetMyStructDart = FlutterRect Function(int, int, int, int);
int _shapePadding = 10;
int _extrude = 0;
FlutterRect calcAtlasImage(int width, int height) {
final getRect = _atlasImageLib
.lookupFunction<GetMyStructC, GetMyStructDart>('calcAtlasImage');
final rect = getRect(width, height, _shapePadding, _extrude);
return rect;
}
マルチウィンドウ表示はdesktop_multi_windowで
flutterは基本的にマルチウィンドウをサポートしていませんが、こちらのパッケージを使用することでmacOS、Linux環境でマルチウィンドウ表示ができるようになります。
- windowsの場合、記事作成時点ではまだ公式サポートしていないので、マルチウィンドウが開くのは確認しましたが、不具合などが発生する可能性があります。
const _defaultOffset = Offset(0, 0);
const _defaultSize = Size(1280, 720);
final window = await DesktopMultiWindow.createWindow();
window
..setFrame(_defaultOffset & _defaultSize) //ウィンドウフレーム設定
..center() //ウィンドウを中央に配置
..show() //ウィンドウをを見せる
...Widget作成
Flutterを使った感想
このようにflutterを使ってアプリを開発してみましたが、良かった点と不便だった点を話してみようと思います。
良かった点
1. Hot Reloadを使ったdebug効率向上
Hot Reloadの存在は思ったよりすごかったです。
他のフレームワークでは、修正確認のためにリロードに時間を費やしますが、Flutterではrボタン一つですぐリロードされるため、デバッグ時間がかなり節約されました。
2. 楽なWidgetの追加
FlutterではVisual Studio Codeの場合、ctrl+[.]を押すだけでWidgetを追加することができます。
機能をあれこれ追加すると括弧が多くなり何か追加することが困難な状況になりますが、このショートカットを利用すると簡単に管理することができます。
3. 色んなパッケージの存在
Flutterの標準ライブラリだけでは少し機能的に足りない部分がある可能性もありますが、これを補うための様々なパッケージが存在します。
パッケージ追加自体もpubspec.yamlに書くだけで追加できるので便利です!
//desktop_multi_windowの追加の場合
dependencies:
flutter:
sdk: flutter
desktop_multi_window: ^0.2.0
不便だった点
1. デスクトップアプリには不便な部分がある
Flutterは様々な環境で使用できるクロスプラットフォームが特徴ですが、逆にこの特徴のためデスクトップアプリを作る時には制限がありました。
ほとんどのデスクトップ開発ライブラリはマルチウィンドウをサポートしていますが、Flutterはサポートしておらず、別のパッケージを見つける必要がありました。
モバイル版の開発にはかなり充実した感じがありましたが、デスクトップ版の開発はすぐに使うには少し不便なことがありましたね。
2. まだライブラリが多くはない
Flutterはまだ作られて間もないフレームワークなので、他のフレームワークに比べて多様なライブラリが追加されているわけではありません。
時間が経てば改善する可能性はありますが、作成したいアプリによっては、現時点では必要なライブラリがないかもしれません。
まとめ
Flutterは便利な機能も多くて作業しやすいフレームワークではありますが、まだ公開されて間もないフレームワークだからか、不便な部分も少しあります。
特にUIの管理はとても便利でしたが、デスクトップ専用アプリを作るのに少し制限があったのでその点は大変でしたね。
でも、しっかり活用すれば有用なフレームワークであることは確かですから、新しいアプリを開発する際に活用してみましょう!