Step3: カスタムストリートビューの作成


パノラマ写真の分割

Step2で作ったパノラマ写真は縦横比が2:1にしなければなりません。私の場合は、2048x1024ピクセルを使用しています。
streetview_ratio
そしてそのパノラマ写真を正方形に分割します。Google Maps APIがタイル画像として使っている256x256ピクセルがオススメです。
slice panorama image

ストリートビュープロバイダの登録

まずストリートビューオブジェクトを作成します。またはMapオブジェクトからデフォルトのストリートビューを取得しても良いです。

// ストリートビューオブジェクトの作成
var streetViewDiv = document.getElementById('streetview_canvas');
var streetView = new google.maps.StreetViewPanorama(streetViewDiv);

// またはMapオブジェクトから取得
var streetView = map.getStreetView();

そしてストリートビュープロバイダをgoogle.maps.StreetViewPanoramaOptionsを使って登録します。
streetView.setOptions({
  panoProvider : getCustomPanorama
});

function getCustomPanorama(panoID) {
}

ストリートビューのビューが変化するとき、登録したストリートビュープロバイダの関数が呼び出されます。そのとき引数にパノラマIDが渡されます。 パノラマ IDはパノラマ写真のIDで、Google Street Viewはそれぞれに違ったIDをビューごとに持っています。 このチュートリアルでは、私は"visitor_center"とします。 そして"visitor_center"が呼び出されたとき、StreetViewPanoramaDataを返します。
function getCustomPanorama(panoID) {
  var streetViewPanoramaData = {
    links: [],
    copyright: 'Imagery (c) Masashi Katsumata',
    tiles: {
        tileSize: new google.maps.Size(256, 256), //デバッグ時には2048x1024にすると作業しやすいです
        worldSize: new google.maps.Size(2048, 1024),
        centerHeading: 0,
        getTileUrl: getCustomPanoramaTileUrl
     }
  };
  switch(panoID) {
    case "visitor_center":
      streetViewPanoramaData["location"] = {
        pano: 'visitor_center',
        description: "Visitor center",
        latLng: new google.maps.LatLng(37.556429,-122.050745)
      };
      return streetViewPanoramaData;
  }
}
上記のコードで、"centerHeading"プロパティをStreetViewPanoramaDataに指定することができます。これはパノラマ写真が中央が真北でないときに、その角度を指定するために使います。 step2で触れたように、パノラマ写真の中央を真北にすることをお勧めします。そうすればcenterHeadingプロパティは常に0でよく、あとで2点間のパノラマ写真の向きを合わせるときも簡単です。

そしてこのコードで最も重要なのが、 "getTileUrl" プロパティです。 この関数は引数に基づいて分割されたパノラマ写真のURLを返します。そしてこれがストリートビューとして表示されます。
function getCustomPanoramaTileUrl(panoID, zoom, tileX, tileY) {
  // panoIDに基づいて対応する画像のURLを返す
  return "ardenwood_tiles/" + panoID + '/'  + tileX + '-' +tileY + '_s1.jpg';
}

このコードはパノラマ写真だけを表示します。
<script type='text/javascript'>

function code3_2() {
  // ストリートビュープロバイダの設定
  var streetViewOptions = {
    zoom: 1,
    pano : "visitor_center",
    panoProvider:  getCustomPanorama
  };
  // ストリートビューオブジェクトの作成
  var streetViewDiv = document.getElementById('streetview_canvas1');
  streetViewDiv.style.fontSize = "15px";
  var streetView = new google.maps.StreetViewPanorama(streetViewDiv, streetViewOptions);
}

function getCustomPanoramaTileUrl(panoID, zoom, tileX, tileY) {
  // panoIDに対応する画像のURLを返す
  return "ardenwood_ardenwood_tiles/" + panoID + '/'  + tileX + '-' +tileY + '_s1.jpg';
}

function getCustomPanorama(panoID) {
  var streetViewPanoramaData = {
    links: [],
    copyright: 'Imagery (c) Masashi Katsumata',
    tiles: {
        tileSize: new google.maps.Size(256, 256),
        worldSize: new google.maps.Size(2048, 1024),
        centerHeading: 0,
        getTileUrl: getCustomPanoramaTileUrl
     }
  };
  switch(panoID) {
    case "visitor_center":
      streetViewPanoramaData["location"] = {
        pano: 'visitor_center',
        description: "Visitor center",
        latLng: new google.maps.LatLng(37.556429,-122.050745)
      };
      return streetViewPanoramaData;
  }
}

google.maps.event.addDomListener(window, 'load', code3_2);
    </script>

Google StreetViewとの接続

このチュートリアルでは、Ardenwoodパークの駐車場とビジターセンターをつなぎます。 Google StreetViewは各ストリートビューのポイントにパノラマIDを持っていますが、それは一定していません。 このパノラマIDは1つのブラウザセッションの中でしか有効ではないため、Googleが撮影した駐車場のパノラマIDは調べなければなりません。 (参照: pano_changed の説明をお読みください。)

StreetViewService.getPanoramaByLocation()メソッドを使うと、指定した緯度経度に一番近い場所のパノラマIDを調べることができます。

// ストリートビューサービス・オブジェクトの作成
var streetviewService = new google.maps.StreetViewService();

// 駐車場のパノラマIDを調べる.
var radius = 50;  //メートル
streetviewService.getPanoramaByLocation(initPos, radius, function(result, status) {
  if (status == google.maps.StreetViewStatus.OK) {
    initPosPanoID = result.location.pano;
    streetView.setPosition(result.location.latLng);
  }
});

そしてそのパノラマIDをStreetViewLink形式で、StreetViewPanoramaData.links プロパティに追加します。 私はこれを"links_changed"イベントの時に行なっています。このイベントを使うことで、デフォルトのストリートビューもカスタムストリートビューの場合も両方捉えることができるからです。
// "links_change" イベントを登録
google.maps.event.addListener(streetView, "links_changed", createCustomLink);

function createCustomLink() {
  var links = streetView.getLinks();
  var panoID = streetView.getPano();
  
  switch(panoID) {
    case initPosPanoID:
      // Add a link to "visitor_center"
      links.push({
        description : "Welcome to Ardenwood",
        pano : "visitor_center",
        heading : 71
      });
      break;
      
    case "visitor_center":
      links.push({
        description : "Parking",
        pano : initPosPanoID,
        heading : 248
      });
      break;
  }
}
これを繰り返していくことで、さらにポイントを増やしていくことが可能です。完了!



Code

<script type='text/javascript'>

var initPosPanoID, streetView;

function initialize() {
  //Ardenwoodパークの正面位置
  var initPos = new google.maps.LatLng(37.55631,-122.051153);  

  // ストリートビュープロバイダの設定
  var streetViewOptions = {
    zoom: 1,
    panoProvider:  getCustomPanorama,
    pov : {
      heading : 55,
      pitch : 0,
      zoom : 1
    }
  };
  
  // ストリートビューオブジェクトの作成
  var streetViewDiv = document.getElementById('streetview_canvas2');
  streetViewDiv.style.fontSize = "15px";
  streetView = new google.maps.StreetViewPanorama(streetViewDiv, streetViewOptions);

  // links_changeイベントの登録
  google.maps.event.addListener(streetView, "links_changed", createCustomLink);
  
  // StreetViewServiceオブジェクトの作成
  var streetviewService = new google.maps.StreetViewService();
  
  // 最初に表示する位置のパノラマIDを取得する
  var radius = 50;
  streetviewService.getPanoramaByLocation(initPos, radius, function(result, status) {
    if (status == google.maps.StreetViewStatus.OK) {
      initPosPanoID = result.location.pano;
      streetView.setPosition(result.location.latLng);
    }
  });
  
}

function getCustomPanoramaTileUrl(panoID, zoom, tileX, tileY) {
  // panoIDに対応する画像のURLを返す
  return "ardenwood_tiles/" + panoID + '/'  + tileX + '-' +tileY + '_s1.jpg';
}

function getCustomPanorama(panoID) {
  var streetViewPanoramaData = {
    links: [],
    copyright: 'Imagery (c) Masashi Katsumata',
    tiles: {
        tileSize: new google.maps.Size(256, 256),
        worldSize: new google.maps.Size(2048, 1024),
        centerHeading: 0,
        getTileUrl: getCustomPanoramaTileUrl
     }
  };
  switch(panoID) {
    case "visitor_center":
      streetViewPanoramaData["location"] = {
        pano: 'visitor_center',
        description: "Visitor center",
        latLng: new google.maps.LatLng(37.556429,-122.050745)
      };
      return streetViewPanoramaData;
  }
}

function createCustomLink() {
  /*
   * リンクの追加
   */
  var links = streetView.getLinks();
  var panoID = streetView.getPano();
  
  switch(panoID) {
    case initPosPanoID:
      links.push({
        description : "Welcome to Ardenwood",
        pano : "visitor_center",
        heading : 71
      });
      break;
      
    case "visitor_center":
      links.push({
        description : "Parking",
        pano : initPosPanoID,
        heading : 248
      });
      break;
      
  }
  
}
google.maps.event.addDomListener(window, 'load', initialize);
    </script>

Step2: パノラマ写真の作成 |  Index: カスタムストリートビューの作成方法

サイト内検索
Google Maps APIプログラミング入門 第2版
Google Maps APIプログラミング入門 第2版
全520ページ。Google Maps API version3を中心に公式ドキュメントより詳しく解説しています。
詳しくはこちら
Google Maps APIプログラミングガイド

Google Maps API Expert 4人が共著で執筆。中級者向けに実用に役立つサンプルを中心に紹介! スマートフォン時代に合わせたGoogle Maps APIの使い方も掲載。
詳しくはこちら