BlazorでLeafletを利用して地図表示する場合,Blazor(C#)とLeafletのJavascriptライブラリの橋渡しをする便利なWrapperがいくつか公開されています.
今回はその内の一つ,「DPBlazorMapLibrary」を使った方法をまとめておきます.
別記事でBlazor Leafletというwrapperを使った方法もまとめていますので,そちらも参考にしてみて下さい.個人的には今回の「DPBlazorMapLibrary」の方が使いやすいかな?と思っています...
事前準備
- Blazor Server のプロジェクトを作ります
ここではBlazor Serverアプリで試していますが,WebAssemblyでも同じように動きます.
テンプレートからアプリが作成されるので,実行するとHello Worldが起ち上がるはずです.
- DPBlazorMapLibraryをnugetでインストールします
この記事を書いている時点で,バージョンは1.2.0でした.
- Leafletをインストールする
肝心のLeafletをBlazorServerアプリのwwwrootフォルダに入れておきます.
今回は,以下からLeaflet 1.8.0をダウンロードして使いました.
ダウンロード,解凍して出来上がるLeafletフォルダ以下のファイルを,wwwroot以下にコピーします.
Drag&Dropで投げ込んでも良いですし,wwwrootで「右クリック」−「既存の項目を追加」どちらでもOKです.wwwrootは,Blazor Serverアプリでwebサーバがアクセスするトップディレクトリになります.もちろん,LeafletはダウンロードせずにCDNでアクセスでも良いです.
- _Layout.cshtmlに設定を加える
DPBlazorMapLibraryとLeafletに関連する,cssやjavascriptの設定を加えます.以下の16,33,34行目を_Layout.cshtmlに追加します.
@using Microsoft.AspNetCore.Components.Web
@namespace DPBTest.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="DPBTest.styles.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
<link href="leaflet/leaflet.css" rel="stylesheet" >
</head>
<body>
@RenderBody()
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script type="text/javascript" src="leaflet/leaflet.js" charset="utf-8"></script>
<script type="text/javascript" src="_content/DPBlazorMapLibrary/map.js"></script>
<script src="_framework/blazor.server.js"></script>
</body>
</html>
- _Imports.razorに設定を加える
以下の1行を追加しておけば,いちいち@usingを書く必要がなくなります
@using DPBlazorMapLibrary;
- Program.csに設定を加える
以下の2行を適当な位置に書き加えます(下の例では4行目と12行目).
using DPBlazorMapLibrary;
builder.Services.AddMapService();
以上で事前準備は完了です.
地図表示を実装する
「index.razor」の不要部分を削除して地図表示を実装していくことにします.
3~10行目がページを作っている部分で,10行目でBlazorコンポーネントを表示しています.ここに地図が表示されます.
12行目以降がコード部分です.ざっと見れば大体分かると思いますが,24~29行目でmapoptionを指定して,39行目でタイルレイヤーを追加しています.この例では地理院タイルを表示しています.
@page "/"
<style>
.mapClass {
height: 50vh;
width: 50vw;
}
</style>
<DPBlazorMapLibrary.Map @ref="mapRef" MapOptions="@mapOptions" CssClass="mapClass" AfterRender="@AfterMapRender"></DPBlazorMapLibrary.Map>
@code{
private MapOptions? mapOptions;
private Map? mapRef;
[Inject]
public LayerFactory? LayerFactory { get; init; }
[Inject]
public IIconFactory? IconFactory { get; init; }
protected override void OnInitialized()
{
base.OnInitialized();
mapOptions = new MapOptions()
{
Center = new LatLng(34.6046389, 135.6541111),
Zoom = 11,
ZoomControl = false,
};
}
private async Task AfterMapRender()
{
//Create Tile Layer
var tileLayerOptions = new TileLayerOptions()
{
Attribution = "© <a href=\"https://maps.gsi.go.jp/development/ichiran.html\">地理院タイル</a>",
};
var mainTileLayer = await LayerFactory.CreateTileLayerAndAddToMap("https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png", mapRef, tileLayerOptions);
}
}
実行すると,以下のように表示されました.
地図を変更する
Leafletの解説を調べれば情報は沢山出てきますが,上記,index.razorの39行目を変更すればベースの地図を変更できます.
//Open Street Map
var mainTileLayer = await LayerFactory.CreateTileLayerAndAddToMap("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", mapRef, tileLayerOptions);
//地理院地図(淡色)
var mainTileLayer = await LayerFactory.CreateTileLayerAndAddToMap("https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png", mapRef, tileLayerOptions)
//地理院地図(衛星写真)
var mainTileLayer = await LayerFactory.CreateTileLayerAndAddToMap("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg", mapRef, tileLayerOptions);
マーカーとアイコン
DPBlazorMapLibraryの使い方に書かれているままですが,アイコンを指定してマーカーを表示する典型例です.
var iconOptions = new IconOptions()
{
IconUrl = "http://leafletjs.com/examples/custom-icons/leaf-green.png",
IconSize = new Point(38, 95),
IconAnchor = new Point(22, 94),
ShadowUrl = "http://leafletjs.com/examples/custom-icons/leaf-shadow.png",
ShadowSize = new Point(50, 64),
ShadowAnchor = new Point(4, 61),
PopupAnchor = new Point(-3, -76),
};
var markerOptions = new MarkerOptions()
{
Opacity = 1.0,
Draggable = true,
IconRef = await this.IconFactory.Create(iconOptions),
};
await this.LayerFactory.CreateMarkerAndAddToMap(new LatLng(34.6046389, 135.6541111), mapRef, markerOptions);
自作の画像などもアイコンとして利用可能です.例えばSVGでplane.svgを用意して,上と同じように表示できます.
var iconOptions = new IconOptions()
{
IconUrl = "plane.svg",
IconSize = new Point(120, 58),
IconAnchor = new Point(19, 22),
PopupAnchor = new Point(-3, -76),
};
var markerOptions = new MarkerOptions()
{
Opacity = 1.0,
Draggable = false,
IconRef = await this.IconFactory.Create(iconOptions),
};
await this.LayerFactory.CreateMarkerAndAddToMap(new LatLng(34.6046389, 135.6541111), mapRef, markerOptions);
アイコンサイズ,アンカーの設定,不透明度,アイコンのドラッグ,popup,tooltip,イベントの追加などJavascriptの場合とほぼ同様のことが出来ます.
SVGアイコンならテキストベースなので,C#側で色,回転,文字などを操作してファイルで保存,表示するような事も簡単に出来ます.
線を引く(Polyline)
次のような感じで,指定した点を通る線(Polyline)を引くことが出来ます.線の太さはPolylineoptionsのWeightで,不透明度はOpacityで決まります.その他にも沢山オプションがあります.
var polylineOptions = new PolylineOptions() { Color = "#FF0000", Opacity = 1, Weight = 2 };
List<LatLng> latLngs = new List<LatLng>();
latLngs.Add(new LatLng(34.60464, 135.65411));
latLngs.Add(new LatLng(34.64936, 135.60028));
latLngs.Add(new LatLng(34.77211, 135.45198));
var polyline = await LayerFactory.CreatePolylineAndAddToMap(latLngs, mapRef, polylineOptions);
画像をオーバーレイする
“RJOO.png”という画像を地図上にオーバーレイしてみます.
1行目で配置する左下,右上の座標を指定し,3行目で追加しています.2行目のオプションでイベントを追加したりできますが,下の例では使っていません.
var imageBounds = new LatLngBounds(new LatLng(34.7717217554931, 135.4266704358842), new LatLng(34.79814965996322, 135.45349378767));
var imageOverlayOptions = new ImageOverlayOptions() { BubblingMouseEvents = false };
var imageOverlay = await LayerFactory.CreateImageOverlayAndAddToMap("RJOO.png", mapRef, imageBounds, imageOverlayOptions);
“RJOO.png”は伊丹空港の滑走路や建物の線画です.重ねてみると以下のようになりました.
使用例
BlazorとDPBlazorMapLibraryでFlightradar24のデータ(CSV)を表示して作ってみた動画です(描画の更新に改善の余地ありです).レーダー画面ぽいところは,上にまとめた表示の組合せだけで作っています.
描画は結構簡単にできたんですが,Flightradar24からダウンロード出来る飛行データ(座標,高度,方位角,スピード)は時間的にかなり間引かれているので,1秒毎に補間してスムーズに見えるようにする方が面倒でした...