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

Leafletは言わずと知れた地図作成・表示のためのJavascriptライブラリです.

BlazorはC#側からJavascriptを呼び出すことが出来るようになっていますので,Blazorアプリ上でLeafletを使って地図作成・表示が可能です.

C#からの呼び出しを簡単に行うために,C#とJavascriptの橋渡しをするラッパーがいくつか公開されていますので,今回はそのうちの一つを使った方法をまとめておきます.

今回使うのはBlazor Leafletというwrapperで,チュートリアルもそこそこ書かれていますし,サンプルプログラムも公開されているので,基本的にその通り作っていけば動くと思いますが....まとめておきます.

以下では,Blazor Serverサイドで実行例を示していますが,webassemblyでも同じように動きます.

Blazor Serverアプリのプロジェクトを作る

Blazor Server のプロジェクトを作ります.

テンプレートからアプリが作成されるので,実行するとHello Worldが起ち上がるはずです.

BlazorLeafletを読み込む

ライブラリ(BlazorLeaflet)をGitHubからダウンロードして,プロジェクトに組み込みます.

Zipでダウンロードして,解凍します.BlazorLeafletというフォルダの中にBlazorLeaflet.slnがあるので,VisualStudioで開くと,サンプルプロジェクト等も確認できます.

やり方は色々あると思いますが,先ほど作ったBlazor ServerのプロジェクトにBlazorLeafletを追加します.「ファイル」−「追加」−「既存のプロジェクト」,または「ソリューションの上で右クリック」-「追加」-「既存のプロジェクト」と進んで,BlazorLeaflet/BlazorLeaflet.csprojを選択して追加します.Visual StudioのスクショはWindows版のものですが,Macでも大体同じような感じです.

追加できたら,Blazor Serverアプリ側の依存関係を設定します.

「依存関係」の上で右クリックし,「プロジェクト参照の追加」からBlazorLeafletを追加します.

Leafletを入れておく

肝心のLeafletをBlazorServerアプリのwwwrootフォルダに入れておきます.

今回は,以下からLeaflet 1.8.0をダウンロードして使いました.

Download - Leaflet - a JavaScript library for interactive maps

ダウンロード,解凍して出来上がるLeafletフォルダ以下のファイルを,wwwroot以下にコピーします.

Drag&Dropで投げ込んでも良いですし,wwwrootで「右クリック」−「既存の項目を追加」どちらでもOKです.wwwrootは,Blazor Serverアプリでwebサーバがアクセスするトップディレクトリになります.もちろん,LeafletはダウンロードせずにCDNでアクセスでも良いです.

Blazor側の設定

まずは,「_Layout.cshtml」にLeaflet用のcssやjavascriptの設定を追加します.

<head>……</head>の部分に以下を追加します.

    <link href="leaflet/leaflet.css" rel="stylesheet" >
    <script src="_content/BlazorLeaflet/leafletBlazorInterops.js"></script>

<body>…..</body>の中に以下を追加します.

    <script src="leaflet/leaflet.js"></script>

_Layout.cshtml全体は以下のようになります.15-16行目,34行目が追加した部分になります.

@using Microsoft.AspNetCore.Components.Web
@namespace testLeaflet.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="testLeaflet.styles.css" rel="stylesheet" />

    <link href="leaflet/leaflet.css" rel="stylesheet" >
    <script src="_content/BlazorLeaflet/leafletBlazorInterops.js"></script>

    <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</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 src="leaflet/leaflet.js"></script>
    <script src="_framework/blazor.server.js"></script>
</body>
</html>

次に,手抜きして,始めに表示される画面「index.razor」に地図を表示するようにします.

1,7-10行目は始めからテンプレートとして入っている部分で,その他は新たに加えた箇所になります.

@page "/"
@using System.Drawing
@using BlazorLeaflet
@using BlazorLeaflet.Models
@inject IJSRuntime jsRuntime

<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />

<div style="height: 800px; width: 800px;">
    <LeafletMap Map="_map" />
</div>

@code
{
    private Map _map;
    private LatLng _startAt = new LatLng(35.0f, 135.0f);

    protected override void OnInitialized()
    {
        _map = new Map(jsRuntime)
        {
            Center = _startAt,
            Zoom = 4.8f
        };

        _map.OnInitialized += () =>
        {
            _map.AddLayer(new TileLayer
                {
                    UrlTemplate = "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
                    Attribution = "© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
                });
        };
    }
}

12-14行目で,地図を入れるスペースを作っています.16-38行目が実際に地図表示するコード部分です.

ここまでで実行すると,北緯35度,東経135度を中心にして,Open Street Mapで表示されます.

地図を変更する

例えば,index.razorの33行目を以下のように変更すると,地理院タイルになります.

UrlTemplate = "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",

マーカーを表示する

以下のような感じでマーカ表示が出来ます.

27-33行目でマーカーを作って,42行目でレイヤーにaddしています.popupやtooltipの表示,マーカーのドラッグ等も設定できます.

@page "/"
@using System.Drawing
@using BlazorLeaflet
@using BlazorLeaflet.Models
@inject IJSRuntime jsRuntime

<PageTitle>Index</PageTitle>

<div style="height: 800px; width: 800px;">
    <LeafletMap Map="_map" />
</div>

@code
{
    private Map _map;
    private LatLng _startAt = new LatLng(35.0f, 135.0f);
    private LatLng _markerLatLng = new LatLng(35.0f, 135.0f);

    protected override void OnInitialized()
    {
        _map = new Map(jsRuntime)
        {
            Center = _startAt,
            Zoom = 11f
        };
        
        var marker = new Marker(new LatLng { Lat = _markerLatLng.Lat, Lng = _markerLatLng.Lng })
        {
            Draggable = true,
            Title = "Marker 1",
            Popup = new Popup { Content = string.Format("I am at {0:0.00}° lat, {1:0.00}° lng", _markerLatLng.Lat, _markerLatLng.Lng) },
            Tooltip = new Tooltip { Content = "Click and drag to move me" },
        };

        _map.OnInitialized += () =>
        {
            _map.AddLayer(new TileLayer
                {
                    UrlTemplate = "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",
                    Attribution = "© <a href=\"https://maps.gsi.go.jp/development/ichiran.html\">地理院タイル</a>",
                });
            _map.AddLayer(marker);
        };
    }
}

マーカーのアイコンを変更する

以下のようにアイコンを設定して,Markerのオプションで指定すれば,オリジナルのアイコンも利用可能です.

        var icon = new Icon()
        {
            Url = "plane.png",
        };

        var marker = new Marker(new LatLng { Lat = _markerLatLng.Lat, Lng = _markerLatLng.Lng })
        {
            Icon = icon
        };

その他,使用例

その他,ポリゴンを描いたり,画像をオーバーレイしたり,よく使われる機能は大体用意されているようです.これとは別に,もう一つおすすめのwrapperがありますので,改めて紹介したいと思います.

以下は,BlazorでFlightrader24のデータ(CSV)を表示して作ってみた動画です.描画の更新に改善の余地ありです...

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