街景服務

Google 街景服務可讓您在指定道路的涵蓋區域進行 360 度全景檢視。

這段影片說明了如何運用街景服務在地圖上呈現特定地址的實景體驗,為使用者提供其目的地或任何感興趣地點的實用背景資訊。

透過 Google Maps Android API 第 2 版提供的涵蓋範圍,與 Android 裝置上的 Google 地圖應用程式相同。如要進一步瞭解街景服務並在互動式地圖上查看支援區域,請參閱街景服務網站上的簡介

StreetViewPanorama 類別會在您的應用程式中建立街景服務全景的模型。在使用者介面中,全景會以 StreetViewPanoramaFragmentStreetViewPanoramaView 物件表示。

程式碼範例

GitHub 上的 ApiDemos 存放區有街景服務的使用說明範例。

Java 範例:

Kotlin 範例:

Maps SDK for Android 中的街景服務總覽

Maps SDK for Android 提供街景服務,以便取得及操控在 Google 街景服務中使用的圖像。圖片會以全景形式傳回。

每個街景服務全景都由一或多張圖片組成,提供單一位置完整的 360 度環景。圖片符合等距長方形投影,包含 360 度的水平視圖 (完整的環景) 與 180 度的垂直視圖 (由正上方到正下方)。所產生的 360 度全景會定義球面投影,將圖片覆蓋在球面的 2D 表面。

StreetViewPanorama 提供的檢視器會將全景算繪為球體,相機則位於其中央。您可以藉由操控 StreetViewPanoramaCamera,控制相機的縮放及方向 (傾斜和航向角度)。

開始使用

請依照入門指南設定 Maps SDK for Android 專案,然後按照下列說明新增街景服務全景。

Google Play 服務 SDK 用戶端程式庫提供了一些街景服務範例,可讓您匯進專案做為開發基礎。請參閱簡介,瞭解匯入範例的指南。

使用 API

請遵循下方操作說明,在 Android 片段中加入街景服務全景。這是將街景服務加入應用程式最簡單的方法。接著,請進一步瞭解片段、視圖及如何自訂全景。

新增街景服務全景

請按照下方步驟,加入像這樣的街景服務全景:

街景服務全景示範

摘要說明:

  1. 片段物件加進處理街景服務全景的活動,最簡單的做法是在 Activity 的版面配置檔案中加入 <fragment> 元素。
  2. 導入 OnStreetViewPanoramaReadyCallback 介面,並使用 onStreetViewPanoramaReady(StreetViewPanorama) 回呼方法取得 StreetViewPanorama 物件的控制代碼。
  3. 呼叫片段的 getStreetViewPanoramaAsync() 以註冊回呼。

以下是每個步驟的詳細說明。

新增片段

在活動的版面配置檔案中加入 <fragment> 元素,藉此定義片段物件。在這個元素中,將 class 屬性設為 com.google.android.gms.maps.StreetViewPanoramaFragment (或 SupportStreetViewPanoramaFragment)。

以下是版面配置檔案中的片段範例:

<fragment
    android:name="com.google.android.gms.maps.StreetViewPanoramaFragment"
    android:id="@+id/streetviewpanorama"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

加入街景服務程式碼

如要在應用程式中使用街景服務全景,您必須導入 OnStreetViewPanoramaReadyCallback 介面,並設定 StreetViewPanoramaFragmentStreetViewPanoramaView 物件的回呼例項。本教學課程使用的是 StreetViewPanoramaFragment,因為這是在應用程式中加入街景服務最簡單的方法。第一步是導入回呼介面:

Java

class StreetViewActivity extends AppCompatActivity implements OnStreetViewPanoramaReadyCallback {
    // ...
}
      

Kotlin

internal class StreetViewActivity : AppCompatActivity(), OnStreetViewPanoramaReadyCallback {
    // ...
        // ...
    }

    override fun onStreetViewPanoramaReady(streetViewPanorama: StreetViewPanorama) {
        val sanFrancisco = LatLng(37.754130, -122.447129)
        streetViewPanorama.setPosition(sanFrancisco)
    }

    private fun newView() {
        val sanFrancisco = LatLng(37.754130, -122.447129)
        val view = StreetViewPanoramaView(
            this,
            StreetViewPanoramaOptions().position(sanFrancisco)
        )
    }

    private fun setLocationOfThePanorama(streetViewPanorama: StreetViewPanorama) {
        val sanFrancisco = LatLng(37.754130, -122.447129)

        // Set position with LatLng only.
        streetViewPanorama.setPosition(sanFrancisco)

        // Set position with LatLng and radius.
        streetViewPanorama.setPosition(sanFrancisco, 20)

        // Set position with LatLng and source.
        streetViewPanorama.setPosition(sanFrancisco, StreetViewSource.OUTDOOR)

        // Set position with LaLng, radius and source.
        streetViewPanorama.setPosition(sanFrancisco, 20, StreetViewSource.OUTDOOR)

        streetViewPanorama.location.links.firstOrNull()?.let { link: StreetViewPanoramaLink ->
            streetViewPanorama.setPosition(link.panoId)
        }
    }

    private fun zoom(streetViewPanorama: StreetViewPanorama) {
        val zoomBy = 0.5f
        val camera = StreetViewPanoramaCamera.Builder()
            .zoom(streetViewPanorama.panoramaCamera.zoom + zoomBy)
            .tilt(streetViewPanorama.panoramaCamera.tilt)
            .bearing(streetViewPanorama.panoramaCamera.bearing)
            .build()
    }

    private fun pan(streetViewPanorama: StreetViewPanorama) {
        val panBy = 30f
        val camera = StreetViewPanoramaCamera.Builder()
            .zoom(streetViewPanorama.panoramaCamera.zoom)
            .tilt(streetViewPanorama.panoramaCamera.tilt)
            .bearing(streetViewPanorama.panoramaCamera.bearing - panBy)
            .build()
    }

    private fun tilt(streetViewPanorama: StreetViewPanorama) {
        var tilt = streetViewPanorama.panoramaCamera.tilt + 30
        tilt = if (tilt > 90) 90f else tilt
        val previous = streetViewPanorama.panoramaCamera
        val camera = StreetViewPanoramaCamera.Builder(previous)
            .tilt(tilt)
            .build()
    }

    private fun animate(streetViewPanorama: StreetViewPanorama) {
        // Keeping the zoom and tilt. Animate bearing by 60 degrees in 1000 milliseconds.
        val duration: Long = 1000
        val camera = StreetViewPanoramaCamera.Builder()
            .zoom(streetViewPanorama.panoramaCamera.zoom)
            .tilt(streetViewPanorama.panoramaCamera.tilt)
            .bearing(streetViewPanorama.panoramaCamera.bearing - 60)
            .build()
        streetViewPanorama.animateTo(camera, duration)
    }
}
      

ActivityonCreate() 方法中,將版面配置檔案設為內容檢視。舉例來說,如果版面配置檔案的名稱是 main.xml,請使用以下程式碼:

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_street_view);
    SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
        (SupportStreetViewPanoramaFragment) getSupportFragmentManager()
            .findFragmentById(R.id.street_view_panorama);
    streetViewPanoramaFragment.getStreetViewPanoramaAsync(this);
}
      

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_street_view)
    // ...
}
      

呼叫 FragmentManager.findFragmentById() 並向其傳送 <fragment> 元素的資源 ID,藉此取得片段的控制代碼。 請注意,您建立版面配置檔案時,系統會自動將資源 ID R.id.streetviewpanorama 加進 Android 專案。

接下來,請使用 getStreetViewPanoramaAsync() 設定片段的回呼。

Java

SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
    (SupportStreetViewPanoramaFragment) getSupportFragmentManager()
        .findFragmentById(R.id.street_view_panorama);
streetViewPanoramaFragment.getStreetViewPanoramaAsync(this);
      

Kotlin

val streetViewPanoramaFragment =
    supportFragmentManager
        .findFragmentById(R.id.street_view_panorama) as SupportStreetViewPanoramaFragment
streetViewPanoramaFragment.getStreetViewPanoramaAsync(this)
      

使用 onStreetViewPanoramaReady(StreetViewPanorama) 回呼方法擷取 StreetViewPanorama 的非空值例項以供使用。

Java

@Override
public void onStreetViewPanoramaReady(StreetViewPanorama streetViewPanorama) {
    LatLng sanFrancisco = new LatLng(37.754130, -122.447129);
    streetViewPanorama.setPosition(sanFrancisco);
}
      

Kotlin

override fun onStreetViewPanoramaReady(streetViewPanorama: StreetViewPanorama) {
    val sanFrancisco = LatLng(37.754130, -122.447129)
    streetViewPanorama.setPosition(sanFrancisco)
}
      

其他初始狀態設定相關說明

與地圖不同,街景服務全景的初始狀態無法透過 XML 設定,但您可以透過程式輔助方式,傳入包含指定選項的 StreetViewPanoramaOptions 物件來設定全景。

Java

LatLng sanFrancisco = new LatLng(37.754130, -122.447129);
StreetViewPanoramaView view = new StreetViewPanoramaView(this,
    new StreetViewPanoramaOptions().position(sanFrancisco));
      

Kotlin

val sanFrancisco = LatLng(37.754130, -122.447129)
val view = StreetViewPanoramaView(
    this,
    StreetViewPanoramaOptions().position(sanFrancisco)
)
      

其他 StreetViewPanoramaFragment 相關說明

StreetViewPanoramaFragmentAndroid 片段類別的子類別,可讓您將街景服務全景放置在 Android 片段中。StreetViewPanoramaFragment 物件是全景的容器,可透過該物件存取 StreetViewPanorama 物件。

StreetViewPanoramaView

StreetViewPanoramaView 是 Android View 類別的子類別,可讓您將街景服務全景放置在 Android View 中。View 代表螢幕的矩形區域,是 Android 應用程式和小工具的基礎建置區塊。與 StreetViewPanoramaFragment 類似,StreetViewPanoramaView 可當做全景的容器使用,且會透過 StreetViewPanorama 物件展示核心功能。此類別的使用者必須將所有活動生命週期方法 (例如 onCreate()onDestroy()onResume()onPause())) 轉送至 StreetViewPanoramaView 類別中的對應方法。

自訂由使用者控管的功能

根據預設,使用者查看街景服務全景時可使用下列功能:平移、縮放及移至相鄰的全景。 您可以透過 StreetViewPanorama 上的方法來啟用和停用由使用者控管的手勢。停用手勢後,仍可進行程式輔助變更。

設定全景的位置

如要設定街景服務全景的位置,請呼叫 StreetViewPanorama.setPosition() 以傳遞 LatLng。 您也可以傳遞 radiussource 做為選用參數。

如果您想要擴大或縮小街景服務尋找相符全景的區域,這個方法就十分實用。半徑 0 表示全景必須完全連結至指定的 LatLng。預設半徑為 50 公尺。如果相符區域中有多個全景,API 會傳回最相符的結果。

如果想要限制街景服務只尋找室外全景,設定來源是個很實用的方法。根據預設,街景服務全景可以是博物館、公共建築物、咖啡廳和商家的內部實景。 請注意,指定的位置可能沒有室外全景相片。

Java

LatLng sanFrancisco = new LatLng(37.754130, -122.447129);

// Set position with LatLng only.
streetViewPanorama.setPosition(sanFrancisco);

// Set position with LatLng and radius.
streetViewPanorama.setPosition(sanFrancisco, 20);

// Set position with LatLng and source.
streetViewPanorama.setPosition(sanFrancisco, StreetViewSource.OUTDOOR);

// Set position with LaLng, radius and source.
streetViewPanorama.setPosition(sanFrancisco, 20, StreetViewSource.OUTDOOR);
      

Kotlin

val sanFrancisco = LatLng(37.754130, -122.447129)

// Set position with LatLng only.
streetViewPanorama.setPosition(sanFrancisco)

// Set position with LatLng and radius.
streetViewPanorama.setPosition(sanFrancisco, 20)

// Set position with LatLng and source.
streetViewPanorama.setPosition(sanFrancisco, StreetViewSource.OUTDOOR)

// Set position with LaLng, radius and source.
streetViewPanorama.setPosition(sanFrancisco, 20, StreetViewSource.OUTDOOR)
      

您也可以將 panoId 傳遞至 StreetViewPanorama.setPosition(),根據全景 ID 設定位置。

如要擷取鄰近全景的全景 ID,請先使用 getLocation() 擷取 StreetViewPanoramaLocation。 此物件包含目前全景的 ID 和 StreetViewPanoramaLink 物件的陣列,每一項都包含與目前全景相連結的全景 ID。

Java

StreetViewPanoramaLocation location = streetViewPanorama.getLocation();
if (location != null && location.links != null) {
    streetViewPanorama.setPosition(location.links[0].panoId);
}
      

Kotlin

streetViewPanorama.location.links.firstOrNull()?.let { link: StreetViewPanoramaLink ->
    streetViewPanorama.setPosition(link.panoId)
}
      

放大和縮小

您可以設定 StreetViewPanoramaCamera.zoom,以程式輔助的方式變更縮放等級。縮放比例設為 1.0 時,系統會將圖片放大兩倍。

下列程式碼片段使用 StreetViewPanoramaCamera.Builder(),根據現有相機的傾斜和航向角度設定來建構新的相機,同時將縮放比例增加 50%。

Java

float zoomBy = 0.5f;
StreetViewPanoramaCamera camera = new StreetViewPanoramaCamera.Builder()
    .zoom(streetViewPanorama.getPanoramaCamera().zoom + zoomBy)
    .tilt(streetViewPanorama.getPanoramaCamera().tilt)
    .bearing(streetViewPanorama.getPanoramaCamera().bearing)
    .build();
      

Kotlin

val zoomBy = 0.5f
val camera = StreetViewPanoramaCamera.Builder()
    .zoom(streetViewPanorama.panoramaCamera.zoom + zoomBy)
    .tilt(streetViewPanorama.panoramaCamera.tilt)
    .bearing(streetViewPanorama.panoramaCamera.bearing)
    .build()
      

設定相機方向 (視角)

您可以在 StreetViewPanoramaCamera 設定航向和傾斜角度,藉此決定街景服務相機的方向。

航向
這是指相機指向的方向,以正北方為基準,由相機擺放位置依順時針方向測量的角度 (以度為單位)。正北為 0 度,正東為 90 度,正南為 180 度,正西為 270 度。
傾斜
Y 軸會向上或向下傾斜。範圍介於 -90 到 0 和 0 到 90 之間;-90 代表垂直向下、0 為水平置中、90 為垂直向上。這個變異值是根據相機的初始預設傾斜角度測量而得;預設傾斜角度通常是水平 (但不一定)。舉例來說,如果圖片是從山丘上拍攝,其預設傾斜角度可能就不是水平。

下列程式碼片段使用 StreetViewPanoramaCamera.Builder(),根據現有相機的縮放和傾斜設定來建構新的相機,同時將航向角調往左邊 30 度。

Java

float panBy = 30;
StreetViewPanoramaCamera camera = new StreetViewPanoramaCamera.Builder()
    .zoom(streetViewPanorama.getPanoramaCamera().zoom)
    .tilt(streetViewPanorama.getPanoramaCamera().tilt)
    .bearing(streetViewPanorama.getPanoramaCamera().bearing - panBy)
    .build();
      

Kotlin

val panBy = 30f
val camera = StreetViewPanoramaCamera.Builder()
    .zoom(streetViewPanorama.panoramaCamera.zoom)
    .tilt(streetViewPanorama.panoramaCamera.tilt)
    .bearing(streetViewPanorama.panoramaCamera.bearing - panBy)
    .build()
      

下列程式碼片段可將相機向上傾斜 30 度。

Java

float tilt = streetViewPanorama.getPanoramaCamera().tilt + 30;
tilt = (tilt > 90) ? 90 : tilt;

StreetViewPanoramaCamera previous = streetViewPanorama.getPanoramaCamera();

StreetViewPanoramaCamera camera = new StreetViewPanoramaCamera.Builder(previous)
    .tilt(tilt)
    .build();
      

Kotlin

var tilt = streetViewPanorama.panoramaCamera.tilt + 30
tilt = if (tilt > 90) 90f else tilt
val previous = streetViewPanorama.panoramaCamera
val camera = StreetViewPanoramaCamera.Builder(previous)
    .tilt(tilt)
    .build()
      

為相機動作加入動畫效果

如要為相機動作加入動畫效果,請呼叫 StreetViewPanorama.animateTo()。動畫會插入目前相機屬性和新相機屬性之間。如要在沒有動畫的情況下直接跳到相機,請將時間長度設為 0。

Java

// Keeping the zoom and tilt. Animate bearing by 60 degrees in 1000 milliseconds.
long duration = 1000;
StreetViewPanoramaCamera camera =
    new StreetViewPanoramaCamera.Builder()
        .zoom(streetViewPanorama.getPanoramaCamera().zoom)
        .tilt(streetViewPanorama.getPanoramaCamera().tilt)
        .bearing(streetViewPanorama.getPanoramaCamera().bearing - 60)
        .build();
streetViewPanorama.animateTo(camera, duration);
      

Kotlin

// Keeping the zoom and tilt. Animate bearing by 60 degrees in 1000 milliseconds.
val duration: Long = 1000
val camera = StreetViewPanoramaCamera.Builder()
    .zoom(streetViewPanorama.panoramaCamera.zoom)
    .tilt(streetViewPanorama.panoramaCamera.tilt)
    .bearing(streetViewPanorama.panoramaCamera.bearing - 60)
    .build()
streetViewPanorama.animateTo(camera, duration)
      

使用 Handler.postDelayed() 讓上述動畫每隔 2000 毫秒執行一次時,結果會如下圖所示:

街景服務全景動畫示範