ドキュメントを検索

応用

ハウツー 地図インスタンス(maps-core)に直接アクセスし、MapLibre GL JS の機能を利用するには

embed / maps-suite / maps-react はどれも、土台に maps-core の GeoloniaMap を持っています。GeoloniaMap は MapLibre GL JS の Map を継承したクラスなので、これを取り出せば on()flyTo()queryRenderedFeatures() といった MapLibre GL JS の API がそのまま使えます。

各ライブラリが用意している機能で足りないときの逃げ道がこれです。取り出し方だけがライブラリごとに違います。

コード

下のデモはどれも同じことをしています。地図を動かすと、左上の枠に現在のズームと中心座標が出ます。ズームや中心を読む API は各ライブラリの表側にはないので、土台のインスタンスから取っています。

geolonia.Map に対象の要素を渡して、自分で地図を作ります。返ってくるのが GeoloniaMap です。以前から案内してきた書き方で、いまもこれが基本です。

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <style>
      #map { width: 100%; height: 100vh; }
      #readout2 {
        position: absolute; top: 8px; left: 8px; z-index: 1;
        background: #fff; padding: 6px 10px; border-radius: 4px;
        font: 13px/1.5 system-ui, sans-serif;
      }
    </style>
  </head>
  <body>
    <div id="readout2">読み込み中</div>
    <div id="map" data-lat="35.68" data-lng="139.75" data-zoom="11"></div>

    <script src="https://cdn.geolonia.com/embed/v5/embed?geolonia-api-key=YOUR-API-KEY"></script>
    <script>
      const map = new geolonia.Map("#map");
      const readout = document.getElementById("readout2");

      map.on("load", () => {
        const show = () => {
          const c = map.getCenter();
          readout.textContent =
            `zoom ${map.getZoom().toFixed(2)} / ${c.lat.toFixed(4)}, ${c.lng.toFixed(4)}`;
        };
        map.on("move", show);
        show();
      });
    </script>
  </body>
</html>
  • class="geolonia" を付けていません。embed が自動で地図を作るのは .geolonia を持つ要素だけなので、クラスを外して id で渡します。
  • data-lat などの属性は、自分で作った場合も読まれます。属性で書ける設定はそのまま使えるので、JavaScript で書き直す必要はありません。
  • map.on("load", ...) を待つのは、スタイルの読み込みが終わってから触るためです。

すでに地図がある要素に対して呼んだ場合は、新しく作らずに既存のインスタンスが返ります。 class="geolonia" を付けたまま new geolonia.Map(".geolonia") を呼んでも、地図が2つになることはありません。自動で作られた地図に後から触りたいときも、この書き方で取れます。

要素の geoloniaMap プロパティからも取れますが、こちらはまだ地図が作られていないと undefined です。embed は要素が画面に入ったときに作るので、画面外にある地図はスクロールされるまで存在しません。new geolonia.Map() なら、その場で作るか既存を返すかのどちらかになるので、タイミングを気にせず書けます。

なお、embed を読み込むと window.geolonia に MapLibre GL JS の中身がそのまま入ります。new geolonia.Popup() のように、MapLibre のクラスを直接使えます。

結果

上のコードは、それぞれのタブの下でそのまま動いています。地図をドラッグしたりズームすると、左上の数値が追従します。値を出しているのは土台の GeoloniaMap で、MapLibre の getZoom()getCenter()、それに move イベントを使っています。

どこまでできるか

取り出したインスタンスでできることは、MapLibre GL JS の Map にできること全部です。書ける API の一覧は MapLibre GL JS のドキュメントにあります。Geolonia が足した部分は maps-core のリファレンスを参照してください。

うまくいかないとき
  • embed で geoloniaMapundefined → 地図がまだ作られていません。embed は要素が画面に入ったときに作ります。new geolonia.Map() で取り直してください。
  • embed で「No HTML elements found matching」→ 渡したセレクタに合う要素がありません。スクリプトを要素より前に置いている場合も起きます。
  • 「Style is not done loading」→ スタイルの読み込み前にレイヤを触っています。maps-suite なら whenReady() を待ち、maps-react なら isStyleLoaded() を見て once("load") で待ってください。
  • maps-react で useRef + useEffect にしたら null だった → 地図はマウント後に作られるので、最初の useEffect の時点ではまだ入っていません。関数を ref に渡して、呼ばれたときに動く形にしてください。
  • インスタンスを取ったのに操作が反映されない → maps-suite が管理している値(中心・ズーム・傾き・向き)を土台側から直接変えた場合、動作は保証されません。これらは maps-suite のメソッドで変えてください。