第十章:營區任意門 - 實作地點搜尋與平滑飛越 (FlyTo)
當你的地圖上只有 10 個營區時,使用者可以很悠哉地滑動地圖尋找。 但當你的資料庫裡有高達 1,000 個全台灣的露營地時,使用者不可能像無頭蒼蠅一樣,慢慢在地圖上放大縮小去尋找「武陵農場」到底隱藏在哪座山裡。
他們需要一個功能強大的「隨意門」:一個在網頁頂端的搜尋框。當使用者打字輸入時,下方會自動跳出建議選單 (Autocomplete),一旦點擊,地圖就會像無人機一樣,瞬間平滑飛越到該地點的上空並放大!
這是一個極具商業價值的進階功能,能讓你的系統體驗瞬間達到 Google Maps 的水準。
🎯 本章目標
- 實作一個帶有 Autocomplete (自動完成) 下拉選單的智慧搜尋框。
- 結合 React 狀態管理與 Leaflet 的
map.flyTo動畫功能。 - 體驗將多個小組件 (搜尋框 + 地圖引擎) 組合連動的系統架構快感。
🔍 第一步:建立智慧搜尋框 (SearchBar)
我們不需要自己從零開始刻下拉選單的過濾邏輯與 CSS 排版,這種繁瑣的 UI 元件是交給 AI 表現的最好機會。
🔥【Vibe Prompt 實戰咒語】
我需要在 React 中做一個營區搜尋框元件 (命名為 SearchBar.tsx)。1. 介面設計:請用 Tailwind CSS 設計得像 Google Maps 的搜尋框一樣有質感。包含陰影 (shadow-lg)、圓角、以及左側有一個放大鏡 Icon (lucide-react)。2. 資料處理:傳入一個陣列 campsData (包含 id, name, lat, lng)。3. 自動完成邏輯:使用者在 input 打字時,下方要出現一個絕對定位 (absolute z-50) 的下拉選單。請用 filter 過濾出名稱包含使用者輸入字串的營區。4. 觸發事件:當使用者點擊下拉選單中的某個營區時,請觸發一個 callback prop: onCampSelect(lat, lng),並且清空輸入框與關閉下拉選單。
將這段咒語送給 AI,它會幫你把 onChange 即時過濾資料、下拉選單的 ul / li 渲染,全部寫得漂漂亮亮,而且樣式看起來非常專業。
🛫 第二步:串接地圖的飛行函數 (FlyTo)
現在,我們要把這個做好的 SearchBar 元件放到地圖頁面中,並把它的 onCampSelect 回呼函數,跟地圖的飛行功能綁定在一起。
要在 React-Leaflet 中控制地圖的視角,我們需要先拿到地圖的「實例 (Instance)」。這通常透過 <MapContainer> 的 ref 來取得。
打開你的主頁面 (例如 MapPage.tsx),修改程式碼如下:
import { useState, useRef } from 'react';
import { MapContainer, TileLayer } from 'react-leaflet';
import SearchBar from './SearchBar';
export default function MapPage() {
// 1. 建立一個 Ref 來抓住 Leaflet 地圖的控制權
const mapRef = useRef(null);
// 2. 定義當搜尋框選中營區時,要發生的動作
const handleCampSelect = (lat, lng) => {
const map = mapRef.current;
if (map) {
// 關鍵魔法:瞬間飛往目標營區,並放大到等級 15!
// duration: 2 代表飛行過程花費 2 秒鐘,創造平滑視覺
map.flyTo([lat, lng], 15, { duration: 2 });
}
};
return (
<div className="relative h-screen w-full">
{/* 搜尋框區塊:絕對定位浮在地圖最上方 */}
<div className="absolute top-6 left-1/2 -translate-x-1/2 z-[1000] w-11/12 max-w-md">
<SearchBar campsData={mockData} onCampSelect={handleCampSelect} />
</div>
{/* 地圖本體區塊 */}
<MapContainer
ref={mapRef} // 把 mapRef 綁定上來
center={[23.5, 121.0]}
zoom={8}
className="h-full w-full z-0"
>
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
{/* 這裡放你的 Marker... */}
</MapContainer>
</div>
);
}
存檔後,測試看看。當你在搜尋框輸入「武陵」,點擊下拉選單出現的「武陵農場」,你的畫面會以極度平滑的動畫,從台灣全圖的視角,飛越山川,直接空降並放大到台中和平區的目的地! 這種絲滑的互動體驗,就是讓客戶心甘情願掏出 10 萬塊結帳的殺手級功能。
✅ 課程大總結 (Course 2 結業)
狂賀!你完成了整個 Car Camping Map (全端地圖資訊平台) 實戰專案的所有章節!
這不是一個隨便寫寫、只能放在本地自嗨的練習題,而是一個具備了企業級功能的真實商業產品:
- 空間資料庫整合 (Supabase API):資料不再寫死,可以從後台無限擴充。
- 海量資料渲染優化 (Marker Clustering):一千個點位也不卡頓。
- 手機版防呆與適配 (Gesture Handling & RWD):解決滑動陷阱,隨時隨地完美展示。
- 地理定位與智慧搜尋 (FlyTo & Autocomplete):提供 Google Maps 等級的極致使用者體驗。
只要把資料庫裡的名字與經緯度換掉,你現在隨時可以把這套系統改裝成「全台特斯拉充電樁地圖」、「台北深夜咖啡廳地圖」或是「房仲尋屋雷達」上線營利!
你已經從一個網頁切版工程師,正式升級為「能開發大型地理資訊系統 (GIS) 的架構師」。 準備好迎接下一個挑戰了嗎?前往下一個專案,我們將教你如何打造自動賺錢的 Line 機器人與後台系統!