Mini Tokyo 3D バージョン 3.2.0 リリース

Mini Tokyo 3D バージョン 3.2.0 がリリースされました (GitHub)。3.1.0 からの追加・修正機能を見ていきましょう。

新しい追跡モードと追跡モード設定パネルの追加

列車・旅客機の追跡モードを大幅に強化しました。画面右側のビデオカメラのアイコンボタンを押すと表示される追跡モード設定パネルで、「位置のみ」「前方」「前方上空」「後方」「後方上空」「ヘリコプター」「ドローン」「鳥」の8種類の視点を選べます。

おすすめは「鳥」追跡モード。方角、ズーム、ピッチ全てがスムーズかつダイナミックに変化するため、時間を忘れて列車の旅を楽しむことができるでしょう。

API からも新しい追跡モードの指定ができるようになっています。

列車・旅客機の高度に応じたスケーリングとズームの調整

地下を走る列車のスケーリングおよび追跡時のズームレベルの計算を修正しました(左: 修正前、右: 修正後)。修正前は地下で列車がやや小さく見えてしまっていましたが、列車位置の標高に応じた見え方の一貫性が保たれるようになりました。また、スケーリングの計算を GPU で行うように最適化し、性能への影響を最小限に抑えています。

追跡前の視点への復帰

列車や旅客機をクリックまたはタップすると追跡が開始され、前述の追跡モードの設定によっては対象の列車や旅客機にズームインしていきますが、これまでは追跡を解除した時に現在位置を見失いがちで不便に感じることがあったかと思います。

そこで追跡前の視点を記憶しておき、追跡が解除された際には元の視点に戻るようにしました。駅やライブカメラを選択した場合も同様に、選択解除後に元の視点に戻ります。

動的な車両形式情報のローディング

車両形式データを動的に読み込むことに対応しました。何かのイベント開催時や臨時列車が走るときに、サーバ側のデータを更新することで簡単に特定の車両を走らせることができるようになります。

この機能を利用し、鉄道開業150年記念「黒い山手線」の現在位置表示に対応。150年前に新橋〜横浜間で運行した1号機関車をモチーフにした黒塗りの車両が山手線を走ります(運用は毎日変わりますが、実際の運用状況を反映しています!)。2022年12月31日までの期間限定。

アイコンスタイル更新

内部で利用しているアイコンフォントライブラリのアップデートにより、一部のアイコンスタイルが更新されました。これまでと比べて見た目の統一感が増し、視認性が上がっているのがわかりますかね?

ダイヤ改正対応

東京メトロ銀座線・丸ノ内線東西線・千代田線の 2022/8/27 ダイヤ改正に対応。また、ふかや花園プレミアム・アウトレット開業に伴う秩父鉄道の 2022/10/1 ダイヤ改正にも対応。さらに、特急成田エクスプレスの 2022/10/1 からの全列車の運転再開に対応し、東京〜新宿間が日中1時間に2本ペースになりました。

ライブカメラの拡充

ライブカメラプラグインで表示される、沿線のライブカメラがさらに追加されました。

Mini Tokyo 3D バージョン 3.1.0 リリース

Mini Tokyo 3D バージョン 3.1.0 がリリースされました (GitHub)。

Mini Tokyo 3D は昨年の第4回東京公共交通オープンデータチャレンジに応募しておりましたが、第3回の受賞に引き続き、完成度の高さを評価いただいて今回は審査員特別賞を受賞することができました。東京公共交通オープンデータチャレンジは今回で終了になりましたが、Mini Tokyo 3D は引き続き進化を続けていきます。

それでは 3.0.0 からの追加・修正機能を見ていきましょう。

公共交通データソースの切り替え

東京公共交通オープンデータチャレンジの終了に伴い、これまで東京公共交通オープンデータチャレンジのデータを利用していたところを、公共交通オープンデータセンターのデータに切り替えました。これにより、一部のリアルタイム遅延情報が利用できなくなっており、遅延マーカーが表示されません。また、旅客機の表示も国内線に限定されています。

開発者が Mini Tokyo 3D をビルドする際には、東京公共交通オープンデータチャレンジのトークンは不要になりました。

ダイヤ改正対応

ゆりかもめの 2021/12/13 ダイヤ改正に対応。さらに、都営浅草線京急、京成、北総、芝山鉄道の 2022/2/26 ダイヤ改正、JR 東日本、りんかい線東京メトロ、都営、横浜市営、京王、東武、西武、小田急、東急、みなとみらい線、相鉄、埼玉高速鉄道つくばエクスプレス東葉高速鉄道関東鉄道小湊鐵道いすみ鉄道ニューシャトル多摩モノレールの 2022/3/12 ダイヤ改正に対応しています。

列車情報の修正

データソースの切り替えとダイヤ改正対応に伴い、データ全体の検証を強化したところ、多くの不具合が見つかりました。次のデータの修正を行い、データの正確性が向上しました。

  • 京急モーニング・ウィング三浦海岸〜横須賀中央間が非表示だった問題を修正
  • 京急逗子線から京急本線への直通列車の追跡が中断してしまう問題を修正
  • 新京成線鎌ヶ谷鎌ヶ谷大仏を全列車通過していた問題を修正
  • いすみ鉄道城見ヶ丘を全列車が通過していた問題を修正
  • 千葉モノレール1号線の土休日の列車の行き先が一部表示されていなかった問題を修正
  • 湘南モノレールで全列車が富士見町を通過していた問題を修正
  • 東急こどもの国線は多客期ダイヤだったのを通常ダイヤに変更
  • 東武東上線の一部列車で和光市〜志木間で列車が表示されていなかった問題を修正
  • 西武秩父線の一部列車で行き先が間違っていた問題を修正
  • 西武多摩川線の白糸台始発の列車が表示されていなかった問題を修正
列車名表示の追加

京急ウィング号の列車名と号数、ホリデー快速おくたまホリデー快速あきがわの列車名が表示されるようになりました。そして京王ライナー Mt.TAKAO 号が臨時便から通年運行になったので、Mini Tokyo 3D にも現れるようになっています。

ボタンを大きくして操作性改善

ボタンのサイズを1.3倍に拡大して操作性を改善しました。最近のスマホの高解像度化でボタンサイズが相対的に小さくなっているため、Mapbox のデフォルトのボタンサイズだと少しタップしにくかったので改良を加えました。

ポルトガル語サポート

コミュニティーのコントリビューションにより、ポルトガル語(ブラジル)に対応しました。

アプリ起動の高速化

アプリ起動時のデータローディングの並列化を実装し、起動時間の短縮を図りました。

降水プラグインが雪のアニメーションに対応

内部で使用している Mapbox プラグインのアップデートに伴い、Mini Tokyo 3D 降水プラグインでも降雪アニメーションの表示に対応しました。

ライブカメラの拡充

ライブカメラプラグインで、東京近郊鉄道沿線のライブカメラを大幅に追加し、現在の東京の様子がより身近に感じられるようになりました。

Mini Tokyo 3D バージョン 3.0.0 リリース

Mini Tokyo 3D バージョン 3.0.0 がリリースされました (GitHub)。前回のリリースからだいぶ時間が経ってしまいました。バージョン 2.x からのメジャーアップグレードということで、多くの変更や改善(開発者向け API の互換性に影響のあるものを含む)が入っています。

また、本バージョンは Mini Tokyo 3D 2021 として第4回 東京公共交通オープンデータチャレンジの応募作品になっています。応募用の YouTube 動画も公開していますので、そちらもご覧ください。

それでは、2.8.0 からの追加・修正機能を見ていきましょう。

描画性能の大幅な改善

3D モデルレンダリングコードを刷新しました。インスタンシングと GPU ピッキングの導入で、列車と旅客機の描画・ピッキング処理を GPU 側に寄せることで大幅に効率化しました。これまでは、ピーク時で 1,500 程度のオブジェクトの表示でしたが、処理能力に余裕ができたことで後述の路線の拡張が可能になり、2,200 程度のオブジェクトの表示も問題なく実現できています。

f:id:nagixx:20211123144004j:plain

f:id:nagixx:20211123144010j:plain

列車・旅客機のハイライト表示、旅客機の尾翼形状の改善

上記の改善に加え、シェーダーにある程度のロジックを追加し、マップのズーム操作や地上・地下切り替えに伴う変換行列の再演算や透過率の計算をCPU側からGPU側に移動。旅客機をズームした時の尾翼の取り付き方の改良やフォーカス時のアウトラインの均等化などの細かい改善も追加しました。

f:id:nagixx:20211123145234j:plain

対応路線・エリアが大幅に拡大

対応路線・エリアが大幅に拡大し、これまでの路線を含めると合計 150路線(支線・連絡線含む)、1,684駅、平日の列車本数は 47,310本になりました。いわゆる首都圏近郊はJR・私鉄含めほぼカバーされました。

路線 説明
JR 横須賀線 大船〜久里浜間を追加
JR 横須賀線 大船〜熱海間を追加
JR 伊東線 熱海〜伊東間が新規開通
JR 相模線 茅ヶ崎〜橋本間が新規開通
JR 青梅線 青梅〜奥多摩間を追加
JR 高崎線 鴻巣〜高崎間を追加
JR 八高線 小川町〜高崎間を追加
JR 宇都宮線 久喜〜宇都宮間を追加
JR 常磐線 取手〜水戸間が新規開通
JR 総武本線 八街〜銚子間を追加
JR 東金線 大網〜成東間が新規開通
JR 成田線 滑河〜銚子間を追加
JR 鹿島線 香取〜鹿島サッカースタジアム間が新規開通
JR 内房線 君津〜安房鴨川間を追加
JR 外房線 上総一ノ宮〜安房鴨川間を追加
JR 久留里線 木更津〜上総亀山間が新規開通
京急本線 金沢八景浦賀間を追加
京急逗子線 金沢八景〜逗子・葉山間が新規開通
京急久里浜線 堀ノ内〜三崎口間が新規開通
都電荒川線 三ノ輪橋〜早稲田間が新規開通
東武伊勢崎線 久喜〜伊勢崎間を追加
東武佐野線 館林〜葛生間が新規開通
東武小泉線 館林〜西小泉間、太田〜東小泉間が新規開通
東武桐生線 太田〜赤城間が新規開通
東武日光線 東武動物公園東武日光間が新規開通
東武鬼怒川線 下今市〜新藤原間が新規開通
東武東上線 小川町〜寄居間を追加
東武越生線 坂戸〜越生間が新規開通
西武池袋線 飯能〜吾野間を追加
西武秩父線 吾野西武秩父間が新規開通
西武山口線 多摩湖西武球場前間が新規開通
小田急小田原線 伊勢原〜小田原間を追加
小田急江ノ島線 藤沢〜片瀬江ノ島間を追加
関東鉄道常総線 取手〜下館間が新規開通
関東鉄道竜ヶ崎線 佐貫〜竜ヶ崎間が新規開通
流鉄流山線 馬橋〜流山間が新規開通
小湊鉄道線 五井〜上総中野間が新規開通
いすみ鉄道いすみ線 大原〜上総中野間が新規開通
金沢シーサイドライン 新杉田金沢八景間が新規開通
江ノ島電鉄線 藤沢〜鎌倉間が新規開通
湘南モノレール江の島線 大船〜湘南江の島間が新規開通
山万ユーカリが丘線 ユーカリが丘ユーカリが丘間が新規開通
ニューシャトル 大宮〜内宿間が新規開通
秩父鉄道秩父本線 羽生〜三峰口間が新規開通
ダイヤ改正対応

前バージョンで未対応だった、りんかい線つくばエクスプレス、相鉄の 3/13 ダイヤ改正に対応。このほか、都営浅草線京急、京成、北総、芝山鉄道の 3/27 ダイヤ改正横浜市営地下鉄の 6/26 ダイヤ改正関東鉄道常総線の 10/2 ダイヤ改正京急久里浜線の 10/18 ダイヤ変更、京成スカイライナーの一部列車の運転再開 (10/30)、京王ライナー土休日の明大前停車開始 (10/30)、などに対応しています。

新しい降水プラグイン

新しい Mini Tokyo 3D 降水プラグインは、以前のパーティクルエンジンを使用したものから、ポリゴンをインスタンス化した方式に変更しました。マシンへの負荷が軽減してマップの拡大・縮小・移動時にもスムーズに表示の更新ができるようになっています。

内部では別途 Mapbox レイヤープラグインとしてリリースした mapbox-gl-rain-layer を使用しています。

東京2020オリンピックプラグイン

Tokyo 2020 Olympics プラグインが追加され、Mini Tokyo 3D マップ上でオリンピック競技会場とスケジュールをチェックすることができます。プラグインを追加すると、オリンピックスタジアム(新国立競技場)の 3D モデルが表示されるようになります。ズームしても鑑賞に堪えるテクスチャ付き高精細モデルを利用しています。また、オリンピック開会式までのカウントダウンや開催日からの経過日数も表示。競技スケジュールの競技名の背景色は、東京2020大会のコアグラフィックス"かさねの色目"「紅」「藍」「藤」「松葉」に合わせています。

新しいユーザーガイド・開発者ガイド

Mini Tokyo 3D ユーザーガイド/開発者ガイドを、Web ページに移行しました。従来より読みやすくなり、内容も拡充しています。

f:id:nagixx:20211123162636j:plain

MiniTokyo3D クラスではなく mt3d 名前空間をエクスポート(API 互換性に影響する変更)

開発者向け API を使う際は、従来の MiniTokyo3D クラスの代わりに、mt3d.Map クラスにコンストラクタオプションを渡して Mini Tokyo 3D マップのオブジェクトを作成します。mt3d 名前空間には Map クラスの他にも複数のクラスや Mapbox GL JS、three.js ライブラリ全体が含まれており、マップのカスタマイズに利用することができます。

const options = {
  container: 'mini-tokyo-3d',
  accessToken: '<Mapbox アクセストークン>'
};
const map = new mt3d.Map(options);

詳しくは、開発者ガイドをご覧ください。

プラグインフレームワークを再設計してすべてのプラグインを個別に提供(API 互換性に影響する変更)

旧バージョンでは、いくつかのプラグインは Mini Tokyo 3D ライブラリに含まれる形で提供されていましたが、バージョン 3.0 ではプラグインフレームワークの設計を一から見直すとともに、すべてのプラグインを別モジュールとして提供するようになりました。このため、プラグインを追加する際には Map クラスのコンストラクタオプションとして、明示的に PluginInterface を実装したオブジェクトのリストを指定する必要があります。

const options = {
  /* ... */
  plugins: [mt3dPrecipitation(), mt3dFireworks()]
};
const map = new mt3d.Map(options);

詳しくは、開発者ガイドをご覧ください。

コンストラクタオプション secrets.mapbox の代わりに accessToken を使用(API 互換性に影響する変更)

従来 MiniTokyo3D コンストラクタのオプション secrets.mapbox で指定していた Mapbox アクセストークンは、accessToken に指定して Map オブジェクトを作成します。

const options = {
  /* ... */
  accessToken: '<Mapbox アクセストークン>'
};
const map = new mt3d.Map(options);

詳しくは、開発者ガイドをご覧ください。

Map クラスのメソッドおよび公開クラス・インターフェースの追加

バージョン 3.0.0 では、Map(従来の MiniTokyo3D)クラスに次のメソッドが追加されました。

メソッド 説明
addLayer レイヤーを追加
getMapboxMap Mapbox の Map オブジェクトを取得
getModelPosition 緯度経度をWeb メルカトル座標に変換
getModelScale メートル単位をWeb メルカトル座標に変換
hasDarkBackground 暗い背景色かどうかを判定
removeLayer レイヤーを削除
setLayerVisibility レイヤーの可視性を設定

また、次の公開クラスが追加されました。

クラス 説明
Marker 地図上に表示するマーカー
Panel 情報を表示するためのパネル
Popup 地図上に表示するポップアップ

さらに、カスタマイズに利用可能なインターフェースが追加されました。

インターフェース 説明
PluginInterface プラグインを作成するためのインターフェース
ThreeLayerInterface three.js シーンを構築するためのレイヤーインターフェース

詳細は API リファレンスをご覧ください。

Mini Tokyo 3D バージョン 2.8.0 リリース

Mini Tokyo 3D バージョン 2.8.0 がリリースされました (GitHub)。2.7.0 からの追加・修正機能を見ていきましょう。

地平線・空が見える傾きのサポート

Mini Tokyo 3D で使っているマップライブラリを Mapbox v2 にバージョンアップして、ピッチ(傾き)最大85°に対応しました。地平線から上の空が見えるようになり、現実の空の色と太陽の動きをリアルタイムで再現した様子を見ることができます。映像はちょうど日の出の朝焼けの中を御茶ノ水に向かう青梅特快。ぜひお試しください。

f:id:nagixx:20210323183947j:plain

旅客機の追跡・表示の改善

旅客機の追跡を改善して、機体に対するズーム比率を維持したまま飛行高度に追従していくことが可能になりました。また、機体が必要以上に伸びて表示される場合がある不具合も修正しています。

動画は夕刻に成田空港A滑走路から離陸するシカゴ行き全日空12便です。徐々に高度を上げ利根川を超えていく様子をご覧ください。

エコモード追加

モバイル端末向けにエコモードを追加しました。画面右のバッテリーアイコンをクリック/タップしてエコモードをオンにすると、毎秒1フレームの描画レートになり、これによってバッテリーの消費と加熱を抑えます。

電池の減りを気にしてスマホでの利用を躊躇していた方も、安心してお使いいただけます。

初期ローディングの改善

エコモードの搭載と合わせて、アプリ起動時に描画レートを抑えることでデータのロードを優先させ、マップを早く表示する最適化も合わせて追加しました。

3/13ダイヤ改正対応

JR、東京メトロ都営地下鉄東武、西武、京王、小田急、東急、横浜高速鉄道埼玉高速鉄道東葉高速鉄道東京モノレールの3/13ダイヤ改正に対応。このダイヤ改正は、終電繰り上げが主な変更点です。小田急ロマンスカーの相模大野での分割・併合がうまく表示されていなかった問題も合わせて修正しました。

列車種別ラベルの表示

列車にマウスを重ねたり、列車追跡時に表示される列車種別が、枠で囲まれたラベルの形式になり見やすくなりました。

f:id:nagixx:20210323181259p:plain

国内線コードシェア便の重複の排除

東京公共交通オープンデータチャレンジの日本空港ビルディングが配信する羽田発着国内線のデータでは、コードシェア便だとしても別々のフライトとして存在するため、旅客機が重複して表示されていましたが、これを調整するコードを追加。150便ほど重複が排除されました。

エコモードの取得・設定 API およびモード変更イベントの追加

バージョン 2.8.0 で追加になったエコモードの取得・設定を行う次のメソッドが追加されました。

メソッド 説明
getEcoMode 現在のエコモードを取得
setEcoMode エコモードを設定

また、各表示モードの変更時や、列車・航空機の選択・選択解除時に発生する次のイベントが追加されました。

イベント 説明
clockmode クロックモードが変更
deselection 列車または航空機の追跡が解除
ecomode エコモードが変更
selection 列車または航空機の追跡が開始
trackingmode 追跡モードが変更
viewmode ビューモードが変更

詳細は Mini Tokyo 3D 開発者ガイドをご覧ください。

Mini Tokyo 3D バージョン 2.7.0 リリース

Mini Tokyo 3D バージョン 2.7.0 がリリースされました (GitHub)。2.6.0 からの追加・修正機能を見ていきましょう。

ライブカメラ映像の配信

Mini Tokyo 3D にライブカメラ映像の配信機能が登場しました。地図上のライブカメラボタンをクリックすると、カメラと同じ視点でリアルタイムに行き来する列車を眺めることができます。現時点で、赤羽、新宿、汐留、さいたま新都心など、東京近郊の16箇所に設置しています。

映像は YouTube で配信されているライブカメラ映像を埋め込んで使用しています。場所によっては不定期に YouTube の URL が変わるため、随時 URL をチェックした上でライブ配信中の場所のみを地図上に表示するようにしています。

ちなみにライブカメラの映像は大体20〜30秒くらい遅れるので、3Dマップ上の列車の方が早く現れがちになっています。

f:id:nagixx:20210130000806j:plain

パネルアニメーションの追加

列車・旅客機・駅の詳細情報やライブカメラ映像、経路検索のパネル表示の際のアニメーションを追加しました。画面下部に表示されるパネルが滑らかに開閉します。

経路検索結果のスワイプジェスチャー対応

経路検索の結果として複数の経路が返ってきたときに、水平方向のスワイプジャスチャーで経路を切り替えられるようにしました。特にタッチスクリーンデバイスで直感的な操作が可能になっています。

経路検索時に列車・航空機・追加レイヤーを非表示に

経路検索を行う際に列車・航空機・追加レイヤーを表示しないように変更しました。これによって、地図上のクリックによる駅の選択がしやすくなるとともに、画面描画処理が軽くなって遷移アニメーションがスムーズになっています。

緊急事態宣言に伴う終電時刻繰り上げダイヤに対応

1/8に発令された新型コロナウイルス感染症緊急事態宣言に伴う、首都圏の各路線の終電時刻繰り上げダイヤに対応しました(JR 東日本各線、りんかい線を除く)。

また、東武鉄道は昨年6月のリバティりょうもう増発、11月のアーバンパークライナー増発が反映されていなかったので合わせて運行ダイヤを修正しました。

駅出口情報の拡充

横浜市営地下鉄の各駅、および東急東横線みなとみらい線、JR 相鉄直通線、京急空港線東京モノレールの地下駅の出口情報を追加しました。

東京都交通局列車番号表示対応

都営地下鉄日暮里・舎人ライナー列車番号を、「ODPTxxxx」形式から本来の番号に変更しました。

f:id:nagixx:20210130000036j:plain

時間経過とともに色合いが変わる地図の作成

この記事は Mapbox Advent Calendar 2020 の23日目の記事です。

Mapbox GL JS では地図がベクトルタイルとして配信されるがゆえに、クライアント側で自由に描画をカスタマイズできるという利点があります。例えば、マップをモノクロ白地図風にしたり、ダークな背景に特定の道路だけ明るくして目立たせる、みたいなことが簡単にできます。

東京の公共交通のリアルタイム3Dマップ Mini Tokyo 3D では、これを活用して昼間なら明るい街、夜なら暗い街、そして夕方には夕焼け風、といった具合に時間の経過とともに色合いが変わる様子を表現しています。本記事では、これをどのように実現しているかを紹介します。

f:id:nagixx:20201223182309j:plain

まずはマップのスタイルから、色調整の対象となるレイヤーとその Paint プロパティを選別し、初期設定値をオブジェクトの配列に保存しておきます。これは後で、色を調整するための基準カラーとして使用します。

// 色調整の対象となる Paint プロパティキー
const paintPropertyKeys = {
    'background': ['background-color'],
    'line': ['line-color'],
    'fill': ['fill-color', 'fill-outline-color'],
    'fill-extrusion': ['fill-extrusion-color']
};

// 色調整の対象となるレイヤータイプ
const layerTypes = Object.keys(paintPropertyKeys);

// 初期カラー情報を格納する配列
const styleColors = [];

map.getStyle().layers.filter(
    layer => layerTypes.includes(layer.type)
).forEach(({id, type}) => {
    for (const key of paintPropertyKeys[type]) {
        let prop = map.getPaintProperty(id, key);

        if (typeof prop === 'string') {
            const [r, g, b, a] = parseCSSColor(prop);
            styleColors.push({id, key, r, g, b, a});
        }
    }
});

paintPropertyKeys には、レイヤータイプをキーとして、値には各レイヤーの対象となる Paint プロパティキーの配列を格納しており、すぐ下のループの中で色調整の対象となるレイヤーとプロパティの選択に利用しています。なお、Paint プロパティのカラー値には CSS カラーの文字列が入っていますので、それをパースするために css-color-parser-js を使っています。

取得したカラー情報は、レイヤー ID、プロパティキーとともに styleColors に入ります。この部分は初回に一回だけ実行していれば大丈夫です。

次に、「いつが昼でいつが夜か」という基準が必要ですが、これにはその場所の日の出・日の入時刻を知る必要があります。日の出・日の入時間は季節や緯度・経度によって変わるので、実際に求めるのは結構複雑です。そこで、ここでは SunCalc という JavaScript ライブラリを使っています。

// 日照に関する時刻を格納するオブジェクト
const times = SunCalc.getTimes(new Date(), 35.6814, 139.7670);

// 日の出時刻を表す UNIX epoch
const sunriseTime = times.sunrise.getTime();

// 日の入時刻を表す UNIX epoch
const sunsetTime = times.sunset.getTime();

上記のコードの通り、SunCalc.getTimes() の引数に現在時刻を表す Date オブジェクト、緯度、経度(例では東京)を渡すと、日照に関する時刻を格納するオブジェクトが得られます。その中の sunrise および sunset プロパティが日の出・日の入時刻を表す Date オブジェクトで、sunriseTime および sunsetTime には UNIX epoch (1970年1月1日からの経過ミリ秒) が入ります。

そして、「夜」「日の出」「昼」「日の入」における基準の色合いを決めておきます。下の表は、それぞれの状態における RGB 要素に乗じる係数と、この係数を白に乗じた場合の色見本を示しています。

状態 R G B 色見本
0.4 0.4 0.5  
日の出 0.8 0.9 1.0  
1.0 1.0 1.0  
日の入 1.0 0.9 0.8  

さらに、日の出前後の1時間ずつ、日の入前後の1時間ずつを色合いの推移の時間として、夜→日の出→昼、昼→日の入→夜の推移を滑らかにすることを考えます。

// 現在時刻を表す UNIX epoch
const now = Date.now();

// 時間推移の係数(0〜1)
let t;

// カラー係数
let cr, cg, cb;

if (now >= sunriseTime - 3600000 && now < sunriseTime) {
    // 夜〜日の出
    t = (now - sunriseTime) / 3600000 + 1;
    cr = .4 * (1 - t) + .8 * t;
    cg = .4 * (1 - t) + .9 * t;
    cb = .5 * (1 - t) + 1 * t;
} else if (now >= sunriseTime && now < sunriseTime + 3600000) {
    // 日の出〜昼
    t = (now - sunrise) / 3600000;
    cr = .8 * (1 - t) + 1 * t;
    cg = .9 * (1 - t) + 1 * t;
    cb = 1;
} else if (now >= sunriseTime + 3600000 && now < sunsetTime - 3600000) {
    // 昼
    cr = cg = cb = 1;
} else if (now >= sunsetTime - 3600000 && now < sunsetTime) {
    // 昼〜日の入
    t = (now - sunsetTime) / 3600000 + 1;
    cr = 1;
    cg = 1 * (1 - t) + .9 * t;
    cb = 1 * (1 - t) + .8 * t;
} else if (now >= sunsetTime && now < sunsetTime + 3600000) {
    // 日の入〜夜
    t = (now - sunsetTime) / 3600000;
    cr = 1 * (1 - t) + .4 * t;
    cg = .9 * (1 - t) + .4 * t;
    cb = .8 * (1 - t) + .5 * t;
} else {
    // 夜
    cr = cg = .4;
    cb = .5;
}

上のコードでは、先ほど求めた日の出・日の入時刻と現在時刻を比較して、状態により条件分岐しています。夜または昼であればカラー係数は固定ですが、日の出前後の1時間、日の入前後の1時間の期間は t を 0〜1 の間で変化する係数として、カラー係数に乗じることで滑らかにカラー係数が変化するようにしています。

for (const {id, key, r, g, b, a} of styleColors) {
    const prop = `rgba(${[r * cr, g * cg, b * cb, a].join(',')})`;
    map.setPaintProperty(id, key, prop);
});

最後に、冒頭で保存した各レイヤーの各プロパティの基準カラー情報からレイヤー ID、プロパティキー、カラー要素を取得し、RGB 要素にカラー係数を乗じて Paint プロパティに設定しています。

以上の処理を例えば1分毎に呼び出すことで、時間に応じて色合いが変わる地図が実現できます。

追記

・・・と、ここまで書いて気づいたのですが、Paint プロパティのカラー値には CSS カラーを表す文字列だけではなく、動的にスタイルを変えるための Expressions 用の配列やオブジェクトが入っている場合もあるため、実際にはもっと複雑なことをしていたのでした。

ご興味ある方は、初期カラー取得コードカラー更新コードあたりを見てください。

Mapbox GL JS のポップアップをアニメーション化

この記事は Mapbox Advent Calendar 2020 の13日目の記事です。

Mapbox のポップアップ(吹き出しで情報が表示されるやつ)って、実にシンプル、言い方を変えるとあまりに素っ気ないんです。こんな感じ。

f:id:nagixx:20201213020802j:plain

一応独自のクラスを指定したり、2日目の記事のように CSS をいじったりすると見た目を変えることはできるのですが、なんかこう、面白味がないんですよね。ポップアップなんだから、もう少し出てくる時にポップアップ感が欲しい。元気のあるやつ。

そこで Mapbox の Popup クラスを拡張して、アニメーションをつけた AnimatedPopup クラスを作ってみました。実際に動いているのを見てもらうのが分かりやすいので、サンプルをお見せします。どん!真ん中のマーカーをクリックすると、ポップアップが出たり消えたりします。

 

どうですか?生きのいいポップアップになりましたよね?

設置方法は非常に簡単です。まず、HTML ヘッダに次のタグを追加します。これは Mapbox GL 本体の後に読み込むようにしてくださいね。

<script src="https://cdn.jsdelivr.net/npm/mapbox-gl-animated-popup@latest"></script>

そして従来 Popup を new していたところを、

var popup = new mapboxgl.Popup();

AnimatedPopup で置き換える。これだけ。コンストラクタオプションは Popup と同じものを指定できます。

var popup = new AnimatedPopup();

ところで、「デフォルトのアニメーション、勢い良過ぎ!ポップアップアニメーションの動きや速さを変えられないの?」という人もいるかと思います。そのような方のために、アニメーションのパラメータは次のように指定できるようになっています。

var popup = new AnimatedPopup({
    openingAnimation: {
        duration: 1000,
        easing: 'easeOutElastic'
    },
    closingAnimation: {
        duration: 300,
        easing: 'easeInBack'
    }
});

上記はデフォルトの設定ですが、duration でアニメーションの持続時間を、easing でアニメーションのイージング関数を、オープン時とクローズ時のそれぞれで指定することができます。パラメータの選択は、次のページで動きを確認しながら確認することができますので、ぜひお使いください。

Mapbox GL JS Animated Popup

f:id:nagixx:20201213033020j:plain f:id:nagixx:20201213033055j:plain

それから GitHub のリンクも載せておきますので、実装に興味がある方はこちらもどうぞ。

最後に、このポップアップのアニメーション化は、元々 東京の公共交通のリアルタイム3Dマップ Mini Tokyo 3D のために作ったというのもあり、ぜひこちらのほうもお楽しみください。