これはレイアウト確認用のダミーテキストです。
Mapbox Japan Weather Layers
これはレイアウト確認用のダミーテキストです。
Mapbox Japan Weather Layers

雨雲レーダーは、地図上で雨雲の現在位置や将来予測される位置を表示するサービスであり、日本では広く普及しております。気象災害対策、交通情報、マーケティングなど、様々な分野で活用されております。本ブログでは、気象タイルセットを提供するサービスであるMapbox Japan Weather Layers(以下JWLとも表記)と、Mapbox 、雨雲レーダーを作成した記録についてお話しします。実際に動くデモはこちらでご覧いただけます。またデモのコードはこちらのGithubリポジトリにて公開しております。

基本的に雨雲などの気象データは、GRIB2と呼ばれるバイナリデータで気象庁などから提供されています。これを地図に表示する際には、GRIB2の解析、およびタイルセットへの変換が必要となります。このための複雑なパイプラインの構築に加え、絶え間なく更新される気象データをタイルセット化に変換し続けるための高額なインフラストラクチャコストへの対応が必要でした。JWLは、Mapboxで気象データをタイルセット化し配信するため、従来とは異なり、どなたでも気軽にご利用いただけます。また、Mapbox APIを併用することで、気象データをjson形式で取得可能です。Mapbox WeatherLayersについてはこちらをご参照ください。
本ブログで紹介する雨雲レーダーは、次の5つの要素で構成されます。一番下にあるのがベースマップ、その上にJWLのタイルセット、降水量の凡例、表示するタイルセットのband(バンドとも表記)を切り替えるためのタイムスライダー、そして表示されているbandの時刻を表示する時刻ボックスです。
バンドとは、JWLタイルセットの単一時間スライスを指します。各バンドは異なる時間データを表します。例えば、mapbox.weather-jp-nowcastには13の異なる時間バンドが含まれます。これは現在降水量と、5分刻みで最大60分先までの将来降水量をカバーしているためです。データが9:00に開始すると仮定しますと、最初のバンドは9:00時点の観測降水量を表します。続くバンドは予測降水量を表し、2番目のバンドは9:05の予測値となります。このパターンはデータの終了時刻である10:00まで続きます。
重要なポイント:mapbox。レジェンドはJWLタイルセットの色設定に合わせて表示されます。タイムダイアログでは、表示中のバンド(時刻)を日本標準時(JST)に変換して表示します。JWLのタイルセットは以下の4つのタイルセットを利用しており、タイムスライダーで表示するタイルセットのバンドを切り替えます。


本デモで利用するタイルセット以外にも、複数のタイルセットが存在します。JWLのタイルセット一覧をご覧ください。
JWLの降水値を「どのように色で表現するか」は、ユーザー体験に直結します。本実装では、気象庁の一般的な降水階級に基づいたカラー表現を採用します。下記では値がない場合や、値が0の場合は、rgbaを0にして透明になるようにしています。また、Mapboxの仕様により、例えば降水強度1mmに相当する色を指定したい場合は、1より低い値(下記では0.99)をコード内で記述する必要があります。
const rasterColorExpression = [ 'step',
['raster-value'],
透明な黒 0.05, 'rgba(242, 242, 255, 0.9)', 0.99, 'rgba(160, 210, 255, 0.9)',
4.99, 'rgba(33, 140, 255, 0.9)', 9.99, 'rgba(0, 65, 255, 0.9)', 19.99, 'rgba(250, 245, 0, 0.9)',
29.99, 'rgba(255, 153, 0, 0.9)', 49.99, 'rgba(255, 40, 0, 0.9)', 79.99, 'rgba(180, 0, 104, 0.9)'
];ラスター再サンプリングを'nearest'に設定すると、一般的な雨雲レーダーと同様に四角いメッシュが並んだ表現となります。'interpolate'に設定すると、滑らかな表現となります。
map.addLayer({
id: `rain-layer-${tileset.id}`,
type: 'grid',
source: `rain-source-${tileset.id}`,
paint: {
'raster-array-band': '',
'raster-color': rasterColorExpression,
'raster-color-range': [0, 100],
'raster-opacity': 0,
'raster-resampling': 'nearest',
'raster-color-range-transition': {
duration: 0
}
}
});下の最初の画像は、「nearest」が使用された場合のメッシュの外観を表しており、2番目の画像は代わりに「interpolate」が設定された場合を示しています。


タイムスライダーを操作するたびに毎回タイルセットをロードすると、UIの遅延や視覚的なちらつきが生じます。そこで本実装では、最初にすべてのJWLのタイルセットを読み込み、タイムスライダーの操作に応じてband(時刻)のみを切り替えるアプローチを採用しております。
map.addSource(`rain-source-${tileset.id}`, {
type: 'raster-array',
url: `mapbox://${tileset.id}`,
tileSize: 1026
});4つのタイルセットは異なる時間帯をカバーしております。そのため、重複バンドの削除、時系列のソート、現在時刻の位置付けを行い、「一つの連続した時間スライダー」としてご利用いただける形式に統合いたします。ユーザー様は過去から未来まで、一つのUI上で自然に操作いただけます。今回の雨雲レーダーにおける重複バンドにつきましては、気象庁のデータ仕様上、現在から60分先の雨雲データであるmapbox.weather-jp-nowcastの最終バンド(60分先)と、mapbox.weather-jp-rain-1-6の最初のバンド(1時間先=60分先)が同一時刻を示す場合があります。そのため、更新頻度の高いmapbox.weather-jp-nowcastのバンドを優先的に表示するようにしています。
allBands = [];
let lastNowcastBandId = null;
for (const tileset of sortedTilesets) {
const result = results.find(r => r?.tileset.id === tileset.id);
if (!result || !result.metadata) continue;
const metadata = result.metadata;
if (metadata.raster_layers && metadata.raster_layers.length > 0) {
const layer = metadata.raster_layers[0];
const layerName = layer.name || 'precipitation';
const rawBands = layer.bands || layer.fields?.bands || [];
// Parse and sort bands once
let bandIds = rawBands
.map(b => {
if (typeof b === 'object' && b.band_id) return parseInt(b.band_id);
if (typeof b === 'string' || typeof b === 'number') return parseInt(b);
return NaN;
})
Filter the array to include only values that are not NaN.
.sort((a, b) => a - b);
// Apply filters based on tileset type
if (tileset.id === 'mapbox.weather-jp-nowcast-last-60m') {
// Remove last band (overlaps with nowcast)
if (bandIds.length > 0) {
bandIds = bandIds.slice(0, -1); // ← Remove last band
}
} else if (tileset.id === 'mapbox.weather-jp-rain-1-6') {
// Only keep bands after last nowcast band
if (lastNowcastBandId !== null) {
bandIds = bandIds.filter(b => b > lastNowcastBandId); // ← Filter overlapping bands
}
}
// Track last nowcast band for filtering next tileset
if (tileset.id === 'mapbox.weather-jp-nowcast' && bandIds.length > 0) {
lastNowcastBandId = bandIds[bandIds.length - 1]; // ← Store for comparison
}ユーザーがスライダーを動かすと、表示するバンド(=時刻)を即座に切り替えます。JWLのタイルセットの不透明度を操作することで、表示するバンド以外のタイルセットは透明になるようにします。例えば、mapbox.weather-jp-nowcastのバンドを表示している際は、他の3つのタイルセットの不透明度を0にします。
map.setPaintProperty(layerId, 'ラスター配列バンド', バンドのバンドID.toString());
map.setPaintProperty(layerId, 'raster-opacity', 0.85);前述の通り、Mapbox Weather Layersをご利用いただければ、最小限の技術的労力とコストで雨レーダーなどの天気マップコンテンツを簡単に実装できます。本ブログでご紹介したデモの完全なコードは、GitHubリポジトリでご確認ください。
JWLで配信される降水タイルセットは、日本の防災インフラを支える気象庁(JMA)の数値予報・実況データに基づいています。

これはレイアウト確認用のダミーテキストです。