TomTomのスタイルを体験する
はじめに
この記事ではTomTomにおけるスタイルの挙動を確認します。具体的にはMaps SDK for Web V6を使って地図を表示し、どのようにスタイルを使うのかを見ていきます。
この記事は以下の企画の子記事です。他サービスの記事へのリンクがあるので、ぜひ合わせてご参照ください。
地図を表示する
チュートリアルを参考に地図を表示してみましょう。
まず、以下のライブラリを読み込みます。
<link rel="stylesheet" href="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/<version>/maps/maps.css" />
<script src="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.23.0/maps/maps-web.min.js"></script>
CSSを設定します。
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
次に地図を表示する場所を作ります。
<div id="map"></div>
JavaScriptのコードは以下のようになります。
const map = tt.map({
key: YOUR_API_KEY_HERE,
container: 'map',
center: [139.768435, 35.681054],
zoom: 8,
});
map.addControl(new tt.FullscreenControl());
map.addControl(new tt.NavigationControl());
Mapクラスのコンストラクタにはオプションを設定します。最低限、key
とcontainer
は設定する必要があります。この他にもcenter
、zoom
で初期位置等が設定できます。
addControl
では全画面表示、ズーム等のコントロールを表示しています。
スタイルの変更
スタイルはMap Style Specificationで定義されたJSONオブジェクトです。Mapオブジェクト作成時のオプションとしてstyle
が設定可能で、JSONファイルのURLやJSONオブジェクトそのものを指定することで設定ができます。またMap#setStyleを使用することで動的にスタイルを変更することも可能です。早速これらを使ってみましょう。
まず、スタイルを選択できるようにします。
<select id="selector">
<option value="day">Day</option>
<option value="night">Night</option>
</select>
<select>
が隠れないように、CSSを調整します
#map { position: absolute; top: 10; bottom: 0; height: 95%; width: 100%; }
コードでは、まず各スタイルのURLを定義します。Map
オブジェクト作成時にstyle
でURLを指定します。また、<select>
による選択時にsetStyle
でスタイルを切り替えます。
const URLS = {
day: 'https://api.tomtom.com/style/1/style/21.1.0-*?map=basic_main&traffic_incidents=incidents_day&traffic_flow=flow_relative0&poi=poi_main',
night: 'https://api.tomtom.com/style/1/style/21.1.0-*?map=basic_night&traffic_incidents=incidents_day&traffic_flow=flow_relative0&poi=poi_main',
};
const map = tt.map({
key: YOUR_API_KEY_HERE,
container: 'map',
style: URLS['day'],
center: [139.768435, 35.681054],
zoom: 8,
});
map.addControl(new tt.FullscreenControl());
map.addControl(new tt.NavigationControl());
selector.addEventListener("change", () => {
map.setStyle(URLS[selector.value]);
});
スタイルのカスタム
Map Stylerというサービスを使用すると、スタイルを編集することができます。ここでは高速道路の色を赤色にします。
左側にレイヤーが並んでいるので、Surface Motorway & Trunkを選択します。
中程のPAINT PROPERTIESのColorのExpressionsを以下のように変更します。
[
"interpolate",
["exponential", 1],
["zoom"],
5,
[
"match",
["get", "category"],
"motorway",
"#FF0000", //ここ
"trunk",
"hsl(37, 80%, 60%)",
"hsla(0, 0%, 0%, 0)"
],
9,
[
"match",
["get", "category"],
"motorway",
"#FF0000", //ここ
"trunk",
"hsl(47, 100%, 80%)",
"hsla(0, 0%, 0%, 0)"
]
]
変更が右側のプレビューで即座に反映されます。最後にEXPORTをクリックするとスタイルのJSONファイルをダウンロードできます。今回はGist上にファイルを置きました。
さて、このJSONファイルをJavaScriptのコードで読み込めばOKです。当初以下のように実装していました。セレクタで選択されると、default/customのURLを切り替えてsetStyle
という挙動です。
const URLS = {
default: 'https://api.tomtom.com/style/1/style/21.1.0-*?map=basic_main&traffic_incidents=incidents_day&traffic_flow=flow_relative0&poi=poi_main',
custom: 'https://gist.githubusercontent.com/OttyLab/f4526ddf444b8f4add296ad337bcc601/raw/d220f74a6425ccda1d24da6c3594f7677683b6ac/tomtom_custom.json',
};
const map = tt.map({
key: YOUR_API_KEY_HERE,
container: 'map',
style: URLS['day'],
center: [139.768435, 35.681054],
zoom: 8,
});
map.addControl(new tt.FullscreenControl());
map.addControl(new tt.NavigationControl());
selector.addEventListener("change", () => {
map.setStyle(URLS[selector.value]);
});
しかし、このコードはCORSエラーで動きませんでした。挙動をデバッグしてみるとfetch
でGETリクエストする際にTomTom-User-Agent
というヘッダが付加されており、これにより単純リクエストではなくなってCORSエラーとなっているようでした。以下の画像がTomTom-User-Agent
を付加している場所ですが、外部からこの挙動を変更できそうになかったです。
そこで今回は以下のように自前でfetch
を呼び、予めJSONをダウンロードしておくことで回避しました。
const custom = (async () => {
const response = await fetch('https://gist.githubusercontent.com/OttyLab/f4526ddf444b8f4add296ad337bcc601/raw/d220f74a6425ccda1d24da6c3594f7677683b6ac/tomtom_custom.json');
const custom = await response.json();
const URLS = {
default: 'https://api.tomtom.com/style/1/style/21.1.0-*?map=basic_main&traffic_incidents=incidents_day&traffic_flow=flow_relative0&poi=poi_main',
custom: custom,
};
const map = tt.map({
key: YOUR_API_KEY_HERE,
container: 'map',
style: URLS['day'],
center: [139.768435, 35.681054],
zoom: 8,
});
map.addControl(new tt.FullscreenControl());
map.addControl(new tt.NavigationControl());
selector.addEventListener("change", () => {
map.setStyle(URLS[selector.value]);
});
})();
自前のサーバにJSONを配置する際は、Access-Control-Allow-Origin
を正しく設定することでこの問題は回避できます。
Mapbox GL JSとの互換性(番外編)
とくに記述はありませんが、TomTomのStyleはMapboxのスタイルと互換性があります。したがって、Mapbox GL JSでTomTomのスタイルを読み込むと表示できます。左下にMapboxロゴが表示されているのでMapbox GL JS上でスタイルが動いていることがわかります。
実はデバッグをしていて気づいたのですが、Maps SDK for Web V6は内部でMapbox GL JS v1.13.2を使用しています。以下のコードはMaps SDK for Web V6におけるMapオブジェクトの初期化処理の一部ですが、Mapbox GL JSのMapオブジェクトを作成しています。
また、以下はMapbox GL JSのテレメトリのコードであると推察されます。
Mapbox GL JSを内部的に使用しているのであればスタイルが同じ形式であるのも、ライブラリの使い方が似ているのも納得できます。
まとめ
TomTomにおけるスタイルはMapbox GL JSと互換性があり、ソースやレイヤーの概念も同じです。したがって、Mapbox GL JSを知っていれば特に違和感なくTomTomも使用できるかと思います。また、Map StylerもMapbox Studioと似た使用感なので学習コストは低いと考えられます。
Discussion