BlazorでLeafletを利用して地図表示する(2)

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秒毎に補間してスムーズに見えるようにする方が面倒でした...

タイトルとURLをコピーしました