Mapbox Newsletter WEEKLY TIPSの解説 -「場所にゆっくり飛ぶ」
はじめに
この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「場所にゆっくり飛ぶ」についての解説です。これはMap#flyTo
のオプションの使い方のサンプルです。また、Newsletterの購読はこちらからお申し込みいただけます。
以下が本サンプルのデモです。
コードを確認
まずExamplesのコードを見に行きましょう。
日本語サイト
英語サイト
基本的に同じコードですが、英語版はスタイルがMapbox Streets v12にアップグレードされているのでこちらを使用します。Mapbox Streets v11ではデフォルトのプロジェクションがWebメルカトルであるのに対し、Mapbox Streets v12ではGlobe(3D表示された地球)なので、印象がかなり異なります。また、コードの中で3D地形や深いピッチ角を使用することで、より印象的な雰囲気に仕上がっています。
HTML/CSS
まずCSSです。以下は上部中央に表示されているFlyボタンのためのスタイルです。
#fly {
display: block;
position: relative;
margin: 0px auto;
width: 50%;
height: 40px;
padding: 10px;
border: none;
border-radius: 3px;
font-size: 12px;
text-align: center;
color: #fff;
background: #ee8a65;
}
次にHTMLです。以下は地図を表示するエレメントを作成しています。
<div id="map"></div>
以下はFlyボタンです。
<button id="fly">Fly</button>
Mapの作成
次にJavaScriptのコードを見ていきます。
以下はflyTo
の始点・終点におけるカメラの設定値です。特筆すべきはend.pitch
が75
に設定されていることです。Mapbox GL JS v2からはピッチが80度まで設定可能になりました(v1は60度)が、ピッチを大きく設定すると水平線と空がカメラに収まるようになります。
const start = {
center: [80, 36],
zoom: 1,
pitch: 0,
bearing: 0
};
const end = {
center: [8.11862, 46.58842],
zoom: 12.5,
bearing: 130,
pitch: 75
};
以下のコードはいつも通り、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/satellite-streets-v12',
...start
});
...start
はオブジェクトリテラルでのスプレッド構文です。以下のように記述したのと同じ効果があります。
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/satellite-streets-v12',
center: [80, 36],
zoom: 1,
pitch: 0,
bearing: 0
});
スタイルの設定
map.on('style.load', () => {/* ここ */});
ではスタイルがロードされたタイミングで行う設定を/* ここ */
の部分に記述しています。イベントとしてstyle.load
を使用すると、スタイルのロード直後、描画の直前に実行されるので、ユーザーの目には最初から設定が反映されているように見えます。
Map#setFog
はFog
の設定を行います。Fogとは空や宇宙の色や、霧っぽさの演出を表現するスタイルです。color
で水平線より下(つまり霧)の色、hight-color
で水平線より上(つまり空)の色を指定します。horizon-blend
はこの二色の境界をどれだけぼかすかを指定します。
map.setFog({
'color': 'rgb(220, 159, 159)', // Pink fog / lower atmosphere
'high-color': 'rgb(36, 92, 223)', // Blue sky / upper atmosphere
'horizon-blend': 0.4 // Exaggerate atmosphere (default is .1)
});
試しに'horizon-blend': 0
としてみると以下のように二色がくっきりと別れてこれらの設定値の挙動がわかりやすくなります。
続いて3D地形を設定しています。 設定方法はこれ以外ないのでイディオムとして覚えてしまうのが良いかと思います。ソースで読み込んているmapbox.terrain-rgb
は標高情報を色情報としてエンコードしたラスタータイルセットです。setTerrain
でこのソースを指定することで、内部的にはheight = -10000 + ((R * 256 * 256 + G * 256 + B) * 0.1)
という計算で高さを算出し、3D地形を表現します。ちなみに、ソースとしてはmapbox.mapbox-terrain-dem-v1
を用いるほうが好ましいです。
map.addSource('mapbox-dem', {
'type': 'raster-dem',
'url': 'mapbox://mapbox.terrain-rgb'
});
map.setTerrain({
'source': 'mapbox-dem',
'exaggeration': 1.5
});
Flyボタンクリック時の挙動
いよいよ本題です。isAtStart
は"start -> end"方向なのか"end -> start"方向なのかを管理するためのフラグです。
let isAtStart = true;
Flyボタンがクリックされたときの挙動の定義をコールバックで指定しています。
document.getElementById('fly').addEventListener('click', () => {
//ここ
});
向きによってstart/endどちらが終点になるかを指定し、次回のためにisAtStart
をトグルします。
const target = isAtStart ? end : start;
isAtStart = !isAtStart;
いよいよflyTo
です。説明にもある通り、flyTo
はCameraOptions
とAnimationOptions
をオプションとして指定可能です。...target
はCameraOptions
に関する設定、duration
とessential
はAnimationOptions
に関する設定です。duration
は何秒間アニメーションするかです。essential
をtrue
にすると、ユーザーがOSの設定でアニメーションを抑制する設定(prefers-reduced-motion
)にしていても無視します。
map.flyTo({
...target, // Fly to the selected target
duration: 12000, // Animate over 12 seconds
essential: true // This animation is considered essential with
//respect to prefers-reduced-motion
});
まとめ
いちばん大事なのはflyTo
のオプションでduration
を指定する部分でした。
Discussion