Help us understand the problem. What is going on with this article?

Elm+Leafletでマーカーをぐりぐりいじるためのメモ書き

More than 1 year has passed since last update.

はじめに

Elm+Leafletをしようとした場合、下記のリポジトリのようにWeb-componentsとして操作する、という手があります。
https://github.com/cbenz/elm-leaflet-maps

このやり方だとElmコードだけで完結するという利点がありますが、例えば「マーカーを表示→それを消して別のマーカーを出す」などの操作をすると、期待した動きにならないことがあります。Leaflet の全機能を使うためには、portsを使ってJavaScriptでの操作が必要なようです。

私はwebpackをちゃんと理解しているわけではないので、これが最適かどうかはわからないですが、ひとまずworkaroundのメモとして書きます。

前提

Elmアプリのプロジェクトはcreate-elm-appで作成するものとします。通常なら「elm-app start」でコーディングし始めることも多いでしょうが、npmでLeafletをインストールするため、create-elm-appしたらすぐに「elm-app eject」しておきます。Leafletはnpmでインストールするのが一番手間が小さいかと思いますが、他の手段でもElmでの利用は可能です(bowerあるいは手動でのダウンロードなど)。

Leafletのインストール

上述した「elm-app eject」が済んでいると、packages.jsonが既にあるはずなので、コマンドラインで下記を実行します。

$ npm install leaflet --save

npmでインストールされたleafletを読み込むために、index.jsに下記を追記します。こうすることで、index.jsにて「L.map()」等のメソッドが利用できるようになります。

src/index.js
import '../node_modules/leaflet/dist/leaflet.css';
import '../node_modules/leaflet/dist/leaflet.js';

Leafletの使い方

ここまで済めば、LeafletはJavaScriptとして操作することになるので、Elmとして注意する点はほとんどありません。

Mapの初期化はこんな感じになるでしょう(Leaflet関連の部分だけ記載)。修正:コメントで「Leafletの操作はDOMができてから実行するのが安全」という話をいただきましたので、反映させました。(参考:[Elm] DOM更新後にJSコードを実行する

src/index.js
var mymap;

app.ports.initMap.subscribe(function(args) {
    requestAnimationFrame(function () {
        var lat = args[0];
        var lng = args[1];
        var mag = args[2];

        mymap = L.map("mymap").setView([lat, lng], mag);

        L.tileLayer(
        'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        {
            attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>',
            maxZoom: 18
        }
        ).addTo(mymap);
    });
});
src/Main.elm
port initMap : (Float, Float, Int) -> Cmd msg

init : ( Model, Cmd Msg )
init = ( {}, initMap (24.20578, 124.08943, 9) )

view : Html msg
view = div [id "mymap"] []

注意点

マップにマーカーを出す歳に、カスタムアイコンを画像ファイルで指定することもあるでしょう。その時に、elm-package.jsonでproxy機能を使っている場合、画像ファイルの読み込みがこのproxyに流れてしまいます。理由はよくわかっていません。これは、もちろんdev環境のみの話で、prod-buildの際は関係ありません。

私はたまたま逃げ道がありましたが、proxyの設定によってはちょっと面倒なことになるかもしれません。

cyclone_t
IoTコンサル勤務。Haskellやってます。
https://twitter.com/cyclone_tr
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away