This is a blog series introducing features useful for developing map apps with Flutter. This time, we focus on displaying shapefiles. We will implement functionality to display shapefile data on the map. In this article, we show how to implement this using the Flutter map SDK (ArcGIS Maps SDK for Flutter).
Sample code is published on GitHub, so if you want to check it immediately, please download it. Instructions for running the app are described in README. To run the sample, you will need to obtain an API key (free). For instructions on setting up the map SDK and displaying maps, please see the blog article “Let's Create a Map App with Flutter!”. This article focuses on the feature of displaying shapefiles.
What is a Shapefile?
A shapefile is one of the GIS (Geographic Information System) data formats. It can store vector data (points, lines, polygons) that include location, shape, and attribute information of targets such as landmarks, roads, and buildings. Shapefiles are the industry standard vector format in GIS and are supported not only by ArcGIS products but also by many GIS software.
Implementing Shapefile Display Functionality
To display shapefiles, use the ShapefileFeatureTable class. You can display shapefile data located at a specified path as a layer on the map. The shapefile used this time is placed here に配置しています。シェープファイルには、千葉県内にランダムに配置したポイント データが格納されています。
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);
// After change
final initialPoint = ArcGISPoint(
x: 140.1111782,
y: 35.6130401,
spatialReference: SpatialReference.wgs84,
);
map.initialViewpoint = Viewpoint.fromCenter(initialPoint, scale: 100000);
17. Build and try displaying the shapefile. The point data is shown in three colors: red, blue, and yellow.
Summary
In this article, we implemented the functionality to display shapefiles. Not only can you display data, but you can also access the ShapefileFeatureTable to perform operations such as querying and editing (query, adding, deleting, updating) on the data. This time we used shapefiles, but the SDK also supports many other GIS data types such as add/delete/update). The SDK supports other GIS data like geodatabases and GeoPackage, rasters, and more.
Related Links