使用 OpenLayers + 高德瓦片源實現旅游足跡地圖

作為一個熱愛旅行的開發者,我一直想要一個能夠記錄和展示自己旅游足跡的功能。市面上雖然有很多地圖應用,但大多功能復雜,而我只需要一個簡單直觀的方式來標記去過的地方和想去的地方。

于是我決定在自己的個人網站上實現一個旅游足跡地圖功能。這個功能的核心需求很簡單:

  • 在地圖上標記去過的地方(綠色標記)
  • 標記想去的地方(橙色標記)
  • 支持點擊查看詳細信息
  • 適配網站的亮色/暗色主題
  • 在移動端也能良好展示

經過技術調研,我選擇了 OpenLayers + 高德地圖瓦片源的方案,既能滿足功能需求,又能保證在國內的訪問速度。

演示

旅游足跡地圖演示

我的主頁:https://fastcar.fun

你可以在我的關于頁面看到這個旅游足跡地圖的實際效果,地圖上標記了我去過的城市和想去的地方。
地圖演示

功能點詳解

技術選型考慮

在實現這個功能時,我面臨幾個技術選型的問題:

地圖庫選擇:

  • Google Maps API:需要翻墻,在國內訪問不穩定
  • 百度地圖 API:需要申請 key,有使用限制
  • 高德地圖 API:同樣需要申請 key
  • OpenLayers + 開放瓦片源:免費、靈活、無需 key

最終選擇 OpenLayers 是因為它是一個功能強大的開源地圖庫,支持多種瓦片源,而且可以直接使用高德地圖的公開瓦片服務,無需申請 API key。

瓦片源選擇:
高德地圖提供了公開的瓦片服務,支持多種樣式:

  • 標準地圖:style=8(亮色主題)
  • 暗色地圖:style=7(暗色主題)
  • 衛星圖:style=6
  • 路網圖:style=1

這些瓦片源都支持中文標注,非常適合國內用戶使用。

核心功能實現

1. 地圖初始化
使用 OpenLayers 創建地圖實例,配置高德瓦片源,設置合適的中心點和縮放級別。

2. 雙主題支持
創建亮色和暗色兩個圖層,根據網站主題動態切換顯示。

3. 標記系統
使用矢量圖層添加標記點,區分"去過"和"想去"兩種類型,使用不同的顏色和圖標。

4. 交互功能
實現點擊標記顯示詳細信息的彈窗,包括地點名稱、描述、訪問時間等。

5. 響應式設計
適配移動端顯示,調整地圖高度和彈窗樣式。

架構圖解

整體架構圖

Astro 組件
TravelMap.astro
travel-map.json 數據
OpenLayers 地圖庫
高德瓦片源
矢量圖層
已訪問標記
愿望清單標記
主題檢測系統
亮色主題圖層
暗色主題圖層
交互系統
點擊事件處理
彈窗顯示

數據流圖

JSON 數據文件
組件加載
解析數據結構
創建地圖實例
添加瓦片圖層
創建矢量圖層
遍歷數據添加標記
綁定交互事件
地圖渲染完成

主題切換時序圖

用戶站點主題系統MutationObserverTravelMap組件地圖圖層切換主題更新 DOM class檢測到 DOM 變化觸發主題檢測判斷當前主題隱藏亮色圖層顯示暗色圖層顯示亮色圖層隱藏暗色圖層alt[暗色主題][亮色主題]地圖主題更新完成用戶站點主題系統MutationObserverTravelMap組件地圖圖層

交互流程圖

用戶點擊地圖
點擊位置有標記?
獲取標記數據
無操作
創建彈窗內容
計算彈窗位置
顯示彈窗
用戶查看信息
用戶點擊關閉?
移除彈窗
保持顯示

代碼實現

地圖初始化核心代碼

function initMap() {// 亮色主題圖層 - 高德地圖標準地圖lightLayer = new ol.layer.Tile({source: new ol.source.XYZ({url: 'https://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',attributions: '? <a href="https://www.amap.com/">高德地圖</a>',maxZoom: 18})})// 暗色主題圖層 - 高德地圖暗色標準地圖darkLayer = new ol.layer.Tile({source: new ol.source.XYZ({url: 'https://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',attributions: '? <a href="https://www.amap.com/">高德地圖</a>',maxZoom: 18}),visible: false})// 創建地圖map = new ol.Map({target: 'travel-map',layers: [lightLayer, darkLayer],view: new ol.View({center: ol.proj.fromLonLat([105.0, 35.0]), // 中國中心zoom: 4,maxZoom: 18,minZoom: 2})})
}

實現要點:

  1. 使用高德地圖的公開瓦片服務,URL 中的 {1-4} 表示負載均衡的服務器
  2. style=8 是標準地圖,style=7 是暗色地圖
  3. lang=zh_cn 確保中文標注
  4. 初始時暗色圖層設置為不可見

標記添加核心代碼

function addMarkers() {const vectorSource = new ol.source.Vector()// 添加已去過的地方data.visited.forEach(location => {const feature = new ol.Feature({geometry: new ol.geom.Point(ol.proj.fromLonLat([location.coordinates[1], location.coordinates[0]])),type: 'visited',data: location})vectorSource.addFeature(feature)})// 添加想去的地方data.wishlist.forEach(location => {const feature = new ol.Feature({geometry: new ol.geom.Point(ol.proj.fromLonLat([location.coordinates[1], location.coordinates[0]])),type: 'wishlist',data: location})vectorSource.addFeature(feature)})const vectorLayer = new ol.layer.Vector({source: vectorSource,style: function(feature) {const type = feature.get('type')return new ol.style.Style({image: new ol.style.Circle({radius: 15,fill: new ol.style.Fill({color: type === 'visited' ? '#22c55e' : '#f59e0b'}),stroke: new ol.style.Stroke({color: type === 'visited' ? '#16a34a' : '#d97706',width: 3})}),text: new ol.style.Text({text: type === 'visited' ? '?' : '?',fill: new ol.style.Fill({ color: 'white' }),font: 'bold 16px sans-serif'})})}})map.addLayer(vectorLayer)
}

實現要點:

  1. 注意坐標轉換:ol.proj.fromLonLat([經度, 緯度])
  2. 使用不同顏色區分標記類型:綠色表示已訪問,橙色表示愿望清單
  3. 添加文字圖標:? 和 ? 增強視覺識別

主題切換核心代碼

function detectSiteTheme() {// 檢測站點當前主題const isDark = document.documentElement.classList.contains('dark') ||document.body.classList.contains('dark') ||document.documentElement.getAttribute('data-theme') === 'dark'currentTheme = isDark ? 'dark' : 'light'switchTheme(currentTheme)
}function switchTheme(theme) {if (theme === 'dark') {// 暗色主題:顯示高德暗色地圖lightLayer.setVisible(false)darkLayer.setVisible(true)} else {// 亮色主題:顯示高德標準地圖lightLayer.setVisible(true)darkLayer.setVisible(false)}
}function watchSiteThemeChanges() {// 使用MutationObserver監聽站點主題變化const observer = new MutationObserver(function(mutations) {mutations.forEach(function(mutation) {if (mutation.type === 'attributes' &&(mutation.attributeName === 'class' || mutation.attributeName === 'data-theme')) {detectSiteTheme()}})})observer.observe(document.documentElement, {attributes: true,attributeFilter: ['class', 'data-theme']})
}

實現要點:

  1. 支持多種主題檢測方式,兼容不同的主題切換實現
  2. 使用 MutationObserver 監聽 DOM 變化,實現主題自動切換
  3. 通過圖層的 setVisible() 方法控制顯示/隱藏

數據結構設計

{"visited": [{"id": "beijing","name": "北京","nameEn": "Beijing","coordinates": [39.9042, 116.4074],"description": "中國首都","visitDate": "2023-05"}],"wishlist": [{"id": "xian","name": "西安","nameEn": "Xi'an","coordinates": [34.3416, 108.9398],"description": "古都西安,兵馬俑故鄉","priority": "high"}]
}

設計要點:

  1. 分離已訪問和愿望清單數據
  2. 坐標使用 [緯度, 經度] 格式
  3. 支持中英文名稱
  4. 可擴展字段:訪問時間、優先級等

簡單總結

通過使用 OpenLayers + 高德瓦片源,我成功實現了一個功能完整的旅游足跡地圖。這個方案的主要優勢:

技術優勢:

  • 無需申請 API key,降低使用門檻
  • 支持自定義樣式和交互
  • 高德地圖在國內訪問速度快,中文支持好
  • OpenLayers 功能強大,擴展性好

功能特色:

  • 雙主題自動切換,與網站整體風格保持一致
  • 直觀的標記系統,清晰區分已訪問和愿望清單
  • 響應式設計,移動端體驗良好
  • 交互彈窗提供詳細信息展示

后續改進方向:

  1. 添加路線規劃功能,連接相鄰的旅游點
  2. 支持照片上傳,為每個地點添加旅游照片
  3. 增加統計功能,顯示旅游里程、訪問城市數量等
  4. 支持數據導入導出,方便備份和分享
  5. 添加搜索功能,快速定位特定地點
  6. 集成天氣信息,顯示各地實時天氣

這個旅游足跡地圖不僅滿足了我個人記錄旅游經歷的需求,也為網站訪客提供了一個了解我旅游足跡的有趣方式。通過開源的技術棧實現,也為其他開發者提供了一個可參考的實現方案。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96523.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96523.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96523.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Redis基礎(含常用命令等以快速入門)

一、初步認識 1、NoSQL SQL 關系型數據庫&#xff08;表結構&#xff0c;強一致&#xff09;NoSQL 非關系型數據庫&#xff08;靈活結構&#xff0c;最終一致&#xff0c;水平擴展爽&#xff09; 維度SQL&#xff08;關系型&#xff09;NoSQL&#xff08;非關系型&#xf…

OSPF特殊區域、路由匯總及其他特性

OSPF路由器需要同時維護域內路由、域間路由、外部路由信息數據庫。當網絡規模不斷擴大時&#xff0c;LSDB規模也不斷增長。如果某區域不需要為其他區域提供流量中轉服務&#xff0c;那么該區域內的路由器就沒有必要維護本區域外的鏈路狀態數據庫。OSPF通過劃分區域可以減少網絡…

在緩存Cacheable注解中Key值如何使用常量

1.在常量類中定義商品緩存空間和商品緩存KEY public interface CacheConstants {/*** Goods Cache Name*/String QNA_GOODS_CACHE "qna-goods";/*** Goods Cache key*/String QNA_GOODS_CACHE_KEY "qna_goods:";/*** Order Cache Name*/String QNA_ORDER…

sklearn聚類

在此將sklearn官網的一張關于聚類算法比較的圖片放過來。 下面的表格是根據sklearn官網翻譯而來。 方法名稱 參數 可擴展性 應用場景 幾何度量(距離) MiniBatchKMeans 簇的數量 非常適合處理大量樣本和中等數量的簇(使用MiniBatch時) 通用型,適用于簇大小均勻、幾何形狀平…

Recharts:React圖表庫,組件化設計助力高效數據可視化開發

你寫前端項目時有沒有卡過數據可視化的坑&#xff1f;比如要做個用戶增長折線圖&#xff0c;查了半天原生 JS 教程&#xff0c;寫了幾十行代碼&#xff0c;結果要么坐標軸對不上&#xff0c;要么數據渲染不出來&#xff1b;或者用了某個圖表庫&#xff0c;文檔全是英文&#xf…

Java 中String類的常用方法

Java 中的 String 類提供了豐富的方法用于字符串操作&#xff0c;以下是最常用的一些方法分類總結&#xff1a; 一、獲取字符串信息length()&#xff1a;返回字符串長度&#xff08;字符個數&#xff09; String s "hello"; int len s.length(); // len 5charAt(i…

【記錄】Docker|Docker內部訪問LInux主機上的Ollama服務

部分內容參考自&#xff1a;使得 docker 容器內部可以訪問宿主機的 ollama 服務_docker 訪問 ollama-CSDN 博客&#xff0c;補充添加了更多的細節&#xff0c;也補充了一個更加簡單的方案。 我測試的系統版本&#xff1a;Ubuntu 24.04.2 LTS noble&#xff0c;查看方式是指令 l…

數據庫物理外鍵與邏輯外鍵全解析

一、核心概念 1. 物理外鍵 (Physical Foreign Key) 物理外鍵是數據庫層面通過語法明確創建的外鍵約束。它是由數據庫管理系統&#xff08;DBMS&#xff09;本身&#xff08;如 MySQL, PostgreSQL, Oracle&#xff09;來強制實現的。 它是什么&#xff1a;數據庫表結構的一部分&…

Vue3入門到實戰,最新版vue3+TypeScript前端開發教程,創建Vue3工程,筆記03

筆記03 一、創建Vue3項目 1.1、創建方式 使用vue-cli創建使用vite創建&#xff08;推薦&#xff09;Vue3官網創建項目文檔 兩種創建方式&#xff0c;推薦使用第二種。vue-cli是基于webpack實現的&#xff0c;vite是新一代前端構建工具。 2.1、vue3項目結構

企業如何利用群暉 NAS 構建高效數據備份與容災體系

在數字化轉型的過程中&#xff0c;企業數據已成為核心資產。然而&#xff0c;勒索病毒攻擊、硬件故障、操作失誤以及自然災害等風險&#xff0c;都可能導致數據丟失甚至業務中斷。如何構建一個高效、安全、可恢復的數據備份與容災體系&#xff0c;已成為企業 IT 管理的關鍵課題…

關于在pycharm終端連接服務器

1、先為每個項目創建一個虛擬環境2、使用命令下載torchpip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple安裝之后發現安裝在了本地&#xff0c;我需要安裝到服務器里面&#xff0c;此時可以把本地的刪除&#xff0c;因為是默認安裝到c盤&#xff0c;除非你指定路…

CSS 繼承 (Inheritance)

一、核心概念CSS 繼承是指某些 CSS 屬性如果被設置在父元素上&#xff0c;其值會自動流向&#xff08;應用到&#xff09;其所有后代元素&#xff08;子、孫元素等&#xff09;的特性。核心價值&#xff1a;通過將樣式聲明應用于祖先元素&#xff0c;可以避免在所有后代元素上重…

UGUI源碼剖析(15):Slider的運行時邏輯與編輯器實現

UGUI源碼剖析&#xff08;第十五章&#xff09;&#xff1a;Slider的運行時邏輯與編輯器實現 在之前的章節中&#xff0c;我們已經深入了UGUI眾多核心組件的運行時源碼。然而&#xff0c;一個完整的Unity組件&#xff0c;通常由兩部分構成&#xff1a;定義其在游戲世界中行為的…

【Python】爬蟲html提取內容基礎,bs4

前言 BeautifulSoup也就是bs4,里面功能其實有很多&#xff0c;不過對于爬蟲而言主要掌握一下幾塊就可以了 怎么找標簽&#xff1f;找到標簽后怎么獲取屬性&#xff0c;怎么獲取文本內容如何通過找到的標簽繼續獲取子標簽 安裝 pip install bs4案例 對于找標簽來說&#xf…

組件庫打包工具選型(npm/pnpm/yarn)的區別和技術考量

組件庫打包工具選型&#xff1a;npm/pnpm/yarn的區別與技術考量 一、核心差異概述 組件庫打包工具的選擇&#xff0c;本質是在??依賴管理效率??、??磁盤空間占用??、??Monorepo支持??、??安裝速度??及??幽靈依賴風險??之間做權衡。npm作為Node.js默認工具…

新型APT組織“嘈雜熊“針對哈薩克斯坦能源部門發起網絡間諜活動

感染鏈圖示 | 圖片來源&#xff1a;Seqrite實驗室APT研究團隊 Seqrite實驗室APT研究團隊近日發布了一份深度分析報告&#xff0c;披露了一個自2025年4月起活躍的新型威脅組織"嘈雜熊"(Noisy Bear)。該組織主要針對哈薩克斯坦石油天然氣行業&#xff0c;攻擊手法結合…

OpenCV 圖像直方圖

目錄 一、什么是圖像直方圖&#xff1f; 關鍵概念&#xff1a;BINS&#xff08;區間&#xff09; 二、直方圖的核心作用 三、OpenCV 計算直方圖&#xff1a;calcHist 函數詳解 1. 函數語法與參數解析 2. 基礎實戰&#xff1a;計算灰度圖直方圖 代碼實現 結果分析 3. 進…

Firefox Window 開發流程(四)

1 引言 在進行 Firefox 瀏覽器的二次開發、內核研究或自定義構建之前&#xff0c;最重要的步驟就是拉取源碼并進入 Mozilla 官方提供的開發引導模式。這不僅是所有定制工作的起點&#xff0c;同時也決定了后續開發環境的穩定性與可維護性。本文將從源碼獲取、工具使用、引導腳…

mybatis plus 使用wrapper輸出SQL

在MyBatis-Plus中&#xff0c;Wrapper對象用于構建復雜的查詢條件。雖然MyBatis-Plus本身沒有直接提供從Wrapper對象獲取完整SQL語句的方法&#xff0c;但你可以通過一些間接的方式來獲取生成的SQL片段。以下是如何使用MyBatis-Plus的Wrapper來獲取SQL片段的步驟&#xff1a;?…

第1章:操作系統和計算機網絡

1. 操作系統和計算機網絡組成目標概述1.1. 核心知識操作系統和網絡知識很龐大&#xff0c;大多內容枯燥無味&#xff0c;主功最常用的&#xff0c;符合2/8原則。操作系統&#xff1a;內核、性能、磁盤IO、內存、CPU進程、線程、文件、中斷計算機網絡&#xff1a;OSI七層模型、T…