🌐

GLJSの条件式をユースケースごとにまとめてみた

2023/12/09に公開

GLJSの条件式をユースケースごとにまとめてみた

はじめに

アイディオットCTOの小倉です。
今回は、mapbox GLJSの実装で利用する条件式についてお話します。

mapboxの条件式について

普段我々がコードの中で利用する条件式について、mapbox GLJSにおいては特殊な記述方法があります。
例えばFeatureにvalueというプロパティがあり、
以下のような条件式があるとします。

if (value === 'foo') {
  return '#ff0000';
} else if (value === 'bar') {
  return '#00ff00';
} else {
  return '#000000';
}

mapbox GLJSでは、以下のようなLispライクな条件式で記述します。

[
  'match',
  ['get', 'value'],
  'foo',
  '#ff0000',
  'bar',
  '#00ff00',
  '#000000'
]

今回行うこと

上記の通り、mapbox GLJSでは条件式の記述方法はなかなか馴染みがないこともあり、実装の中でどう書けばいいのか悩むこともあると思います。
今回は条件式として書くことがありそうなものをユースケースとして想定して、JavaScriptでの条件式とmapbox GLJSでの条件式を比較したものを紹介しようと思います。

扱うサンプルコードについては、試して頂きやすいように、公式のEXAMPLESにあるCreate and style clustersを利用します。
こちらの実装例の中で、円のクラスターを描画するレイヤーにおいて、下記のコードのようにpoint_countというクラスタリングされた円の数を表す属性値を利用して、クラスターの数に応じて円の色を変えるという処理を行っており、その部分を変更する形で進めていきます。

map.addLayer({
    id: 'clusters',
    type: 'circle',
    source: 'earthquakes',
    filter: ['has', 'point_count'],
    paint: {
        // こちらのpaintプロパティの circle-color を変更します。
        'circle-color': [ 
            'step',
            ['get', 'point_count'],
            '#51bbd6',
            100,
            '#f1f075',
            750,
            '#f28cb1'
        ],
        'circle-radius': [
            'step',
            ['get', 'point_count'],
            20,
            100,
            30,
            750,
            40
        ]
    }
});

ユースケース

(1) まずは条件式を全く使わないケースで、単純に白くする。

JavaScript

paint['circleColor'] = '#ffffff'

GLJS

paint: {
    'circle-color': '#ffffff'
}

結果

result1

(2) point_count が300以上で赤くし、それ以外は白くする。

JavaScript

if (point_count >= 300) {
  paint['circleColor'] = '#ff0000'
} else {
  paint['circleColor'] = '#ffffff'
}

GLJS

step関数を利用するパターン。

paint: {
    'circle-color': [
        'step',
        ['get', 'point_count'],
        '#ffffff',
        300,
        '#ff0000',
    ],
}

case関数を利用して、演算子を利用するパターン。

paint: {
    'circle-color': [
        'case',
        ['>=', ['get', 'point_count'], 300],
        '#ff0000',
        '#ffffff',
    ],
}

結果

result2

(3) point_count が5, 255, 106の場合赤くし、それ以外は白くする。

JavaScript

if (point_count === 5 || point_count === 255 || point_count === 106) {
  paint['circleColor'] = '#ff0000'
} else {
  paint['circleColor'] = '#ffffff'
}

GLJS

match関数を利用します。

paint: {
    'circle-color': [
        'match',
        ['get', 'point_count'],
        5,
        '#ff0000',
        255,
        '#ff0000',
        106,
        '#ff0000',
        '#ffffff',
    ],
}

リスト化することもできます。

paint: {
    'circle-color': [
        'match',
        ['get', 'point_count'],
        [5, 255, 106],
        '#ff0000',
        '#ffffff',
    ],
}

結果

result3

(4) point_count が300以上かつ5の倍数の場合緑にする。それ以外は白くする。

if (point_count >= 300 && point_count % 5 === 0) {
  paint['circleColor'] = '#00ff00'
} else {
  paint['circleColor'] = '#ffffff'
}

GLJS

all関数を利用して && を表現します。
ちなみに || を表現する場合はany関数を利用します。

paint: {
    'circle-color': [
        'case',
        [
          'all', 
          ['>=', ['get', 'point_count'], 300], 
          ['==', ['%', ['get', 'point_count'], 5], 0]
        ],
        '#00ff00',
        '#ffffff',
    ],
}

結果

result4

(5) point_count が300より小さい場合は青くし、300以上かつ5の倍数の場合緑に、2の倍数の場合は赤くする。それ以外は白くする。

JavaScript

if (point_count >= 300) {
  if (point_count % 5 === 0) {
    paint['circleColor'] = '#00ff00'
  } else if (point_count % 2 === 0) {
    paint['circleColor'] = '#ff0000'
  } else {
    paint['circleColor'] = '#ffffff'
  }
} else {
  paint['circleColor'] = '#0000ff'
}

GLJS

入れ子の条件式は以下のように記述します。

paint: {
    'circle-color': [
        'step',
        ['get', 'point_count'],
        '#0000ff',
        300,
        [
            'case',
            ['==', ['%', ['get', 'point_count'], 5], 0],
            '#00ff00',
            ['==', ['%', ['get', 'point_count'], 2], 0],
            '#ff0000',
            '#ffffff',
        ],
    ],
}

結果

result5

まとめ

いかがでしたでしょうか。

mapbox GLJSの条件式は、JavaScriptの条件式とは異なる記述方法になっていますが、
ユースケースに応じて、条件式を組み合わせることで、JavaScriptの条件式と同じようなことができることがわかりました。

まだ様々な条件式があると思いますが、今回の記事が少しでもお役にたてればと思います。

今回の記事の参考サイト

Discussion