近頃はお仕事でGoogleMapAPIを触ってます。
いやー、これだけ高機能な地図アプリケーションを、たったの数十行のコードで実現できるなんて素晴らしいですね。Google恐るべし。
ストリートビューを開いた時の向きを自動的に最適化する
さて、デフォルトではストリートビューを開いた時の方角は固定です。 デフォルト値は以下の通り変更できるのですが、だからどうしたという感じです。
const map = new google.maps.Map(document.getElementById("map")); // デフォルトで右上(北東)を向くようにする map.getStreetView().setPov({ heading: 45, // 真北を0として時計回り180度まで。反時計回りはマイナスの値 pitch: 0 // 仰角。真下は-90、真上は90 });
今回は地図上の最寄りのマーカへ自動的に向いて欲しいという要求があるので、以下の通りにしました。
import _ from 'lodash'; import google from 'google-maps-api'; // 地図上に配置したマーカー群の位置 /** @type {!Array<google.maps.LatLng>} */ const markerLocations = [ new google.maps.LatLng(...), new google.maps.LatLng(...), ... ]; /** * 第二引数の要素のうち、第一引数に最も近いものを返す。 * * @param {!google.maps.LatLng} currentPos * @param {!Array<google.maps.LatLng>} positions * @return {!google.maps.LatLng} */ const findClosestPosition = (currentPos, positions) => positions.map(position => ({ position, distance: google.maps.geometry.spherical.computeDistanceBetween( currentPos, position ) })).sort((x, y) => x.distance - y.distance)[0].position; const sview = map.getStreetView(); // 一度ストリートビューをONにしないとposition_changedイベントが発火しない模様 sview.setVisible(true); sview.setVisible(false); // ペグマン(ストリートビューの位置を指定するためにドラッグするアレ)を移動したら向きを変える google.maps.event.addListener(sview, 'position_changed', () => { // ペグマンの位置を特定 /** @type {!google.maps.LatLng} */ const pos = sview.getPosition(); sview.setPov({ heading: google.maps.geometry.spherical.computeHeadingFrom( pos, findClosestPosition(pos)) pitch: -10 }); });
ここで重要なのは次の2点です。
要点1: 位置情報計算用のユーティリティ関数を使え
この2つの関数を用いることで、面倒な計算が一発でできます。
google.maps.geometry.spherical.computeHeading
- A→Bの向きを計算する
google.maps.geometry.spherical.computeDistanceBetween
- A→Bの距離を計算する
同等品を自前で書くのはメンドクサイので、大いに助かりました。
ところで、この関数はオプションライブラリ扱いです。
URLにlibraries=geometry
を付ける必要があるのでご注意を。詳しくはこちら。
http://developers.google.com/maps/documentation/javascript/libraries
要点2: StreetViewPanoramaのposition_changedイベントを使え
mousemoveイベントはペグマンのドラッグ時には発生しないので使えません。
ではどうするかというと、StreetViewPanoramaのposition_changedイベントを使います。
イベントオブジェクトにはLatLngオブジェクトが設定されていないので、
StreetViewPanorama.getPosition()
でペグマンの位置を取得する必要があります。
『ストリートビューを開く前に1度行えば充分ならば、visible_changedイベントでいいんじゃね?』という話もありますが、ペグマンの向きも動的に変えたいのでposition_changedの方が望ましいと思います。
ただし、どうやら一度ストリートビューを開かないとposition_changedが発火しないみたいです。 だからサンプルコードにある通り、ストリートビューを強制的にON→OFFしています。