Covid-19 tracker với Goong Maps SDK, ReactJS

https://corona.goong.io

Bài viết hôm nay sẽ giúp các bạn tạo 1 live tracker cho những vùng dịch được cảnh báo (dữ liệu từ Bộ Y Tế) với Goong Maps ReactJS.

Bước 1: Download project

https://github.com/goong-io/goong-covid19

Trước khi bắt đầu, các bạn cần tạo 1 key/access token cho Goong Tiles tại https://account.goong.io/keys (xin vui lòng tạo tài khoản nếu bạn chưa có)

tạo file .env trong thư mục goong-covid19 với nội dung như sau:

REACT_APP_GOONG_MAP_TILES_KEY='YOUR_KEY'

sau đó chạy

npm install

Bước 2: Tạp Mapview với Goong Maps React

import MapGL {Marker, NavigationControl} from '@goongmaps/goong-map-react';

 <MapGL
                {...viewport}
                width="100vw"
                height="100vh"
                minZoom={1}
                goongApiAccessToken={process.env.REACT_APP_GOONG_MAP_TILES_KEY}
                mapStyle="https://tiles.goong.io/assets/goong_map_web.json"
                onViewportChange={this._onViewportChange}
            >
                <div style={{ position: 'absolute', right: 10, top: 30 }}>
                    <NavigationControl />
                </div>                  
                {this.props.points.length > 0 ? <Markers data={this.props.points} /> : null}
            </MapGL>

Xem Map.js

Chạy npm start

Done!!

Hướng dẫn viết 1 app Android cơ bản với Goong SDK

Trong bài tiếp theo này, các bạn sẽ được hướng dẫn cách dùng Goong SDK để build một ứng dụng dùng map cơ bản cho Android. Đến cuối tutorial, các bạn đã có thể hoàn thành một app với các chức năng map view, tìm kiếm với đề xuất kết quả và ghim pin trên bản đồ.

Full source code available at https://github.com/goong-io/Goong-Android-Example
*Xin lưu ý là chỉ các thiết bị Android phiên bản 4.0 trở lên được hỗ trợ

Phần 1: MapView


Bước 1:
Tạo 1 Project trong Android Studio

Thêm đoạn code sau vào file build.gradlecho Project (không phải cho module):

allprojects {
	repositories {
		...
    maven {
      url  "https://dl.bintray.com/goong-io/GoongMapSDK"
    }
    // or jcenter()
	}
}

Add thêm thư viện vào file:

dependencies {
  implementation('io.goong.goongsdk:goong-android-sdk:2.1.0'){
    transitive=true
  }
}

Bước 2:
Tạo keys (Để sử dụng được SDK và API, các bạn cần keys/token. Hãy truy cập vào account.goong.io để tạo tài khoản, rồi tạo keys tại https://account.goong.io/keys. Xin lưu ý là bài hướng dẫn này cần key cho Map Tiles.)

Bước 3:
Tạo MapView đơn giản

Điền key/token đã được tạo tại {YOUR_GOONG_ACCESS_TOKEN}:

public class MyApplication extends Application {

  @Override
  public void onCreate() {
    super.onCreate();

    // Goong Access token
    Goong.getInstance(getApplicationContext(), 
       {YOUR_GOONG_ACCESS_TOKEN});
  }
}

Đăng ký custom Class Application trong AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <application
   android:name=".MyApplication"
   ...>
   ...
   <service android:name="io.goong.goongsdk.telemetry.TelemetryService" />
 </application>

Thêm fragment vào Activity_maps.xml. Fragment này xác định SupportMapFragment hoạt động như một container cho bản đồ và để cung cấp quyền truy cập vào đối tượng GoongMap.

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/map"
  android:name="io.goong.goongsdk.maps.SupportMapFragment"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.example.mapwithmarker.MapsMarkerActivity" />

Tại method onCreate()trong map activity, set content view bằng file layout:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Retrieve the content view that renders the map.
    setContentView(R.layout.activity_maps);
    // Get the SupportMapFragment and request notification
    // when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

Implement interface OnMapReadyCallBack, override method onMapReady(). Gắn marker lên Map :

public class MapsMarkerActivity extends AppCompatActivity
        implements OnMapReadyCallback {
    // Include the OnCreate() method here too, as described above.
    @Override
    public void onMapReady(GoongMap goongMap) {
        // Add a marker in Hanoi, Vietnam,
        // and move the map's camera to the same location.
        LatLng hanoi = new LatLng(21.0217827, 105.7942671);
        goongMap.addMarker(new MarkerOptions().position(hanoi)
                .title("Marker in Hanoi"));
        goongMap.moveCamera(CameraUpdateFactory.newLatLng(hanoi));
    }
}

Phần 2: Goong Geocoder

Goong Geocoder là thư viện front-end cho Goong Autocomplete. Sau khi tích hợp nó vào thì người dùng app của bạn có thể dễ dàng tìm kiếm địa điểm trên thanh SearchBox, với những đề xuất kết quả được update liên tục khi gõ từ khóa.

Source code: https://github.com/goong-io/Goong-Geocoder-Android

Để tích hợp Goong Geocoder cho Android:

Thêm dòng này vào file gradle và build lại:

implementation 'io.goong.goongsdk.geocoder:goong-android-geocoder:1.0'

Tạo API Key để gọi (như trên nhưng thay vì chọn Maptile Key, chọn API key)

Có 2 cách để sử dụng Geocoder có sẵn: dùng Activity hoặc Fragment

Start Activity for result:
Intent intent = new PlaceAutocomplete.IntentBuilder()
    .apiKey("Your Api Key")
    .placeOptions(new PlaceOptions.Builder()
                    .limit(20)
                    .location(21.0278, 105.8342) // your lat-long to improve search results
                    .build()
    )
    .build(this);
  startActivityForResult(intent, 100);

Lấy kết quả trả về qua onActivityResult:

@Override
  protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      if (requestCode == 100 && data != null && resultCode == Activity.RESULT_OK) {
          PlaceDetails details = PlaceAutocomplete.getPlaceDetail(data);
          Log.e("Test", details.toString());
          Toast.makeText(this, details.name + "", Toast.LENGTH_SHORT).show();
      }
  }
Add Fragment
AutocompleteFragment autocompleteFragment = AutocompleteFragment.newInstance("Your API Key",
          new PlaceOptions.Builder().build());
  autocompleteFragment.setOnPlaceSelectedListener(details -> {
        Log.e("Test", details.toString());
        Toast.makeText(this, details.name + "", Toast.LENGTH_SHORT).show();
  });
  // add/replace your fragment into your view
Place Options:
  • Ta có thể điều chỉnh kết quả tìm kiếm bằng `PlaceOptions`
new PlaceOptions.Builder()
      .limit(20) // limit the results returned
      .location(21.0278, 105.8342) // your lat-long location to improve search results. This is recommended
      .radius(2500) // results will be in the radius from the location you provided above
      .build()

Hướng dẫn sử dụng Goong REST API

Trong blog hôm nay, các bạn sẽ được hướng dẫn cách sử dụng các REST API của Goong, bao gồm:

  • Geocode (trả về chi tiết địa điểm với input là tọa độ)
  • Direction (trả về tuyến đường với input là tọa độ điểm đi và điểm đến)
  • Autocomplete (trả về danh sách địa điểm được đề xuất với input là từ khóa tìm kiếm)
  • PlaceDetail (trả về chi tiết địa điểm với input là ID của địa điểm đó)
  • Distance Matrix (trả về tuyến đường cho tất cả những cặp tọa độ điểm đi/đến trong input)
  • Static Map (trả về png image hiển thị bản đồ và tuyến đường giữa 2 tọa độ đi/đến trong input)

Để dùng được SDK và API, các bạn cần keys/token. Hãy truy cập vào account.goong.io để tạo tài khoản, rồi tạo keys tại https://account.goong.io/keys. Xin lưu ý là bạn cần key cho API cho các dịch vụ REST API trên.

Cách sử dụng Geocode (lưu ý điền API key đã tạo ở bước trên tại <add your API key here>):

https://rsapi.goong.io/Geocode?latlng=20.9819927215576,105.864227294922&api_key=<add your API key here>

Expected Response:

{
   "plus_code":{

   },
   "results":[
      {
         "address_components":[
            {
               "long_name":"477A Tam Trinh",
               "short_name":"477A Tam Trinh"
            },
            {
               "long_name":"Tam Trinh",
               "short_name":"Tam Trinh"
            },
            {
               "long_name":"Phường Hoàng Văn Thụ",
               "short_name":"Phường Hoàng Văn Thụ"
            },
            {
               "long_name":"Quận Hoàng Mai",
               "short_name":"Quận Hoàng Mai"
            },
            {
               "long_name":"Thành phố Hà Nội",
               "short_name":"Thành phố Hà Nội"
            }
         ],
         "name":"477A Tam Trinh",
         "formatted_address":"Hoàng Văn Thụ, Hoàng Mai, Hà Nội",
         "geometry":{
            "location":{
               "lat":20.9819927215576,
               "lng":105.864227294922
            }
         },
         "place_id":"XJe60zNLPn2m9JLdqe3K5MA3bBDW7dwo",
         "plus_code":{

         },
         "types":[

         ]
      }
   ],
   "status":"OK"
}

Các bạn có thể thêm tham số limit=x để API trả về 1 list với x kết quả, như sau:

https://rsapi.goong.io/Geocode?latlng=20.9819927215576,105.864227294922&api_key=<add your API key here>&limit=2

Expected Results:

{
   "plus_code":{

   },
   "results":[
      {
         "address_components":[
            {
               "long_name":"477A Tam Trinh",
               "short_name":"477A Tam Trinh"
            },
            {
               "long_name":"Tam Trinh",
               "short_name":"Tam Trinh"
            },
            {
               "long_name":"Phường Hoàng Văn Thụ",
               "short_name":"Phường Hoàng Văn Thụ"
            },
            {
               "long_name":"Quận Hoàng Mai",
               "short_name":"Quận Hoàng Mai"
            },
            {
               "long_name":"Thành phố Hà Nội",
               "short_name":"Thành phố Hà Nội"
            }
         ],
         "name":"477A Tam Trinh",
         "formatted_address":"Hoàng Văn Thụ, Hoàng Mai, Hà Nội",
         "geometry":{
            "location":{
               "lat":20.9819927215576,
               "lng":105.864227294922
            }
         },
         "place_id":"XJe60zNLPn2m9JLdqe3K5MA3bBDW7dwo",
         "plus_code":{

         },
         "types":[

         ]
      },
      {
         "address_components":[
            {
               "long_name":"477 Tam Trinh",
               "short_name":"477 Tam Trinh"
            },
            {
               "long_name":"Tam Trinh",
               "short_name":"Tam Trinh"
            },
            {
               "long_name":"Phường Hoàng Văn Thụ",
               "short_name":"Phường Hoàng Văn Thụ"
            },
            {
               "long_name":"Quận Hoàng Mai",
               "short_name":"Quận Hoàng Mai"
            },
            {
               "long_name":"Thành phố Hà Nội",
               "short_name":"Thành phố Hà Nội"
            }
         ],
         "name":"477 Tam Trinh",
         "formatted_address":"Hoàng Văn Thụ, Hoàng Mai, Hà Nội",
         "geometry":{
            "location":{
               "lat":20.9820232391357,
               "lng":105.864219665527
            }
         },
         "place_id":"bYa6ewBEPyrMk2ydPwq9Dz38lnmp5OV0",
         "plus_code":{

         },
         "types":[

         ]
      }
   ],
   "status":"OK"
}

Cách sử dụng Direction (lưu ý điền API key đã tạo ở bước trên tại <add your API key here>):

https://rsapi.goong.io/Direction?origin=21.027719,105.785911&destination=21.025846,105.788325&api_key=<add your API key here>

Expected Response:

{
   "geocoded_waypoints":[

   ],
   "routes":[
      {
         "bounds":{

         },
         "legs":[
            {
               "distance":{
                  "text":"351 m",
                  "value":351
               },
               "duration":{
                  "text":"32 giây",
                  "value":32
               }
            }
         ],
         "overview_polyline":{
            "points":"k~i_C_itdS`@wDZm@NQDEDEDEDGBG@G@GZe@LOhDeBt@a@"
         },
         "warnings":[

         ],
         "waypoint_order":[

         ]
      }
   ]
}

Các bạn có thể thêm các tham số alternative:(boolean) (trả thêm các tuyến đường khác) hoặc vehicle:(string)//'car'|'bike'|'taxi'(trả về tuyến đường cho các loại phương tiện giao thông khác nhau), ví dụ:

https://rsapi.goong.io/Direction?origin=21.027719,105.785911&destination=21.029862,105.802219&api_key=<add your API key here>&alternatives=true&vehicle=taxi

Expected Results:

{
   "geocoded_waypoints":[

   ],
   "routes":[
      {
         "bounds":{

         },
         "legs":[
            {
               "distance":{
                  "text":"5 km",
                  "value":4522
               },
               "duration":{
                  "text":"8 phút",
                  "value":461
               }
            }
         ],
         "overview_polyline":{
            "points":"k~i_C_itdS`@wDZm@NQDEDEDEDGBG@G@GZe@LOhDeBrH{DnCwAv@c@bAk@XOfAo@jFsCx@c@hFoCjBaAb@Ub@Uf@UMWc@}@cAsBvBqCbAwAr@qAb@}@`@sBp@gDViAXkAj@mCiCw@{@a@aAm@{@eAq@eAoBeE?M?IISSe@IOUe@KWEECEGEICM[c@PcBx@sAp@u@`@g@\\s@l@mAnA}@fAa@f@OP{AhBsA~AKJYRULYJe@Hc@BOA[Ce@Gq@Mk@O{@[kAg@gAm@_Ak@gAy@IO{@aAu@o@uG_GB}Cd@oArDwJTu@B]CWGSIYIGEGg@[Mn@Ot@UhAQn@oDxIO^U\\"
         },
         "warnings":[

         ],
         "waypoint_order":[

         ]
      },
      {
         "bounds":{

         },
         "legs":[
            {
               "distance":{
                  "text":"5 km",
                  "value":4990
               },
               "duration":{
                  "text":"8 phút",
                  "value":491
               }
            }
         ],
         "overview_polyline":{
            "points":"k~i_C_itdS`@wDZm@NQDEDEDEDGBG@G@G?I?GAIAECGCEEEEEGEGCICIAG?I?IBG@IDi@H[FK?eEo@uDg@q@KeAQkF{@yGaA}F_AyAUkDk@o@SGCMGMMa@_@eA_@[IwDu@_C_@oGKYg@dAyAv@eAh@u@~@qArDeFr@_APSTSNIJOFQBO@KAOGQEKKEKEa@q@Wa@QOIGKCaBeBqAyAOWKg@IoBDYA]C_AAe@E}ACsA@[B[D[HYDMNa@r@eAfIaL~B_DrEeGnAiBFIXa@TYDEzGrDhBdAh@`@dAx@dGjFf@f@f@d@d@^DBZGn@e@d@}@Rg@d@oArDwJTu@B]CWGSIYIGEGg@[Mn@Ot@UhAQn@oDxIO^U\\"
         },
         "warnings":[

         ],
         "waypoint_order":[

         ]
      }
   ]
}

Cách sử dụng Autocomplete (lưu ý điền API key đã tạo ở bước trên tại <add your API key here>), input:

https://rsapi.goong.io/Place/AutoComplete?input=20 Hoàng Quốc Việt&api_key=<add your API key here>

Expected Results:

{
   "predictions":[
      {
         "description":"20 Hoàng Quốc Việt, Nghĩa Đô, Cầu Giấy, Hà Nội",
         "matched_substrings":[

         ],
         "place_id":"xElXN1DBLJb7kz6vzyVkRrjW3Oz80Y5n",
         "structured_formatting":{
            "main_text":"20 Hoàng Quốc Việt",
            "secondary_text":"Nghĩa Đô, Cầu Giấy, Hà Nội"
         },
         "terms":[

         ],
         "types":[
            ""
         ],
         "has_children":false
      }
   ],
   "status":"OK"
}

API này cũng có các tham số phụ khác, như location: (string)//ví dụ:20.981971,105.864323(tọa độ tìm kiếm trung tâm), limit:(int)(limit số kết quả đề xuất), radius:(int)(bán kính tìm kiếm quanh tọa độ location bằng kilomet, mặc định là 50 km). Ví dụ:

https://rsapi.goong.io/Place/AutoComplete?input=20 Hoàng Quốc Việt&api_key=<add your API key here>&location=21.044662,105.800412&radius=5&limit=5

Expected Results:

{
   "predictions":[
      {
         "description":"20 Ngõ 234 Hoàng Quốc Việt, Phường Cổ Nhuế 1, Bắc Từ Liêm, Hà Nội",
         "matched_substrings":[

         ],
         "place_id":"4LmgDZJaO3vB9g0j3wmkE0AelbW26zqw",
         "structured_formatting":{
            "main_text":"20 Ngõ 234 Hoàng Quốc Việt",
            "secondary_text":"Phường Cổ Nhuế 1, Bắc Từ Liêm, Hà Nội"
         },
         "terms":[

         ],
         "types":[
            ""
         ],
         "has_children":false
      },
      {
         "description":"20 Hoàng Quốc Việt, Nghĩa Đô, Cầu Giấy, Hà Nội",
         "matched_substrings":[

         ],
         "place_id":"xElXN1DBLJb7kz6vzyVkRrjW3Oz80Y5n",
         "structured_formatting":{
            "main_text":"20 Hoàng Quốc Việt",
            "secondary_text":"Nghĩa Đô, Cầu Giấy, Hà Nội"
         },
         "terms":[

         ],
         "types":[
            ""
         ],
         "has_children":false
      }
   ],
   "status":"OK"
}

Cách sử dụng PlaceDetail với placeID xElXN1DBLJb7kz6vzyVkRrjW3Oz80Y5n mà chúng ta đã có được từ response Autocomplete trên (lưu ý điền API key đã tạo ở bước trên tại <add your API key here>):

https://rsapi.goong.io/Place/Detail?placeid=xElXN1DBLJb7kz6vzyVkRrjW3Oz80Y5n&api_key=<add your API key here>

Expected Results:

{
   "result":{
      "formatted_address":"Nghĩa Đô, Cầu Giấy, Hà Nội",
      "geometry":{
         "location":{
            "lat":21.0463771820068,
            "lng":105.799339294434
         }
      },
      "name":"20 Hoàng Quốc Việt"
   },
   "status":"OK"
}

Cách sử dụng DistanceMatrix với 1 điểm đi và 3 điểm đến (lưu ý điền API key đã tạo ở bước trên tại <add your API key here>):

https://rsapi.goong.io/DistanceMatrix?origins=20.981971,105.864323&destinations=21.031011,105.783206|21.022328,105.790480|21.016665,105.788774&api_key=<add your API key here>

Expected Results:

{
   "rows":[
      {
         "elements":[
            {
               "status":"OK",
               "duration":{
                  "text":"18 phút",
                  "value":1061
               },
               "distance":{
                  "text":"16 km",
                  "value":15955
               }
            },
            {
               "status":"OK",
               "duration":{
                  "text":"17 phút",
                  "value":1014
               },
               "distance":{
                  "text":"15 km",
                  "value":14620
               }
            },
            {
               "status":"OK",
               "duration":{
                  "text":"15 phút",
                  "value":928
               },
               "distance":{
                  "text":"14 km",
                  "value":13549
               }
            }
         ]
      }
   ]
}

Cũng như với Direction, các bạn có thể thêm các tham số phụ như vehicletype:(string)//'fastest'|'shortest'.

Cách sử dụng StaticMap (lưu ý điền API key đã tạo ở bước trên tại <add your API key here>):

https://rsapi.goong.io/staticmap/route?origin=10,105&destination=21,105&api_key=<add your API key here>

Expected Result:

Cảm ơn các bạn đã theo dõi đến đây, now start coding!!

Hướng dẫn sử dụng Goong SDK trên JavaScript

Trong bài viết hôm nay, các bạn sẽ được hướng dẫn cách tích hợp MapView cơ bản của Goong vào 1 trang web bằng JavaScript. Đến cuối tutorial, các bạn đã có thể hoàn thành một trang web với các chức năng map view, tìm kiếm với đề xuất kết quả và ghim pin trên bản đồ.

Để dùng được SDK và API, các bạn cần keys/token. Hãy truy cập vào account.goong.io để tạo tài khoản, rồi tạo keys tại https://account.goong.io/keys. Xin lưu ý là cần 1 key cho API và 1 key cho Map Tiles.

Bước 1 – Tạo MapView: ( https://docs.goong.io/js/guide )
Include các file JavaScript và CSS cần thiết:

<script src='https://cdn.jsdelivr.net/npm/@goongmaps/goong-js@1.0.2/dist/goong-js.js'></script>
<link href="https://cdn.jsdelivr.net/npm/@goongmaps/goong-js@1.0.2/dist/goong-js.css" rel="stylesheet" />

Tạo một HTML element có chứa MapView với đoạn code dưới, thay <your access token here> bằng key Map Tiles đã tạo ở bước trên. Các bạn có thể tùy chỉnh kích thước với 2 tham số widthheightvà thay đổi tọa độ trung tâm (long, lat), mức zoom khởi đầu tại center:zoom: :

<div id='map' ></div>
<script>
goongjs.accessToken = '<your access token here>';
var map = new goongjs.Map({
    container: 'map',
    style: 'https://tiles.goong.io/assets/goong_map_web.json'
    center: [105.7938073,21.0244247],
    zoom: 15 
});
</script>

Add thêm button để thể hiện map full màn hình với method addControl:

<div id='map' ></div>
<script>
goongjs.accessToken = '<your access token here>';
var map = new goongjs.Map({
    container: 'map',
    style: 'https://tiles.goong.io/assets/goong_map_web.json'
    center: [105.7938073,21.0244247],
    zoom: 15 
});
map.addControl(new goongjs.FullscreenControl());
</script>

Add thêm button để hiển thị tọa độ người dùng (trình duyệt sẽ yêu cầu truy cập quyền location):

<div id='map' ></div>
<script>
goongjs.accessToken = '<your access token here>';
var map = new goongjs.Map({
    container: 'map',
    style: 'https://tiles.goong.io/assets/goong_map_web.json'
    center: [105.7938073,21.0244247],
    zoom: 15 
});
map.addControl(
        new goongjs.GeolocateControl({
            positionOptions: {
                enableHighAccuracy: true
            },
            trackUserLocation: true
        })
);
</script>

Add Navigation Control cho MapView:

<div id='map' ></div>
<script>
goongjs.accessToken = '<your access token here>';
var map = new goongjs.Map({
    container: 'map',
    style: 'https://tiles.goong.io/assets/goong_map_web.json'
    center: [105.7938073,21.0244247],
    zoom: 15 
});
map.addControl(new goongjs.NavigationControl());
</script>

Dùng control element goong-geocoder để search các địa điểm qua Goong Autocomplete API.

Include file JavaScript cần thiết:

<script src='https://cdn.jsdelivr.net/npm/@goongmaps/goong-geocoder@1.0.2/dist/goong-geocoder.min.js'></script>
<link href="https://cdn.jsdelivr.net/npm/@goongmaps/goong-geocoder@1.0.2/dist/goong-geocoder.css" rel="stylesheet" type="text/css"/>

<!-- Promise polyfill script required to use Goong Geocoder in IE 11 -->
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js"></script>

Dùng control element goong-geocoder để search các địa điểm qua Goong Autocomplete API. Điền API key các bạn đã tạo tại <add your API key here>.

<div id="map"></div>
<script>
  goongjs.accessToken = "<add your Maptiles key here>";
    var map = new goongjs.Map({
        container: 'map', // container id
        style: 'https://tiles.goong.io/assets/goong_map_web.json', // stylesheet location
        center: [105, 21], // starting position [lng, lat]
        zoom: 9 // starting zoom
    });
map.addControl(
new GoongGeocoder({
accessToken: "<add your API key here>",
goongjs: goongjs
})
);
</script>

Nếu muốn tùy chỉnh kích cỡ của control goong-geocoder, các bạn có thể dùng cách sau:

<style>
.geocoder {
position: absolute;
z-index: 1;
width: 50%;
left: 50%;
margin-left: -25%;
top: 20px;
}
.goongjs-ctrl-geocoder {
min-width: 100%;
}
</style>
<div id="map"></div>
<div id="geocoder" class="geocoder"></div>
 
<script>
	goongjs.accessToken = "<add your Maptiles key here>";
    var map = new goongjs.Map({
        container: 'map', // container id
        style: 'https://tiles.goong.io/assets/goong_map_web.json', // stylesheet location
        center: [105, 21], // starting position [lng, lat]
        zoom: 9 // starting zoom
});
 
var geocoder = new GoongGeocoder({
accessToken: "<add your API key here>",
goongjs: goongjs
});
 
document.getElementById('geocoder').appendChild(geocoder.onAdd(map));
</script>

Hướng dẫn viết 1 app iOS cơ bản với Goong SDK

Trong bài hôm nay, các bạn sẽ được hướng dẫn cách dùng Goong SDK để build một ứng dụng dùng map cơ bản cho iOS. Đến cuối tutorial, các bạn đã có thể hoàn thành một app với các chức năng map view, tìm kiếm với đề xuất kết quả và ghim pin trên bản đồ.

Full source code available at https://github.com/goong-io/Goong-iOS-Example

Bước 1:

  • Tạo Project Xcode và chạy các lệnh sau:
cd YourProject/
pod init

thêm dòng sau vào Podfile:

pod 'GoongSDK'

chạy

pod update

Để dùng được SDK và API, các bạn cần keys/token. Hãy truy cập vào account.goong.io để tạo tài khoản, rồi tạo keys tại https://account.goong.io/keys. Xin lưu ý là cần 1 key cho API và 1 key cho Map Tiles.

  • Mở YourProject.xcworkspace
  • Điền key Map Tiles vào Info.plist tại YOUR_ACCESS_TOKEN như sau:

Bước 2 — Tạo MapView: (https://docs.goong.io/guide/ios)

  • Điền NSLocationWhenInUseUsageDescriptionvào Info.plist
  • Import GoongSDK

Swift: import GoongSDK

Objective C: @import GoongSDK

  • Tạo MapView trong viewDidLoad()
import UIKit
import GoongSDK

class ViewController: UIViewController, MGLMapViewDelegate {

override func viewDidLoad() {
super.viewDidLoad()
let mapView = MGLMapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.delegate = self
// View more style at MGLStyle.h
mapView.styleURL = MGLStyle.dayStyleURL
// Optionally set a starting point.
mapView.setCenter(CLLocationCoordinate2DMake(21.028511, 105.804817), zoomLevel: 12, animated: false)
mapView.myLocationEnabled = true

view.addSubview(mapView)
}
}

Chúc mừng! Sau khi build thì bạn đã có một ứng dụng hiển thị MapView đơn giản, có hỗ trợ các tương tác zoom và scroll.

Bước 3 — Tạo SearchBar với Autocomplete

  • thêm dòng sau vào Podfile:
pod 'GoongGeocoder'

sau đó chạy

pod update

Import GoongGeocoder vào ViewController

import GoongGeocoder

Tạo một Search Button:

let searchButton = UIButton(frame: CGRect(x: view.frame.size.width - 100 , y: 50, width: 80, height: 30))  
searchButton.setTitle("Search", for: .normal)
searchButton.backgroundColor = .darkGray
searchButton.setTitleColor(.white, for: .normal)
searchButton.addTarget(self, action: #selector(self.search), for: .touchUpInside)
view.addSubview(searchButton)

Cung cấp API key mà các bạn đã tạo sau accessToken:

@objc func search() {  
let vc = GoongAutocompleteViewController(accessToken: "insert API key here")
let nav = UINavigationController(rootViewController: vc)
vc.delegate = self
self.present(nav, animated: true, completion: nil)
}

Build and Run!

Bước 4 — Ghim Pin trên Map :

Thêm pin icon vào Assets.xcassets.

Download icon

Implement GoongAutocompleteDelegate để xử lý lựa chọn kết quả trong autocomplete:

class ViewController: UIViewController, MGLMapViewDelegate, GoongAutocompleteDelegate {  
.....func viewController(_ viewController: GoongAutocompleteViewController, didAutocompleteWith place: Placemark?) {
guard let place = place else {return}
let marker = MGLMarker()
marker.coordinate = place.location!.coordinate
marker.title = place.name
marker.reuseIdentifier = "markerIdentifier"
marker.icon = UIImage(named: "pin")!
marker.map = self.mapView
// Move map camera to marker coordinate
self.mapView.setCenter(marker.coordinate, animated: true)
}
}

Thêm vài dòng code cho việc xử lý lỗi:

func viewController(_ viewController: GoongAutocompleteViewController, didFailAutocompleteWithError error: Error?) {
print(error)
}

Chúc mừng các bạn đã hoàn thành bài 1 của series blog hướng dẫn sử dụng Goong SDK. Xin cảm ơn và hẹn gặp lại vào các bài hướng dẫn sắp tới 🙂

Goong
Goong Documents
Goong Account