基于Uni-app+vue3實現微信小程序地圖固定中心點范圍內拖拽選擇位置功能(分步驟詳解)

一、功能概述與實現步驟

1.1 功能需求

  • 顯示地圖并固定中心點標記

  • 繪制服務區域多邊形邊界

  • 實時檢測拖拽后位置是否在服務區內

  • 提供位置確認和超出范圍提示功能

1.2 實現步驟分解

第一步:初始化地圖基礎配置
  1. 創建Map組件并設置基本屬性

  2. 定義服務區域多邊形坐標

  3. 設置地圖初始中心點

第二步:實現地圖交互邏輯
  1. 監聽地圖拖拽事件

  2. 獲取拖拽后中心點坐標

  3. 判斷坐標是否在服務區內

第三步:實現覆蓋層UI
  1. 固定中心點標記

  2. 位置信息顯示面板

  3. 操作按鈕(確認/返回服務區)

    二、分步驟代碼實現

    2.1 第一步:地圖基礎配置

    <template><view class="map-container"><mapid="map"style="width: 100%; height: 80vh":latitude="center.latitude":longitude="center.longitude":polygons="polygons"@regionchange="handleMapDrag":show-location="true"><!-- 覆蓋層將在第三步添加 --></map></view>
    </template><script setup>
    import { ref, onMounted } from "vue";// 服務區域邊界坐標
    const serviceAreaPolygon = [{ latitude: 34.808, longitude: 113.55 },{ latitude: 34.805, longitude: 113.58 },// ...其他坐標點{ latitude: 34.808, longitude: 113.55 } // 閉合多邊形
    ];// 中心點位置
    const center = ref({latitude: 34.747, longitude: 113.625
    });// 多邊形配置
    const polygons = ref([{points: serviceAreaPolygon,strokeWidth: 2,strokeColor: "#1E90FF",fillColor: "#1E90FF22"
    }]);// 初始化地圖上下文
    const mapContext = ref(null);
    onMounted(() => {mapContext.value = uni.createMapContext("map");
    });
    </script>

    2.2 第二步:地圖交互邏輯實現

    // 當前坐標點
    const currentPos = ref({ ...center.value });
    // 是否在服務區內
    const isInServiceArea = ref(true);// 地圖拖拽事件處理
    const handleMapDrag = (e) => {if (e.type === "end") {mapContext.value.getCenterLocation({success: (res) => {currentPos.value = {latitude: res.latitude,longitude: res.longitude};// 判斷是否在服務區內isInServiceArea.value = isPointInPolygon(currentPos.value,serviceAreaPolygon);}});}
    };// 射線法判斷點是否在多邊形內
    function isPointInPolygon(point, polygon) {const { latitude, longitude } = point;let inside = false;for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {const xi = polygon[i].longitude, yi = polygon[i].latitude;const xj = polygon[j].longitude, yj = polygon[j].latitude;const intersect = ((yi > latitude) !== (yj > latitude))&& (longitude < (xj - xi) * (latitude - yi) / (yj - yi) + xi);if (intersect) inside = !inside;}return inside;
    }

    2.3 第三步:覆蓋層UI實現

    <!-- 在map標簽內添加 -->
    <cover-view class="center-marker"></cover-view><cover-view class="info-box" :class="{ 'out-of-range': !isInServiceArea }"><cover-view v-if="isInServiceArea">當前位置在服務區域內</cover-view><cover-view v-else class="error">當前選擇位置超出服務區域</cover-view><cover-view class="coords">緯度: {{ currentPos.latitude.toFixed(6) }} 經度: {{ currentPos.longitude.toFixed(6) }}</cover-view><cover-view v-if="!isInServiceArea" class="recenter-btn" @tap="centerToServiceArea">查看最近的服務區域</cover-view><cover-view v-else class="confirm-btn" @tap="confirmLocation">確定上車位置</cover-view>
    </cover-view>

    2.4 第四步:業務功能完善

    // 返回服務區中心
    const centerToServiceArea = () => {const center = getPolygonCenter(serviceAreaPolygon);currentPos.value = { ...center };isInServiceArea.value = true;mapContext.value.moveToLocation({latitude: center.latitude,longitude: center.longitude});
    };// 計算多邊形中心點
    function getPolygonCenter(polygon) {let latSum = 0, lngSum = 0;polygon.forEach(point => {latSum += point.latitude;lngSum += point.longitude;});return {latitude: latSum / polygon.length,longitude: lngSum / polygon.length};
    }// 確認位置
    const confirmLocation = () => {uni.showToast({title: `位置已確認: ${currentPos.value.latitude.toFixed(6)}, ${currentPos.value.longitude.toFixed(6)}`,icon: "none"});// 實際業務中可以觸發回調或跳轉
    };

    三、完整實現代碼

    <template><view class="map-container"><mapid="map"style="width: 100%; height: 80vh":latitude="center.latitude":longitude="center.longitude":polygons="polygons"@regionchange="handleMapDrag":show-location="true"><cover-view class="center-marker"></cover-view><cover-view class="info-box" :class="{ 'out-of-range': !isInServiceArea }"><cover-view v-if="isInServiceArea">當前位置在服務區域內</cover-view><cover-view v-else class="error">當前選擇位置超出服務區域</cover-view><cover-view class="coords">緯度: {{ currentPos.latitude.toFixed(6) }} 經度: {{ currentPos.longitude.toFixed(6) }}</cover-view><cover-view v-if="!isInServiceArea" class="recenter-btn" @tap="centerToServiceArea">查看最近的服務區域</cover-view><cover-view v-else class="confirm-btn" @tap="confirmLocation">確定上車位置</cover-view></cover-view></map></view>
    </template><script setup>
    import { ref, onMounted } from "vue";// 服務區域邊界
    const serviceAreaPolygon = [{ latitude: 34.808, longitude: 113.55 },{ latitude: 34.805, longitude: 113.58 },{ latitude: 34.79, longitude: 113.61 },{ latitude: 34.765, longitude: 113.625 },{ latitude: 34.735, longitude: 113.62 },{ latitude: 34.71, longitude: 113.6 },{ latitude: 34.7, longitude: 113.57 },{ latitude: 34.715, longitude: 113.54 },{ latitude: 34.75, longitude: 113.53 },{ latitude: 34.808, longitude: 113.55 }
    ];const center = ref(getPolygonCenter(serviceAreaPolygon));
    const currentPos = ref({ ...center.value });
    const isInServiceArea = ref(true);
    const mapContext = ref(null);const polygons = ref([{points: serviceAreaPolygon,strokeWidth: 2,strokeColor: "#1E90FF",fillColor: "#1E90FF22"
    }]);onMounted(() => {mapContext.value = uni.createMapContext("map");
    });const handleMapDrag = (e) => {if (e.type === "end") {mapContext.value.getCenterLocation({success: (res) => {currentPos.value = {latitude: res.latitude,longitude: res.longitude};isInServiceArea.value = isPointInPolygon(currentPos.value,serviceAreaPolygon);}});}
    };function isPointInPolygon(point, polygon) {const { latitude, longitude } = point;let inside = false;for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {const xi = polygon[i].longitude, yi = polygon[i].latitude;const xj = polygon[j].longitude, yj = polygon[j].latitude;const intersect = ((yi > latitude) !== (yj > latitude))&& (longitude < (xj - xi) * (latitude - yi) / (yj - yi) + xi);if (intersect) inside = !inside;}return inside;
    }function getPolygonCenter(polygon) {let latSum = 0, lngSum = 0;polygon.forEach(point => {latSum += point.latitude;lngSum += point.longitude;});return {latitude: latSum / polygon.length,longitude: lngSum / polygon.length};
    }const centerToServiceArea = () => {const center = getPolygonCenter(serviceAreaPolygon);currentPos.value = { ...center };isInServiceArea.value = true;mapContext.value.moveToLocation({latitude: center.latitude,longitude: center.longitude});
    };const confirmLocation = () => {uni.showToast({title: `位置已確認: ${currentPos.value.latitude.toFixed(6)}, ${currentPos.value.longitude.toFixed(6)}`,icon: "none"});
    };
    </script><style scoped>
    .map-container {width: 100%;height: 100vh;position: relative;
    }.center-marker {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 20px;height: 20px;background-color: #5ca7fc;border-radius: 50%;border: 2px solid white;z-index: 999;
    }.info-box {position: absolute;top: 20%;left: 50%;transform: translateX(-50%);background: rgba(255, 255, 255, 0.9);padding: 12px 16px;border-radius: 8px;width: 80%;box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    }.info-box.out-of-range {background: rgba(255, 240, 240, 0.9);
    }.coords {font-size: 12px;color: #666;margin: 8px 0;
    }.error {color: #f56c6c;font-weight: bold;
    }.recenter-btn, .confirm-btn {margin-top: 10px;padding: 8px 12px;border-radius: 4px;text-align: center;font-size: 14px;
    }.recenter-btn {background: #606266;color: white;
    }.confirm-btn {background: #409eff;color: white;
    }
    </style>

    四、總結

    本文分步驟詳細講解了如何使用Uni-app實現地圖位置選擇功能,從基礎配置到完整實現,重點介紹了:

  • 地圖基礎配置方法

  • 多邊形區域繪制與判斷

  • 交互邏輯的實現

  • 覆蓋層UI的開發技巧

  • .moveToLocation移動api 只有在真機才能實現,微信開發者工具不支持

  • 可直接復制完整代碼到單頁測試運行,歡迎補充問題

五、實現效果

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

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

相關文章

《設計模式》抽象工廠模式

1.抽象工廠模式定義 抽象工廠模式&#xff08;Abstact Factory &#xff09;&#xff1a; 提供一個創建一系列相關或者相互依賴對象的接口&#xff0c;而無須指定它們具體的類。 1.1 UML圖&#xff1a;2.抽象工廠模式舉例&#xff1a; 業務場景&#xff1a;需要實現一個數據訪問…

git stash臨時保存工作區

通過git stash 可以靈活管理臨時修改&#xff0c;保持工作區整潔&#xff0c;是多人協作或多任務切換時的常用工具&#xff0c;主要用于臨時保存工作區和暫存區修改的命令&#xff0c;常用于以下場景&#xff1a;&#xff08;1&#xff09;需要切換分支&#xff0c;但不想立即提…

Vue 3.5+ Teleport defer 屬性詳解:解決組件渲染順序問題的終極方案

&#x1f4cb; 概述 Vue 3.5 引入了 Teleport 的 defer 屬性&#xff0c;這是一個重要的延遲解析特性。傳統的 Teleport 在組件掛載時會立即解析目標容器&#xff0c;而 defer 屬性允許推遲 Teleport 的目標解析&#xff0c;直到應用的其他部分掛載完成。 ?? 傳統 Teleport …

【102頁PPT】某著名企業智能制造解決方案及智能工廠產品介紹(附下載方式)

篇幅所限&#xff0c;本文只提供部分資料內容&#xff0c;完整資料請看下面鏈接 https://download.csdn.net/download/2501_92808811/91662620 資料解讀&#xff1a;某著名企業智能制造解決方案及智能工廠產品介紹 詳細資料請看本解讀文章的最后內容 智能制造背景與整體規劃…

Revisiting Character-level Adversarial Attacks for Language Models

文章目錄**核心設計目標****關鍵步驟與實現細節**1. **候選位置選擇&#xff08;Algorithm 1: get_top_locations&#xff09;**2. **擾動生成與篩選&#xff08;Algorithm 2: Charmer&#xff09;**3. **適配大語言模型&#xff08;LLM&#xff09;的攻擊****實驗中的性能表現…

(一)Python + 地球信息科學與技術 (GeoICT)=?

目錄 引子 一、核心定位&#xff1a;Python 為何能重塑 GeoICT&#xff1f; 二、Python 在 GeoICT 中的關鍵應用領域 1. 空間數據處理&#xff08;GIS 基礎&#xff09; 2. 遙感圖像處理與解譯 3. 空間分析與建模 4. 地學數據可視化 5. 時空大數據分析 三、Python GeoI…

OpenAI 發布了 GPT-5,有哪些新特性值得關注?國內怎么使用GPT5?

GPT-5很強&#xff0c;在LMAreana上獲得了1481分&#xff0c;超過Gemini 2.5 Pro&#xff0c;奪回第一。 國內怎么使用GPT5&#xff1f;-> zhangfeidezhu.com/?p1033 這次發布的GPT-5系列包含三個模型&#xff1a; GPT-5&#xff1a;適合復雜推理、廣泛的世界知識&#x…

PowerPoint和WPS演示放映PPT時如何禁止鼠標翻頁

在演示播放PPT的時候&#xff0c;我們有時候會用鼠標在幻燈片上劃重點&#xff0c;一不小心就點擊了鼠標左鍵&#xff0c;而默認的鼠標左鍵是向下翻頁&#xff08;下一步&#xff09;。可以簡單設置一下&#xff0c;禁用鼠標翻頁的功能&#xff0c;改為其他方式翻頁。一、禁用/…

基于springboot養老院管理系統 畢業論文+項目源碼及數據庫文件

&#xff01;&#xff01;&#xff01; 有需要的小伙伴可以通過文章末尾名片咨詢我哦&#xff01;&#xff01;&#xff01; &#x1f495;&#x1f495;作者&#xff1a;優創學社 &#x1f495;&#x1f495;個人簡介&#xff1a;本人在讀博士研究生&#xff0c;擁有多年程序開…

Meteodyn WT 6.7(Meteodyn)風力資源評估及微觀選址軟件工具

Meteodyn WT 6.7&#xff08;Meteodyn&#xff09;風力資源評估及微觀選址軟件工具&#xff0c;基于計算流體力學&#xff08;CFD&#xff09;技術&#xff0c;主要用于復雜地形下的風能評估和風電場選址。該軟件由法國政府環境與能源署&#xff08;ADEME&#xff09;支持開發&…

計算機網絡 TCP time_wait 狀態 詳解

TCP 的 TIME_WAIT 狀態是 TCP 連接終止過程中 主動關閉連接的一方&#xff08;通常是先調用 close() 或主動發送 FIN 的一端&#xff09;進入的一個重要狀態。理解其原理、副作用和優化策略對高性能網絡編程和服務器調優至關重要。&#x1f50d; 一、TIME_WAIT 是什么&#xff…

《GuardHFL: Privacy Guardian for Heterogeneous Federated Learning》——論文閱讀

研究背景&#xff1a;異構聯邦中各客戶端模型結構&#xff0c;精度&#xff0c;算力都不同&#xff0c;無法像傳統聯邦那樣共享梯度&#xff0c;只能通過“查詢-響應”使用輔助數據來訓練模型。這種方法存在嚴重隱私問題&#xff1a;直接共享查詢樣本會泄露敏感信息&#xff0c…

Spring AI 進階之路01:三步將 AI 整合進 Spring Boot

引子 當 LLM 的浪潮以不可阻擋之勢席卷全球&#xff0c;從改變用戶交互到重塑商業模式&#xff0c;我們每一位開發者都身處這場技術變革的中心。作為龐大的 Java 生態中的一員&#xff0c;你是否也曾思考&#xff1a;當 Python 似乎成為 AI 的“官方語言”時&#xff0c;我們這…

pycharm2025導入anaconda創建的各個AI環境

目錄1.pycharm下載及安裝2.導入anaconda的環境到pycharm項目中1.pycharm下載及安裝 建議從官網下載&#xff0c;不要亂下載。 https://www.jetbrains.com.cn/en-us/pycharm/ 右上角可以切換中英文&#xff0c;在此切換為中文。 點擊下載&#xff0c;如下頁面: 點擊中間下載w…

獲取IPv6地址的三種方式

DHCPv6無狀態自動分配IP地址Server 配置&#xff1a;<Huawei>system-view[Huawei]ipv6[Huawei]dhcp enable[Huawei]dhcpv6 pool pool1[Huawei-dhcpv6-pool-pool1]dns-server 2002::2[Huawei-dhcpv6-pool-pool1]dns-domain-name example.com[Huawei-dhcpv6-pool-pool1]qui…

[Oracle數據庫] Oracle 復雜查詢

對于剛接觸 Oracle 數據庫的初學者來說&#xff0c;簡單查詢&#xff08;如SELECT * FROM 表名&#xff09;可能不難掌握&#xff0c;但面對復雜業務場景時&#xff0c;就需要更強大的查詢能力。本文將圍繞 Oracle 復雜查詢的核心知識點展開&#xff0c;包括條件邏輯、分組函數…

Redis-plus-plus API使用指南:通用操作與數據類型接口介紹

&#x1f351;個人主頁&#xff1a;Jupiter.&#x1f680; 所屬專欄&#xff1a;Redis 歡迎大家點贊收藏評論&#x1f60a;目錄通用 API連接 Redis1. get/set2. exists 方法3. del 方法4. keys 方法5. expire 方法6. ttl 方法7. type 方法8. flushall 方法String 類型 API1. ge…

基于遺傳編程的自動程序生成

這里寫目錄標題核心概念與工作原理1. 個體表示&#xff1a;樹結構2. 初始化種群3. 適應度評估4. 選擇5. 遺傳操作&#xff08;繁殖&#xff09;6. 新一代種群形成7. 終止條件基于遺傳編程的符號回歸示例問題示例GP實現符號回歸&#xff08;Deap&#xff09;GP實現符號回歸&…

flowable匯總查詢方式

背景&#xff1a;小程序開發申請流程。使用flowable流程框架。用戶需要在后臺統攬用戶申請的匯總表。 設計思路&#xff1a;通過查詢流程實例分頁查詢獲取數據&#xff0c; 其中可以通過查詢條件進行查詢&#xff0c;查詢條件是流程申請時添加到流程變量當中的&#xff0c;方便…

力扣438:找到字符串中所有的字母異位詞

力扣438:找到字符串中所有的字母異位詞題目思路代碼題目 給定兩個字符串 s 和 p&#xff0c;找到 s 中所有 p 的 異位詞 的子串&#xff0c;返回這些子串的起始索引。不考慮答案輸出的順序。 思路 我們先不看異位詞這個條件&#xff0c;如何在字符串s中找到字符串p。我們可以…