Flutter で地図アプリ開発に使える機能をシリーズで紹介するブログ記事です。今回はシェープファイルの表示編です。マップ上にシェープファイルのデータを表示する機能を実装していきます。この記事では、Flutter 用の地図 SDK (ArcGIS Maps SDK for Flutter) を使用して、その機能を実装する方法を紹介します。
サンプル コードは GitHub に公開しているので、すぐに確認したい方は、ダウンロードしてみてください。アプリの実行方法は README に記載しています。サンプルを実行するために、API キーの取得 (無償) が必要になります。 地図 SDK の導入からマップ表示までの方法は「Flutter で地図アプリを作成してみよう!」のブログ記事をご覧ください。この記事では、シェープファイルの表示の機能にフォーカスして紹介します。
シェープファイルは GIS (地理情報システム) データのフォーマットの 1 つです。目標物や道路、建物などの位置や形状、属性情報を持つベクター データ (ポイント、ライン、ポリゴン) を格納することができます。シェープファイルは、ベクター形式の GIS 業界標準フォーマットで、ArcGIS 製品はもちろん、多くの GIS ソフトウェアで利用可能です。
シェープファイルを表示するには、ShapefileFeatureTable クラスを使用します。指定したパスにあるシェープファイルのデータをレイヤーとして、マップ上に表示できます。今回使用するシェープファイルは、こちら に配置しています。シェープファイルには、千葉県内にランダムに配置したポイント データが格納されています。
1. 「Flutter で地図アプリを作成してみよう!」のブログ記事の手順 6 で、マップビュー コントローラーに作成したマップを設定してマップの表示までできることを確認します。
2. こちらから、シェープファイルを格納した ZIP ファイルをダウンロードして解凍します。shp フォルダーを、<アプリケーション名>/asset フォルダーに配置します。asset フォルダーは自身で作成します。
3. アプリケーションに配置したシェープファイルを追加するために pubspec.yaml の assets セクションを下記のように更新します。
assets:
- assets/shp/
4. デバイス内のパスの取得に path_provider パッケージを使用するため、pubspec.yaml の dependencies セクションにパッケージを追加します。
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
arcgis_maps: ^200.8.0+4672
// 追加
path_provider: ^2.1.5
5. lib/main.dart を開き、既に書かれているインポート行の後に、下記のコードを追加して、この後の処理に必要なパッケージをインポートします。
import 'package:path_provider/path_provider.dart';
import 'package:flutter/services.dart';
import 'dart:io';
6. ファイル操作等に await を使用するため _onMapViewReady() を async 関数に変更します。
// 変更前
void _onMapViewReady() {
// 変更後
Future<void> _onMapViewReady() async {
7. _onMapViewReady() async 関数の最後にコードを追加します。assets フォルダーにあるシェープファイルを読み込み、iOS/Android アプリケーションのドキュメント ディレクトリーに、新たにシェープファイルを作成します。
// マップビュー コントローラーに作成したマップを設定します。
_mapViewController.arcGISMap = map;
// 追加
// assets フォルダーにあるシェープファイルから、ドキュメントディレクトリーに新たにシェープファイルを作成します。
final assetManifest = await AssetManifest.loadFromAssetBundle(rootBundle);
final fileAssetsList = assetManifest
.listAssets()
.where((string) => string.startsWith("assets/shp/"))
.toList();
for (int i = 0; i < fileAssetsList.length; i++) {
String filePath = fileAssetsList[i];
final byteData = await rootBundle.load(filePath);
final file =
File('${(await getApplicationDocumentsDirectory()).path}/$filePath');
await file.create(recursive: true);
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
}
8. 続いて、ドキュメント ディレクトリーに作成したシェープファイル (.shp) のパスから File オブジェクトを作成します。
final shapefile = File(
'${(await getApplicationDocumentsDirectory()).path}/assets/shp/random_points.shp',
);
9. File.uri を引数に指定して ShapefileFeatureTable を作成し、作成した ShapefileFeatureTable から FeatureLayer を作成します。ShapefileFeatureTable はシェープファイルに格納されているデータにアクセス (検索や編集) でき、FeatureLayer はマップ上での表示を管理します。
// ドキュメントディレクトリーにあるシェープファイルのパスから ShapefileFeatureTable を作成します。
final shapefileFeatureTable =
ShapefileFeatureTable.withFileUri(shapefile.uri);
await shapefileFeatureTable.load();
final shapefileFeatureLayer =
FeatureLayer.withFeatureTable(shapefileFeatureTable);
await shapefileFeatureLayer.load();
10. 作成した FeatureLayer を ArcGISMap オブジェクトの operationalLayers に追加します。
_mapViewController.arcGISMap!.operationalLayers.add(shapefileFeatureLayer);
11. この状態でビルドします。マップを千葉県に移動して、シェープファイルを表示します。表示スタイルを設定していないため、ポイント データが黒い点で表示されています。
12. 今回は、シェープファイルの属性情報に応じて、色分け表示する機能を実装してみます。手順4の FeatureLayer を ArcGISMap の operationalLayers に追加するコードの前に、下記のコードを追加します。シェープファイルのポイント データには、name 属性フィールドに a, b, c のいずれかの属性値がランダムに格納されています。属性値が a のときは赤色の丸で、b のときは青色の丸で、c のときは黄色の丸で、それ以外の場合は黒色の丸で表示するために、それぞれのシンボル (SimpleMarkerSymbol) を作成します。
// 各属性値用のシンボルを作成します。
final redMarkerSymbol = SimpleMarkerSymbol(
style: SimpleMarkerSymbolStyle.circle,
color: Colors.red,
size: 10,
);
final blueMarkerSymbol = SimpleMarkerSymbol(
style: SimpleMarkerSymbolStyle.circle,
color: Colors.blue,
size: 10,
);
final yellowMarkerSymbol = SimpleMarkerSymbol(
style: SimpleMarkerSymbolStyle.circle,
color: Colors.yellow,
size: 10,
);
final defaultMarkerSymbol = SimpleMarkerSymbol(
style: SimpleMarkerSymbolStyle.circle,
color: Colors.black,
size: 10,
);
13. 続いて、レイヤーの表示ルールを定義するレンダラーを作成します。各ポイントの属性値に応じて表示スタイルを定義することができるレンダラーである UniqueValueRenderer を使用します。UniqueValueRenderer オブジェクトの uniqueValues プロパティには、a, b, c の属性値とそれに対応するシンボルから作成した UniqueValue オブジェクトの配列を設定します。
// name フィールドの属性値に応じて色分け表示(a は赤色、b は青色、c は黄色)するための、UniqueValueRenderer を作成します。
final aValue = UniqueValue(
description: 'name is a',
label: 'a',
symbol: redMarkerSymbol,
values: ['a'],
);
final bValue = UniqueValue(
description: 'name is b',
label: 'b',
symbol: blueMarkerSymbol,
values: ['b'],
);
final cValue = UniqueValue(
description: 'name is c',
label: 'c',
symbol: yellowMarkerSymbol,
values: ['c'],
);
final uniqueValueRenderer = UniqueValueRenderer(
fieldNames: ['name'],
uniqueValues: [
aValue,
bValue,
cValue,
],
defaultLabel: 'Other',
defaultSymbol: defaultMarkerSymbol,
);
14. 作成した UniqueValueRenderer をシェープファイル表示用の FeatureLayer の renderer プロパティに設定します。
shapefileFeatureLayer.renderer = uniqueValueRenderer;
15. シェープファイルのポイント データのシンボルが目立つように暗色のベースマップに変更します。
//変更前
final basemap =
Basemap.withStyle(BasemapStyle.arcGISStreets, parameters: bsp);
//変更後
final basemap =
Basemap.withStyle(BasemapStyle.arcGISDarkGray, parameters: bsp);
16. 最後にマップの初期表示座標とスケールを調整します。
//変更前
final initialPoint = ArcGISPoint(
x: 139.745461,
y: 35.65856,
spatialReference: SpatialReference.wgs84,
);
map.initialViewpoint = Viewpoint.fromCenter(initialPoint, scale: 10000);
//変更後
final initialPoint = ArcGISPoint(
x: 140.1111782,
y: 35.6130401,
spatialReference: SpatialReference.wgs84,
);
map.initialViewpoint = Viewpoint.fromCenter(initialPoint, scale: 100000);
17. ビルドして、シェープファイルを表示してみます。ポイント データが赤/青/黄の3色で表示されています。
本記事では、シェープファイルの表示機能を実装しました。データを表示するだけでなく、ShapefileFeatureTable にアクセスして、データのクエリーや編集 (追加/削除/更新) 等も可能です。今回はシェープファイルを使用しましたが、SDK では、その他にもジオデータベースや GeoPackage、ラスター等の多くの GIS データに対応しています。