參加F2E前端個人組Week1的作品,作品連結:台灣景點旅遊導覽。
主要功能
- 景點旅遊整合應用
取得景點、餐飲、旅宿、活動資料 - 串接第三方API
PTX MOTC Transport API
Google Map - 搜尋功能
支援單一關鍵字不含其他操作搜尋
支援詳細搜尋(依種類,動態提供過濾方式:地點、活動日期、活動標籤)
資料頁碼邏輯(參考巴哈姆特分頁邏輯) - UX優化
增加按鍵回饋,提高使用者體驗
圖文列表模式瀏覽
本文目的
主要介紹以下功能。實作邏輯、踩到的坑及可以注意的事項
- PTX API
- Google Map
- Pagination
PTX API
公共運輸整合資訊-流通服務平台
主要流程
申請會員(取得使用金鑰) → 將取得金鑰加密後的資料做為要Query時用的header →
透過header發出Query請求 → 取得資料
1. 申請會員
六角學院API全攻略,照著做就可以申請通過了。申請成功後會寄Gmail給你APP ID以及APP Key,待會會用到。
2. 透過APP ID以及APP Key,建立header
在這之前記得要先安裝jssha,它能幫你把AppKey加密,畢竟一般像是Key這種比較機密的資料,在請求的時候不可能透過明碼來傳
npm i jssha
3. 對PTX發出請求
透過剛剛建立的Header,加在Query中就能取得Activity這支API的所有資料
4. 加入Filter條件
PTX API支援OData查詢語法,如果需要增加條件(例如:種類、地區、時段)可以參考這裡。
舉例:我需要查找的種類是"活動",地點是"台中",活動開始的時間段是"2021/10/01"~"2021/12/31",而且種類是"產業文化活動"
先根據種類以及是否有地點,決定要打的API。
/v2/Tourism/Activity
/v2/Tourism/Activity/{City}
決定好API後,加入Filter條件(日期以及種類)。
日期(格式是YYYY-MM-DD)
StartTime:2021–10–01EndTime:2021–12–31let queryStringDate = "(StartTime gt ' + this.startTime + ' and EndTime lt ' + this.endTime + ')"
種類(給中文就可以了)
let queryStringType = "(Class1 eq '產業文化活動' or Class2 eq '產業文化活動')"
把它們加起來
let queryString = queryStringDate + 'and' + queryStringType
*還有一個要注意的是
送出Query前要先將queryString進行URL編碼(encodeURI)
encodeURI(queryString);
最後就可以發出Query了
getActivitityWithFilter('Taichung',encodeURI(queryString))
Google Map
Google Map Embed API
主要流程
申請API Key → 嵌入
1. 申請API Key
到Google Developers點Get Started建立一個新的Google Map Embed專案,取得API Key,詳細參考如何申請Google Map API
2. 嵌入
Google Map有提供許多地圖模式,像是輸出兩地的路徑;放大縮小...等,我這邊選擇的是place mode(文檔)。
要完成place mode的嵌入只需要給API Url、名稱(城市)、或地址,以及定位座標(經緯度)就可以了,根據下面這一頁的資料來作範例。
API baseUrl
https://www.google.com/maps/embed/v1/place
Key
?key={你的App Key}
q
&q = "哈密街61號","台北市"
center(data就是PTX撈下來的資料,在Position中這兩個值就是經緯度)
¢er=${data.Position.PositionLat},${data.Position.PositionLon}
組起來就是
https://www.google.com/maps/embed/v1/place?key={你的App Key}&q=${addressRef},${this.data.City}¢er=${data.Position.PositionLat},${data.Position.PositionLon}`
最後把這串資料綁到HTML上的ifram就完成了
<iframe frameborder=”0" [src]=”googleMapQueryString” allowfullscreen
></iframe>
3.補充
照著上面做,但是報錯了,錯誤資訊如下:
這是Angular內建的安全機制,為了避免XSS之類的攻擊,其中一個解決這個Error的方式就是將綁到iframe的src認定為被信任的網址,透過使用Angular內建的DomSanitizer。
程式碼
import { DomSanitizer } from ‘@angular/platform-browser’;...constructor(private sanitizer: DomSanitizer,) { }...let q = this.sanitizer.bypassSecurityTrustResourceUrl(剛剛那串Url);
補充
取得本地位置
getPosition(): Promise<any>{ return new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition(resp => { resolve({lng: resp.coords.longitude, lat: resp.coords.latitude}); }, err => { reject(err); }); });}
Pagination
分頁頁碼
不太確定是不是有些Pagination有包含這個功能,但這邊是直接自己實作,先看看每個情況下的顯示頁碼
這邊的條件跟對應輸出是
- 如果在頁碼的位置在首頁或末頁,就只顯示三頁(含當頁)及起始或末頁
- 如果頁碼在中間頁,就顯示當前頁以及前後兩頁與起始及末頁
- 如果頁碼在中間頁,且前後兩頁包含起始頁,則顯示當前附近頁與起始或末頁
總結
假設總頁數 n = 30頁 ; 當前頁數為 x
HTML迴圈用1~30去跑 迴圈索引 為 i
If (Math.abs(x-i) <= 2 ) { 顯示此頁頁碼 }
If (Math.abs(x-i) == 2 ) { 將此頁頁碼設為"..." }
Else { 跳過不顯示 }