Mapbox Newsletter WEEKLY TIPSの解説 -「expressionを使用してグラデーションラインを作成」
はじめに
この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「expressionを使用してグラデーションラインを作成」についての解説です。このサンプルではExpressionsを使ってLineStringの色をグラデーションさせる方法を例示しています。また、Newsletterの購読はこちらからお申し込みいただけます。
以下が本サンプルのデモです。
コードを確認
まずExamplesのコードを見に行きましょう。
日本語サイト
英語サイト
基本的に同じコードですが、英語版はスタイルがMapbox Light v11にアップグレードされているのでこちらを使用します。Mapbox Light v10ではデフォルトのプロジェクションがWebメルカトルであるのに対し、Mapbox Light 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/light-v11',
center: [-77.035, 38.875],
zoom: 12
});
GeoJSONの作成
今回のサンプルは線を引くので、LineStringのデータをGeoJSONで作成しています。
const geojson = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'properties': {},
'geometry': {
'coordinates': [
[-77.044211, 38.852924],
[-77.045659, 38.860158],
...
],
'type': 'LineString'
}
}
]
};
ソースの追加
map.on('load', () => {}
の中身を見ていきます。以下の部分でソースを追加しています。先ほど作成したGeoJSONをソースとして使用します。lineMetrics
をtrue
に設定しておかないとError: layers.line: layer "line" specifies a line-gradient, which requires a GeoJSON source with lineMetrics enabled.
というエラーが発生するので注意が必要です。
map.addSource('line', {
type: 'geojson',
lineMetrics: true,
data: geojson
});
レイヤーの追加
次にレイヤーの追加です。ここでいよいよグラデーションの登場です。レイヤーの役割は見た目(色や形)を指定することなので、ここでグラデーションが出てくるのは納得ですね。
まずはグラデーション以外の部分を見ていきます。線を引くのてtype
はline
、source
はさきほどしたソースのIDであるline
を指定します。paint
プロパティではデフォルトの色として'line-color': 'red'
、太さを'line-width': 14
としています。また、layout
プロパティは'line-cap': 'round'
で線の始点と終点を丸く、'line-join': 'round
で線のカドを丸くしています。
map.addLayer({
type: 'line',
source: 'line',
id: 'line',
paint: {
'line-color': 'red',
'line-width': 14,
// 'line-gradient' must be specified using an expression
// with the special 'line-progress' property
'line-gradient': [
...
]
},
layout: {
'line-cap': 'round',
'line-join': 'round'
}
});
そして以下がグラデーションです。グラデーションはExpressionsで指定します。ExpressionsはJSONの配列で表現する式で["op", "param1", ...]
という形式を取ります。配列の要素0が命令、それ以降がパラメータです。ちょうどLisp言語のS式のような感じです。
'line-gradient': [
'interpolate',
['linear'],
['line-progress'],
0,
'blue',
0.1,
'royalblue',
0.3,
'cyan',
0.5,
'lime',
0.7,
'yellow',
1,
'red'
]
interpolate
は補間に関するExpressionsです。第一引数がtypeでlinear
なら線形補間、exponential
なら指数的な補間が使用されます。ここではlinear
が指定されているので線形補間です。
第二引数が「値」の供給源の指定です。この「値」に応じて以降で指定する色が使用されます。ここではline-progress
というExpressionsが使用されていますが、これはLineの始点からどれぐらいの場所かを返します。始点が0
、終点が1
です。
一般にinterpolate
の第二引数には、['get', プロパティ名]
と記述するすることでプロパティに応じてline-color
を変えるというような使い方をします。しかしline-gradient
ではこのような使い方はできません。これはプロパティのタイプにより決まっています。
第三引数以降が「値」「出力」の組です。ここでは0
(始点)がblue
、0.1
(10%地点)でroyalblue
…1
(終点)がred
です。
ちなみに、line-gradient
のソースに使用できるのはGeoJSONのみです。Vector TilesetではLineString全体が読み込まれているとは限らず、グラデーションが計算できないからではないかと推察します。
まとめ
Lineのグラデーションはline-progress
を使うということがポイントでした。lineMetrics
の指定も忘れないようにしましょう。
Discussion