9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MapLibreAdvent Calendar 2024

Day 11

MapLibre GL JSのaddProtocolとは何なのか

Last updated at Posted at 2024-12-10

mug-jp_logo_01.png

はじめに

MapLibreとは

MapLibre Official WebSite
https://maplibre.org

  • Web地図に関するプロダクトをOSSとして開発・メンテナンスしているOrganizationです
  • ブラウザ・モバイル向けの地図ライブラリおよび地図配信に関するツール群があります

MapLibre User Group Japan (MUG-JP) とは

MUG-JP Official Web Site
https://mug-jp.org/

  • MapLibreプロダクトの開発者によるユーザーコミュニティです
  • ナレッジの共有やイベントの開催による普及活動を行なっています

v2で突如生えてきたaddProtocol()関数

addProtocol()の経緯などについては以下の記事が詳しいです。そういえば昔はmapbox://というプロトコルが使えたっけ…。

MapLibre Styleでは、sourceでタイル等のURLを定義しますが、その際のプレフィックスをprotocolと呼びます(http/https...)。https://ならもちろんデフォルトの挙動(単にデータをダウンロードする)となりますが、ここに独自のprotocolを定義するのがaddProtocolという訳です。

addProtocol()という言葉だけだと意味がわかりづらいので、ユーザーがタイルデータを自由に生成出来るcustom sourceと理解するのが良いと思います。

addProtocolで定義するカスタムプロトコル

割となんでも出来て、ルールはたったひとつ=「タイルデータをreturnする」ことだけです。

以下の例では、クライアントサイドでオンメモリで生成したPNG画像をreturnしています(fetchせずcanvasで画像生成しているのがポイント)。

https://svelte-maplibre-gl.mierune.dev/examples/custom-protocol より引用

maplibregl.addProtocol('myprotocol', async (params) => {
    const zxy = params.url.replace('myprotocol://', '');
    const [z, x, y] = zxy.split('/').map((v) => parseInt(v, 10));

    const png = await new Promise((resolve) => {
      const canvas = document.createElement('canvas');
      canvas.width = 512;
      canvas.height = 512;
      const context = canvas.getContext('2d')!;

      // checkered pattern
      context.fillStyle = (z + x - y) % 2 === 0 ? 'rgba(255, 255, 255, 0.4)' : 'rgba(0, 0, 0, 0.4)';
      context.fillRect(0, 0, canvas.width, canvas.height);
      context.fillStyle = 'white';
      context.font = '32px sans-serif';
      context.fillText(`${z}/${x}/${y}`, 32, 64);

      // canvas to blob (png) to arraybuffer
      canvas.toBlob(async (blob) => {
        resolve(await blob!.arrayBuffer());
      });
    });

    return { data: png };
});

また、以下の例ではベクトルタイルのバイナリをオンメモリで生成しています。

addProtocolを活用しているライブラリ群

余談:addProtocol()が実装されたあたりにあった会話

筆者所属のMIERUNEがMapLibre Orgにスポンサーしたときに、MIERUNEがMapLibreをどう利用しているか的なインタビューがあり:

Screenshot 2024-12-07 at 10.55.11.png

メンテナーたちも、現状のような使われ方は予想していなかったのかもしれませんね。addProtocol()がユーザー定義のsourceの作成を可能としたことで、図らずもいわゆる「プラグイン機構」を提供するものとなったということでしょう。当初、関数のシグネチャもおよそサードパーティに利用させるような作りではなかったのも思い出されます(値を返すのがcallback(null, png, null, null)という関数だった。v4で綺麗になった)。

余談:MapLibre Nativeではどうなっているのか

MapLibre Nativeでは、そもそもデータへのリクエストは全て自分で定義する必要があります。以下は筆者が開発しているchiitilerのコードです。

データフェッチングは全てこの関数を通るので、プロトコルをチェックして条件分岐させています。

ここで、GL JSとNativeは違う仕組みで動いていることに注意が必要です。つまりaddProtocolに過度に依存したstyleはNativeでは利用出来ないということです。

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?