iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Modern Web

使用 Kotlin 快速開發 Web 程式 -- Vaadin系列 第 27

使用 Vaadin Directory 組件 - day27

目的

地圖反查經緯度,將地圖顯示在立委服務地區旁。
https://ithelp.ithome.com.tw/upload/images/20211012/20138680YKzMtZMDsX.png
https://ithelp.ithome.com.tw/upload/images/20211012/20138680BByZxn72xA.png

本篇重點:

  • 導入Vaadin direction組件 Google Maps Addon
  • 地址查座標
  • 地圖顯示

本示例使用 Google Maps Addon 套件最基本功能 : 使用街道地圖、將地圖移到座標中心點、地圖放大、加地圖標記。從上方執行結果可看到執行結果,地圖可切換全螢幕顯示、zoom in/out、地圖顯示模式切換、街景服務,功能相當完備。

Vaadin Directory

Vaadin Directory 內有大量開源組件,筆者在本系列文首篇簡介裡提到,Vaadin Directory 內已有近2000個組件。當開發出滿意的組件時,也可自由上傳供其他人使用。
https://ithelp.ithome.com.tw/upload/images/20211012/20138680QWNHDhTz29.png

Google Maps Addon

https://ithelp.ithome.com.tw/upload/images/20211012/20138680hQFONRb0fG.png
通常 add-on 只提供 Maven dependency 如下,但本專案為 Gradle 專案,須轉換一下。

<dependency>
   <groupId>com.flowingcode.vaadin.addons</groupId>
   <artifactId>google-maps</artifactId>
   <version>1.4.0</version>
</dependency>
<repository>
   <id>vaadin-addons</id>
   <url>https://maven.vaadin.com/vaadin-addons</url>
</repository>

準備工作

導入 Gradle 專案

repository

    repositories {
        maven("https://maven.vaadin.com/vaadin-addons")
        mavenCentral()
        google()
    }

dependency

因本套件使用 Google Map,所以除了Google Maps Addon外,還要導入Google Maps Services

implementation("com.flowingcode.vaadin.addons:google-maps:1.4.0")
implementation("com.google.maps:google-maps-services:1.0.0")

啟用 Google API

使用 Google 地圖服務需要啟用帳單收費功能,請留意收費標準
地址查經緯度 : Geocoding API
https://ithelp.ithome.com.tw/upload/images/20211012/20138680WQN6KyWhzL.png
網頁顯示地圖 : Maps JavaScript API
雖然Vaadin使用kotlin開發,但別忘了,它畢竟是web application
https://ithelp.ithome.com.tw/upload/images/20211012/201386807XrEU6lk7H.png

取得 API Key

請參考官網文件
https://ithelp.ithome.com.tw/upload/images/20211012/20138680QQHAvnacf3.png

地圖顯示

地址查經緯度座標

這部份在很多地方都可查到上傳格式,在此不多加敘述,或者您可參考官網文件。本文取得座標方法在下方。

回傳內容格式

Geocoding API response json 如下,但我們需要的只有下述打 * 號的部份

{
  "addressComponents": [
    {
      "longName": "165",
      "shortName": "165",
      "types": [
        "STREET_NUMBER"
      ]
    },
    {
      "longName": "Section 4, Fengyuan Boulevard",
      "shortName": "Section 4, Fengyuan Blvd",
      "types": [
        "ROUTE"
      ]
    },
    {
      "longName": "北陽里",
      "shortName": "北陽里",
      "types": [
        "ADMINISTRATIVE_AREA_LEVEL_4",
        "POLITICAL"
      ]
    },
    {
      "longName": "Fengyuan District",
      "shortName": "Fengyuan District",
      "types": [
        "ADMINISTRATIVE_AREA_LEVEL_3",
        "POLITICAL"
      ]
    },
    {
      "longName": "Taichung City",
      "shortName": "Taichung City",
      "types": [
        "ADMINISTRATIVE_AREA_LEVEL_1",
        "POLITICAL"
      ]
    },
    {
      "longName": "Taiwan",
      "shortName": "TW",
      "types": [
        "COUNTRY",
        "POLITICAL"
      ]
    },
    {
      "longName": "420",
      "shortName": "420",
      "types": [
        "POSTAL_CODE"
      ]
    }
  ],
  "formattedAddress": "No. 165, Section 4, Fengyuan Blvd, Fengyuan District, Taichung City, Taiwan 420",
  "geometry": {
*    "location": {
*      "lat": 24.2467722,
*      "lng": 120.73373
*    },
    "locationType": "ROOFTOP",
    "viewport": {
      "northeast": {
        "lat": 24.2481211802915,
        "lng": 120.7350789802915
      },
      "southwest": {
        "lat": 24.2454232197085,
        "lng": 120.7323810197085
      }
    }
  },
  "types": [
    "STREET_ADDRESS"
  ],
  "partialMatch": false,
  "placeId": "ChIJVfZYFhgaaTQRxZpdnhApIp4",
  "plusCode": {
    "globalCode": "7QP26PWM+PF",
    "compoundCode": "6PWM+PF Fengyuan District, Taichung City, Taiwan"
  }
}

使用 Google Maps Services API 查座標,取得 location

    private fun getLatLng(addr: String): LatLng {
        val context = GeoApiContext.Builder()
            .apiKey(apiKey)
            .build()
        val result = GeocodingApi.geocode(context, addr).await()
        val gson = GsonBuilder().setPrettyPrinting().create()
        return result[0].geometry.location
    }

顯示地圖組件

此自製組件傳入參數為地址,透過geocoding api查詢經緯度座標,再顯示地圖。一般實務上不這麼使用,通常會儲存查到的座標,節省重複查詢流量。

本示例使用 Google Maps Addon 套件最基本功能 : 使用街道地圖、將地圖移到座標中心點、地圖放大、加地圖標記。

class GoogleMapComponent(addr: String) : KComposite() {
    private lateinit var gmaps: GoogleMap
    private val apiKey = "AIzaSyD.............wXyRDoA"

    private val root = ui {
        verticalLayout {
            val latLng = getLatLng(addr)
            val latlon = LatLon(latLng.lat, latLng.lng)

            gmaps = GoogleMap(apiKey, null, null).apply {
                mapType = GoogleMap.MapType.ROADMAP
                zoom = 15
                center = latlo
                addMarker("Center", center, true, "")
                setSizeFull()
            }
            add(gmaps)
        }
    }
}

fun HasComponents.googleMapComponent(addr: String, block: GoogleMapComponent.() -> Unit = {}) = init(GoogleMapComponent(addr), block)

在 ui 上顯示地圖

   horizontalLayout.add(this@verticalLayout.googleMapComponent(addr)

上一篇
Vaadin Pro Components 圖表初探 - day26
下一篇
Vaadin login with Facebook - day28
系列文
使用 Kotlin 快速開發 Web 程式 -- Vaadin30

尚未有邦友留言

立即登入留言