はじめに
Mapbox GL JS が v3 となって久しいですが、v3 の新機能として Style Specification に random
という Expressions が登場しました。
この機能について、私は、当時の記事で以下のように記載しましたが、これがあまり使い勝手がよくなかった(私が使い方を勘違いしていた)ので、その補足を兼ねて挙動をメモします。
地味に、ランダムな値を発生させる
random
もうれしいです。今までは、同じ種類の地物(建物など)を少しずつ違った色合いで見せたい、というような場合、データ段階で色のデータを仕込んでおかねばならなかったので。
random
の使い方
使い方はドキュメントの通りなのですが、以下のように、number_1 と number_2 の間のランダムな値を seed をもとに生成します。
["random", number_1, number_2, seed]
ここで、seed の値が同じであれば同じ値が返ってくることになります。そのため、単に以下のように単一のスタイルレイヤで共通の seed を用いる場合、そのスタイルレイヤで記述される地物については、全て同じ値が適用されることになります。
たとえば、以下のようにポリゴン(fill)の色をランダムに発生させた場合、このスタイルレイヤで再現される地物は、全て同じ色で塗られることになります。
"fill-color": ["hsl", ["random", 0, 360, 123], 50, 50],
これを地物毎にランダムな値で塗りつぶしたい場合は、seed を地物に合わせて変更する必要があるようです。以下の例は、例えば、地物毎に id というユニークな属性値を持っている場合の記述方法です。
"fill-color": ["hsl", ["random", 0, 360, ["get", "id"]], 50, 50],
そのため、地物毎にユニークな値がない場合、それをスタイル側の設定でランダムに塗り分けるというのは、どうやら難しいようです。
結果として、私の過去の記述は、「ランダム/ユニークな色そのものをデータ段階で仕込む必要はない」という点は誤りないのですが、同じ種類の地物(建物など)を少しずつ違った色合いで見せたい場合は、「データ段階で各地物のユニークな値を仕込んでおく必要がある」という知識が抜けておりました。
地味に、ランダムな値を発生させる
random
もうれしいです。今までは、同じ種類の地物(建物など)を少しずつ違った色合いで見せたい、というような場合、データ段階で色のデータを仕込んでおかねばならなかったので。
無理やり地物毎に塗分けてみる
たとえば、地理院地図Vector や最適化ベクトルタイルの建物データを塗り分けようとすると、地物(建物ポリゴン)毎にユニークな属性値はありません。そのため、random
を用いて塗分けるのは無理だと思っていました。
ただ、属性値としてはユニークなものがないとしても、座標値(geometry) は地物毎にユニークなはずです。そのため、座標値を評価できる Expressions がないか探したところ、disatance
という Expressions が利用できそうでした(ドキュメントはこちら)。
["distance", geojson_object]
そこで、各地物と座標 [0, 0] の距離を random
の seed として入れてみると、見事にランダムな色で各地物を塗り分けることができました。
"fill-color": ["hsl", ["random", 0, 360, ["distance",
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [0, 0]},
"properties": {}
}
]], 50, 50],
※地図データ:地理院地図Vector(実際は、fill ではなく、fill-extrusion で表示)
ただし、以下のような懸念は残っています。
- 無駄に距離の演算をさせるので、パフォーマンスが心配
- 距離演算の精度や Simplification 等で ZL 毎に地物の形状が異なるためか、ZL を変更する毎に色が変わってしまい安定しない
- 地物がデータ上分かれていると別の色に塗られてしまう
サンプル
レポジトリ
おわりに
期待していた random
について、私が当初想定していた通りの挙動をしていないことに気づき、あきらめかけたところですが、distance
を用いることで100点でないにしろやりたいことができるとわかりました。いろいろな地図表現を楽しめることに感謝です。
ただ、機能の充実に伴い、それらの組み合わせで様々なことができるようになりますが、果たしてそれが開発陣の想定している使い方なのかは分かりません。今回の記事を書きながら、あまりにも想定を外れる使い方は避けた方が良いな、とも思いました。