Mapbox Newsletter WEEKLY TIPSの解説 -「ヒートマップレイヤーの作成」
はじめに
この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「ヒートマップレイヤーの作成」についての解説です。このサンプルではヒートマップレイヤーを作成する方法を例示しています。
ヒートマップの作成方法についてはMapbox Newsletterでも紹介されていた【チュートリアル】Mapbox Studioで隕石落下地点のヒートマップを作成してみる|地図デザインの基礎も合わせてご参照いただければと思います。
また、Newsletterの購読はこちらからお申し込みいただけます。
コードを確認
まずExamplesのコードを見に行きましょう。
日本語サイト
英語サイト
基本的に同じコードですが、英語版はスタイルがMapbox Dark v11にアップグレードされているのでこちらを使用します。Mapbox Dark v10ではデフォルトのプロジェクションがWebメルカトルであるのに対し、Mapbox Dark v11ではGlobe(3D表示された地球)なので、印象がかなり異なります。
今回もコードが少し長めでドキッとしますが、順番に見ていけば大丈夫です。
HTML/CSS
まずHTMLを見ていきましょう。
以下は地図を表示するエレメントです。
<div id="map"></div>
Mapの作成
次にJavaScriptのコードを見ていきます。以下のコードはいつも通り、Mapオブジェクトを作成しています。container
で地図を表示するHTMLエレメントのidを指定します。
const map = new mapboxgl.Map({
container: 'map',
// Choose from Mapbox's core styles, or make your own style with Mapbox Studio
style: 'mapbox://styles/mapbox/dark-v11',
center: [-120, 50],
zoom: 2
});
load
イベント(map.on('load', () => {})
の中身)で1つのソース、2つのレイヤーを追加しています。
ソース
まず、ソースを見てみます。
data
にURLが指定されており、そこからGeoJSONを入手しています。
map.addSource('earthquakes', {
'type': 'geojson',
'data': 'https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson'
});
データの中身を覗いてみると以下のようなFeatureが大量に並んでいます。Pointデータで、プロパティとしてmag
(マグニチュード)などが含まれていることからもわかるように、これは地震のデータです。
{
"type": "Feature",
"properties": {
"id": "ak16994521",
"mag": 2.3,
"time": 1507425650893,
"felt": null,
"tsunami": 0
},
"geometry": {
"type": "Point",
"coordinates": [
-151.5129,
63.1016,
0
]
}
}
ヒートマップレイヤー
次に1つ目のレイヤー、ヒートマップレイヤーを見てみます。まずヒートマップレイヤーで大事なことは以下の3点です。
- ヒートマップは何らかの密度の分布を色で表現
- 密度の値が0~1の間で変化
- 0~1の値に応じた色を設定しておくことで分布の色味を決定
ヒートマップレイヤーを作成するためにはtype
にheatmap
を指定します。また、maxzoom
を9
としていることから、ズームレベルが9以上になるとここで作成したヒートマップレイヤーは表示されなくなります。さらに、addLayer
の第二引数に'waterway-label'
が指定されているので、waterway-label
レイヤーの下に配置されます。
map.addLayer(
{
'id': 'earthquakes-heat',
'type': 'heatmap',
'source': 'earthquakes',
'maxzoom': 9,
'paint': {
...
},
'waterway-label'
}
paint
の中身を見ていきます。
heatmap-weight
は重み値です。密度を表す0~1の値に使用される基準値となります。ここではソースのプロパティのmag
を読み取り、マグニチュードが0のときは0
、6のときは1
を出力します。それ以外の値は線形補間(interpolate
が['linear']
)されます。
'heatmap-weight': [
'interpolate',
['linear'],
['get', 'mag'],
0,
0,
6,
1
],
heatmap-intensity
は強度値です。ズームレベルに応じてweight
に乗じる値を指定します。ヒートマップは密度を表現しますが、ズームすればするほどデータがスカスカになって密度が下がるので、ズームレベルに応じてintensity
を乗算することで値が0に張り付くのを防ぎます。ここではzoom
が0のとき1
、9のとき3
を乗算します。
'heatmap-intensity': [
'interpolate',
['linear'],
['zoom'],
0,
1,
9,
3
],
heatmap-color
は色設定です。0~1と変化する値に応じて出力する色を設定しています。
'heatmap-color': [
'interpolate',
['linear'],
['heatmap-density'],
0,
'rgba(33,102,172,0)',
0.2,
'rgb(103,169,207)',
0.4,
'rgb(209,229,240)',
0.6,
'rgb(253,219,199)',
0.8,
'rgb(239,138,98)',
1,
'rgb(178,24,43)'
],
heatmap-radius
は帯域幅(Bandwidth)の設定です。Mapbox GL JSのヒートマップではカーネル密度推定と呼ばれる方法で密度を推定していますが、帯域幅はそこで用いられる値です。radius
という名前がついている通り、データのある点からどのぐらいの距離までを影響範囲とするかを指定します。ズームすればするほどデータがスカスカになって密度が下がるので、ズームレベルに応じてradius
を大きくすることで値が0に張り付くことを防止しています。
'heatmap-radius': [
'interpolate',
['linear'],
['zoom'],
0,
2,
9,
20
],
最後がheatmap-opacity
で不透明度です。ズーム7から9で不透明度が1から0に変化します。この設定により、サークルレイヤーになめらかに視覚効果が移行するようにしています。
'heatmap-opacity': [
'interpolate',
['linear'],
['zoom'],
7,
1,
9,
0
]
以上がヒートマップレイヤーの使い方となります。リファレンスも合わせてご参照ください。
サークルレイヤー
ヒートマップレイヤーはデータの存在するポイントを中心に、ぼやっとした分布を色で表現していました。サークルレイヤーはそれに加えてそのポイントの位置を表示するために使用されます。つまり、ヒートマップレイヤーの使い方としては必ずしも必要なレイヤーではないです。
minzoom
で7
が指定されているので、ズームレベルが7未満では表示されません。ヒートマップで不透明度がズームレベル7以上で変化していましたが、ちょうどそのズームレベルからサークルを表示させるようにしています。また、addLayer
の第二引数に'waterway-label'
が指定されているので、このレイヤーの下に配置されます。
map.addLayer(
{
'id': 'earthquakes-point',
'type': 'circle',
'source': 'earthquakes',
'minzoom': 7,
'paint': {
...
},
'waterway-label'
);
paint
の中身を見ていきます。
circle-radius
は円の半径です。mag
の値に応じて大きく、ズームレベルに応じて大きな円になるように設定されています。
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
7,
['interpolate', ['linear'], ['get', 'mag'], 1, 1, 6, 4],
16,
['interpolate', ['linear'], ['get', 'mag'], 1, 5, 6, 50]
],
circle-color
は円の色です。これもmag
の値に応じて色を変えています。
'circle-color': [
'interpolate',
['linear'],
['get', 'mag'],
1,
'rgba(33,102,172,0)',
2,
'rgb(103,169,207)',
3,
'rgb(209,229,240)',
4,
'rgb(253,219,199)',
5,
'rgb(239,138,98)',
6,
'rgb(178,24,43)'
],
circle-stroke
は円の縁の設定です。縁の色が白で、ズームレベルに応じて太くしています。
'circle-stroke-color': 'white',
'circle-stroke-width': 1,
// Transition from heatmap to circle layer by zoom level
'circle-opacity': [
'interpolate',
['linear'],
['zoom'],
7,
0,
8,
1
]
まとめ
ヒートマップレイヤーの使い方について確認しました。設定項目は多いですが、サンプルやチュートリアルを動かして雰囲気を掴んでみてください。
Discussion