🗺️

mapbox studioを使って地図上の物件名の表示を調整する

2022/09/13に公開約4,400字

mapbox studioにて、表示される物件の特定のカテゴリーのみラベルを非表示にした際に調べたことのメモ

mapboxの地図上に表示される情報はすべて「レイヤー」である

地図の編集画面から Layersを選択し、適当なレイヤーを選択して表示・非表示アイコンを切り替えると、どのレイヤーがどの表示を担っているのかがわかる

物件名は Point of Interest labelsである

前述の方法で、今回調整したいのが Point of Interest labels(以下 poi labels)であることがわかった。入力データソースをFilterしてあげると良いので、 poi-labelレイヤーの Select dataタブを選択する。

が、Filterの編集ができないので、このレイヤーをDuplicateする。

FilterするためのFormula(式)を定義する

https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/

レイアウトプロパティ、ペイントプロパティ、フィルタの値は、expression(式)として定義することができます。
expression(式)は、以下に説明する演算子を使用して、プロパティの値を計算するためのformula(式)を定義します。Mapbox GL が提供するexpression operators(式演算子)には以下のものがあります。

  • 数値に対して算術演算やその他の操作を行うための数学演算子
  • 論理演算子:ブーリアン値の操作や条件判断を行います。
  • 文字列を操作するための文字列演算子
  • ソース フィーチャーのプロパティにアクセスするための Data 演算子
  • カメラ演算子:現在のマップビューを定義するパラメータにアクセスするための演算子
    expression(式)は JSON 配列として表現されます。expression(式)配列の最初の要素は、"*" や "case" などのexpression operators(式演算子)の名前を示す文字列です。その後に続く要素は、(もしあれば) 式の引数です。各引数は、リテラル値(文字列、数値、ブール値、NULL)か、別の式配列です。

日本語の場合、Formulaもexpressionも「式」として訳されるのでややこしいが、様々なexpressionを用いてformulaを定義すると考えればよい。

poi labelsにデフォルトで定義されているformulaは以下である。

[
  "<=",
  ["get", "filterrank"],
  [
    "+",
    [
      "step",
      ["zoom"],
      0,
      16,
      1,
      17,
      2
    ],
    2
  ]
]

expressionを理解する

"<=" 演算子

https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/#<=

最初の入力が2番目の入力より小さいか等しい場合に真を、そうでない場合に偽を返します。引数は両方とも文字列か数字でなければなりません。

プログラミング言語のfilter関数と同じく、trueを返した場合にその値が残ると考えれば良いので、
第一引数 ["get", "filterrank"]が第二引数より小さいか等ければ、そのデータは表示される

"get" 演算子

https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/#get

現在の関数のプロパティから、または第二引数が指定された場合は他のオブジェクトから、プロパティ値を取得します。要求されたプロパティが見つからない場合は、null を返します。

filterrank

https://docs.mapbox.com/data/tilesets/reference/mapbox-streets-v8/#filterrank-number

filterrank フィールドは、ラベルの密度をカスタマイズするために使用される 0 ~ 5 の値です。これは、スタイル レイヤー フィルタ(Mapbox Studio の 'データ選択' タブ)で使用されることを意図しています。
値は現在のズームレベルに対する相対値です。例えば、同じ POI が z10 では filterrank = 5 であるのに対し、z14 では filterrank = 1 になっていることがあります。

filterrank<=1は最も目立つラベルのみを表示し、filterrank<=3は中程度の密度で表示し、filterrank<=5はできるだけ多くのラベルを表示するように設定することができます。

この値は決してヌルではなく、常に0〜5の範囲にあります。

物件ごとに決められるランクで、現在のズームレベルにおいて重要な建物ほどランクが高い(番号が若い ← ややこしい)。ズームレベルによって変動する。後述するstep演算子でzoomレベルに対して閾値を設定することで表示させる物件をフィルターさせたりできる。

"+" 演算子

Returns the sum of the inputs.

このexpressionの末尾に 2があるので、常に後述の step演算子の結果に2が足されることになる。(filterrankとの評価を調整している)

"step"演算子

https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/#step

入力値と出力値のペア(「stop」)で定義される区分的定数関数を評価することにより、離散的で段階的な結果を生成する。入力は、任意の数値式(例えば、["get", "population"])であることができる。stopの入力は、厳密には昇順の数値リテラルでなければならない。入力よりちょうど小さいstopの出力値、または入力が最初のstopより小さい場合は、最初の出力値を返します。

syntax

["step",
    input: number,
    stop_output_0: OutputType,
    stop_input_1: number, stop_output_1: OutputType,
    stop_input_n: number, stop_output_n: OutputType, ...
]: OutputType

定義されたexpressionと照らし合わせると

    ["step",
      ["zoom"],
      0,
      16,1,
      17,2
    ],

つまりズームレベルを入力にして、zoomレベルが18以上の場合、それよりも小さいstop(17)の出力が採用され、15以下の場合、最初の出力値(0)が採用される。

よって、このstepと+演算子は以下のような状態を表す

それぞれのzoomレベルにて、step以下にfilterrankが収まる物件はラベルが表示される。
どんなにズームしてもstepは4までしか上がらないので、filterrankが5のように評価されがちなアパートみたいな物件のラベルは表示されないことになる。

【実践】特定のカテゴリーのみラベルを非表示にする

formulaの構文が理解できたので、今回の用途に適した演算子を探す。

match演算子

結果から言うと matchである。

https://docs.mapbox.com/mapbox-gl-js/style-spec/expressions/#match

ラベル値が入力値と一致する出力を選択し、一致しない場合はフォールバック値を選択する。入力は任意の式(例えば ["get", "building_type"] )が可能です。各ラベルは一意でなければならず、以下のいずれかでなければならない。

syntax

["match",
    input: InputType (number or string),
    label: InputType | [InputType, InputType, ...], output: OutputType,
    label: InputType | [InputType, InputType, ...], output: OutputType,
    ...,
    fallback: OutputType
]: OutputType

これを用いて物件のカテゴリを取得し、表示させたいカテゴリはtrueを返し、それ以外はfallbackでfalseを返す。

["match",
  ["get", "class"],
  "landmark", true,
  "park_like", true,
  "religion", true,
  false
]

上記の例では class を用いているが、別のプロパティを getしても問題ない。用途によって使い分けたり、別のデータを組み合わせてもよい。

それぞれの物件がどのようなプロパティを持っているかは、 Select dataタブ選択時のマップ内でラベルをクリックすることで確認できる。

Discussion

ログインするとコメントできます