最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Uniapp+vue3實現(xiàn)微信小程序地圖固定中心點范圍內(nèi)拖拽選擇位置功能及實現(xiàn)步驟

 更新時間:2025年08月18日 11:06:04   作者:編程豬豬俠  
本文分步驟給大家介紹基于Uniapp+vue3實現(xiàn)微信小程序地圖固定中心點范圍內(nèi)拖拽選擇位置功能,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧

一、功能概述與實現(xiàn)步驟

1.1 功能需求

  • 顯示地圖并固定中心點標記
  • 繪制服務(wù)區(qū)域多邊形邊界
  • 實時檢測拖拽后位置是否在服務(wù)區(qū)內(nèi)
  • 提供位置確認和超出范圍提示功能

1.2 實現(xiàn)步驟分解

第一步:初始化地圖基礎(chǔ)配置

  • 創(chuàng)建Map組件并設(shè)置基本屬性
  • 定義服務(wù)區(qū)域多邊形坐標
  • 設(shè)置地圖初始中心點

第二步:實現(xiàn)地圖交互邏輯

  • 監(jiān)聽地圖拖拽事件
  • 獲取拖拽后中心點坐標
  • 判斷坐標是否在服務(wù)區(qū)內(nèi)

第三步:實現(xiàn)覆蓋層UI

固定中心點標記

位置信息顯示面板

操作按鈕(確認/返回服務(wù)區(qū))

二、分步驟代碼實現(xiàn)

2.1 第一步:地圖基礎(chǔ)配置

<template>
  <view class="map-container">
    <map
      id="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";

// 服務(wù)區(qū)域邊界坐標
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 第二步:地圖交互邏輯實現(xiàn)

// 當(dāng)前坐標點
const currentPos = ref({ ...center.value });
// 是否在服務(wù)區(qū)內(nèi)
const isInServiceArea = ref(true);

// 地圖拖拽事件處理
const handleMapDrag = (e) => {
  if (e.type === "end") {
    mapContext.value.getCenterLocation({
      success: (res) => {
        currentPos.value = {
          latitude: res.latitude,
          longitude: res.longitude
        };
        // 判斷是否在服務(wù)區(qū)內(nèi)
        isInServiceArea.value = isPointInPolygon(
          currentPos.value,
          serviceAreaPolygon
        );
      }
    });
  }
};

// 射線法判斷點是否在多邊形內(nèi)
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實現(xiàn)

<!-- 在map標簽內(nèi)添加 -->
<cover-view class="center-marker"></cover-view>

<cover-view class="info-box" :class="{ 'out-of-range': !isInServiceArea }">
  <cover-view v-if="isInServiceArea">
    當(dāng)前位置在服務(wù)區(qū)域內(nèi)
  </cover-view>
  <cover-view v-else class="error">
    當(dāng)前選擇位置超出服務(wù)區(qū)域
  </cover-view>
  
  <cover-view class="coords">
    緯度: {{ currentPos.latitude.toFixed(6) }} 
    經(jīng)度: {{ currentPos.longitude.toFixed(6) }}
  </cover-view>
  
  <cover-view 
    v-if="!isInServiceArea" 
    class="recenter-btn" 
    @tap="centerToServiceArea"
  >
    查看最近的服務(wù)區(qū)域
  </cover-view>
  
  <cover-view 
    v-else 
    class="confirm-btn" 
    @tap="confirmLocation"
  >
    確定上車位置
  </cover-view>
</cover-view>

2.4 第四步:業(yè)務(wù)功能完善

// 返回服務(wù)區(qū)中心
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"
  });
  // 實際業(yè)務(wù)中可以觸發(fā)回調(diào)或跳轉(zhuǎn)
};

三、完整實現(xiàn)代碼

<template>
  <view class="map-container">
    <map
      id="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">當(dāng)前位置在服務(wù)區(qū)域內(nèi)</cover-view>
        <cover-view v-else class="error">當(dāng)前選擇位置超出服務(wù)區(qū)域</cover-view>
        
        <cover-view class="coords">
          緯度: {{ currentPos.latitude.toFixed(6) }} 
          經(jīng)度: {{ currentPos.longitude.toFixed(6) }}
        </cover-view>
        
        <cover-view 
          v-if="!isInServiceArea" 
          class="recenter-btn" 
          @tap="centerToServiceArea"
        >
          查看最近的服務(wù)區(qū)域
        </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";

// 服務(wù)區(qū)域邊界
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>

四、總結(jié)

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

  • 地圖基礎(chǔ)配置方法
  • 多邊形區(qū)域繪制與判斷
  • 交互邏輯的實現(xiàn)
  • 覆蓋層UI的開發(fā)技巧
  • .moveToLocation移動api 只有在真機才能實現(xiàn),微信開發(fā)者工具不支持
  • 可直接復(fù)制完整代碼到單頁測試運行,歡迎補充問題

五、實現(xiàn)效果

到此這篇關(guān)于基于Uniapp+vue3實現(xiàn)微信小程序地圖固定中心點范圍內(nèi)拖拽選擇位置功能及實現(xiàn)步驟的文章就介紹到這了,更多相關(guān)uniapp vue拖拽選擇位置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue使用Three.js加載glTF模型的方法詳解

    Vue使用Three.js加載glTF模型的方法詳解

    這篇文章主要給大家介紹了關(guān)于Vue使用Three.js加載glTF模型的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • vue實現(xiàn)顯示消息提示框功能

    vue實現(xiàn)顯示消息提示框功能

    這篇文章主要介紹了vue實現(xiàn)顯示消息提示框功能,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • vue3?keep-alive實現(xiàn)tab頁面緩存功能

    vue3?keep-alive實現(xiàn)tab頁面緩存功能

    如何在我們切換tab標簽的時候,緩存標簽最后操作的內(nèi)容,簡單來說就是每個標簽頁中設(shè)置的比如搜索條件及結(jié)果、分頁、新增、編輯等數(shù)據(jù)在切換回來的時候還能保持原樣,這篇文章介紹vue3?keep-alive實現(xiàn)tab頁面緩存功能,感興趣的朋友一起看看吧
    2023-04-04
  • vue在自定義組件上使用v-model和.sync的方法實例

    vue在自定義組件上使用v-model和.sync的方法實例

    自定義組件的v-model和.sync修飾符其實本質(zhì)上都是vue的語法糖,用于實現(xiàn)父子組件的"數(shù)據(jù)"雙向綁定,下面這篇文章主要給大家介紹了關(guān)于vue在自定義組件上使用v-model和.sync的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • 詳解10分鐘學(xué)會vue滾動行為

    詳解10分鐘學(xué)會vue滾動行為

    本篇文章主要介紹了vue滾動行為,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • vue將某個組件打包成js并在其他項目使用

    vue將某個組件打包成js并在其他項目使用

    這篇文章主要給大家介紹了關(guān)于vue將某個組件打包成js并在其他項目使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Vue.js 表單控件操作小結(jié)

    Vue.js 表單控件操作小結(jié)

    這篇文章給大家介紹了Vue.js 表單控件操作的相關(guān)知識,本文通過實例演示了input和textarea元素中使用v-model的方法,本文給大家介紹的非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2018-03-03
  • vue項目刷新當(dāng)前頁面的三種方式(重載當(dāng)前頁面數(shù)據(jù))

    vue項目刷新當(dāng)前頁面的三種方式(重載當(dāng)前頁面數(shù)據(jù))

    這篇文章主要介紹了vue項目刷新當(dāng)前頁面的三種方式(重載當(dāng)前頁面數(shù)據(jù)),本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • Vue項目打包后出現(xiàn)的路徑問題以及解決方案

    Vue項目打包后出現(xiàn)的路徑問題以及解決方案

    本文詳細探討了Vue項目打包后常見的路徑問題,包括靜態(tài)資源路徑錯誤、路由路徑錯誤、環(huán)境變量路徑錯誤和publicPath配置錯誤,并提供了相應(yīng)的解決方案,通過正確配置這些路徑,可以有效解決Vue項目在打包后的資源加載問題,確保項目在生產(chǎn)環(huán)境中的正常運行
    2025-11-11
  • Vue 實現(xiàn)樹形視圖數(shù)據(jù)功能

    Vue 實現(xiàn)樹形視圖數(shù)據(jù)功能

    這篇文章主要介紹了Vue 實現(xiàn)樹形視圖數(shù)據(jù)功能,利用簡單的樹形視圖實現(xiàn)的,在實現(xiàn)過程中熟悉了組件的遞歸使用,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-05-05

最新評論

卢氏县| 砀山县| 济南市| 秦皇岛市| 昌都县| 革吉县| 菏泽市| 龙山县| 阳泉市| 荣成市| 金山区| 南宁市| 涞水县| 新昌县| 吉安市| 肃宁县| 岳西县| 潞西市| 兰西县| 淮阳县| 乡城县| 鹤庆县| 芦山县| 凤冈县| 浪卡子县| 宾川县| 中卫市| 昌平区| 东宁县| 教育| 安新县| 磐安县| 敦煌市| 广丰县| 海淀区| 威信县| 天柱县| 繁峙县| 崇左市| 宜兴市| 昌邑市|