|
| 1 | +[English](./README.md) / 日本語 |
| 2 | + |
| 3 | +# Mapbox Collision Boxes |
| 4 | + |
| 5 | +Mapboxマップ上の衝突ボックスを画面座標系で計算する、[Mapbox GL JS (`mapbox-gl`)](https://docs.mapbox.com/mapbox-gl-js/guides/)用のユーティリティライブラリです。 |
| 6 | + |
| 7 | +## はじめる |
| 8 | + |
| 9 | +### 事前準備 |
| 10 | + |
| 11 | +このライブラリは`mapbox-gl`バージョン2以降と一緒に使用する想定です。 |
| 12 | + |
| 13 | +### インストール方法 |
| 14 | + |
| 15 | +このレポジトリを依存関係に追加してください。 |
| 16 | + |
| 17 | +```sh |
| 18 | +npm install https://github.com/codemonger-io/mapbox-collision-boxes#v0.1.0 |
| 19 | +``` |
| 20 | + |
| 21 | +### 使い方 |
| 22 | + |
| 23 | +以下のスニペットはクリックしたシンボルに画面上で隠されているFeatureを集めてくる例です。 |
| 24 | + |
| 25 | +```ts |
| 26 | +import mapboxgl from 'mapbox-gl'; |
| 27 | +import { boxesIntersect, collectCollisionBoxesAndFeatures } from 'mapbox-collision-boxes'; |
| 28 | + |
| 29 | +const map = new mapboxgl.Map( |
| 30 | + // ... マップの初期化 |
| 31 | +); |
| 32 | +// ... その他の設定 |
| 33 | +const layerId = 'cats-and-dogs'; // カスタムレイヤーを追加した想定 |
| 34 | +const map.on('click', layerId, async event => { |
| 35 | + const clickedFeatureId = event.features[0].id; |
| 36 | + const collisionBoxes = await collectCollisionBoxesAndFeatures(map, layerId); |
| 37 | + const clickedBox = collisionBoxes.find(box => box.feature.id === clickedFeatureId); |
| 38 | + const hiddenBoxes = collisionBoxes.filter(box => box !== clickedBox && boxesIntersect(box.box, clickedBox.box)); |
| 39 | + const hiddenFeatures = hiddenBoxes.map(box => box.feature); |
| 40 | + // ... Featureの処理 |
| 41 | +}); |
| 42 | +``` |
| 43 | + |
| 44 | +[`example`](./example)フォルダに完成したプロジェクトがあります。 |
| 45 | + |
| 46 | +## 動機 |
| 47 | + |
| 48 | +私はマップ上に`mapbox-gl`の[Symbol Layer](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#symbol)を使ってカスタムシンボルを表示するアプリを開発中です。 |
| 49 | +画面上でシンボルが被ると、`mapbox-gl`は最初のものだけ表示し、他の重なるものは隠してしまいます。 |
| 50 | +私の知る限り、`mapbox-gl`には画面上で特定のシンボルによって隠されているシンボルを取得するAPIはありません。 |
| 51 | +開発中のアプリでは非表示のものも含めてクリックされたポイントにあるすべてのシンボルをリストしたいので、これでは不都合です。 |
| 52 | +`mapbox-gl`に衝突検出をスキップさせてすべてのシンボルを画面に表示させる[オプション](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#layout-symbol-icon-allow-overlap)はありますが、重なるシンボルがたくさんある場合は画面がごちゃごちゃし過ぎてしまいます。 |
| 53 | + |
| 54 | +ということで**Mapboxマップ上で特定のシンボルと重なるシンボルを集めることのできるライブラリを開発**することにしました。 |
| 55 | + |
| 56 | +詳しくは[私のブログ投稿](https://codemonger.io/blog/0009-mapbox-collision-boxes/)をご覧ください。 |
| 57 | + |
| 58 | +## APIドキュメント |
| 59 | + |
| 60 | +[`api-docs/markdown/index.md`](./api-docs/markdown/index.md)をご覧ください。 |
| 61 | + |
| 62 | +## Tips |
| 63 | + |
| 64 | +### ビューポートオフセット |
| 65 | + |
| 66 | +[`collectCollisionBoxesAndFeatures`](./api-docs/markdown/mapbox-collision-boxes.collectcollisionboxesandfeatures.md)が集める衝突ボックスは固定のオフセットを含んでいます。 |
| 67 | +xとyの両軸について実際の画面位置 + `100`\*になっています。 |
| 68 | +オフセットは衝突ボックス同士の衝突判定には影響しないため、このライブラリでは不必要な計算を避けるためにそのままにしてあります。 |
| 69 | +衝突ボックスを実際の画面に投影したい場合は、xとy軸の値から`100`を引かなければなりません。 |
| 70 | + |
| 71 | +\* この定数は`viewportPadding`として https://github.com/mapbox/mapbox-gl-js/blob/e29e113ff5e1f4c073f84b8cbe546006d2fb604f/src/symbol/collision_index.js#L50 に定義されていますが、`mapbox-gl`はエクスポートしていません。 |
0 commit comments