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

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

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

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

1.1 功能需求

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

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

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

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

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

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

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

固定中心點(diǎn)標(biāo)記

位置信息顯示面板

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

二、分步驟代碼實(shí)現(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ū)域邊界坐標(biāo)
const serviceAreaPolygon = [
  { latitude: 34.808, longitude: 113.55 },
  { latitude: 34.805, longitude: 113.58 },
  // ...其他坐標(biāo)點(diǎn)
  { latitude: 34.808, longitude: 113.55 } // 閉合多邊形
];

// 中心點(diǎn)位置
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 第二步:地圖交互邏輯實(shí)現(xiàn)

// 當(dāng)前坐標(biāo)點(diǎn)
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
        );
      }
    });
  }
};

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

<!-- 在map標(biāo)簽內(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
  });
};

// 計(jì)算多邊形中心點(diǎn)
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
  };
}

// 確認(rèn)位置
const confirmLocation = () => {
  uni.showToast({
    title: `位置已確認(rèn): ${currentPos.value.latitude.toFixed(6)}, ${currentPos.value.longitude.toFixed(6)}`,
    icon: "none"
  });
  // 實(shí)際業(yè)務(wù)中可以觸發(fā)回調(diào)或跳轉(zhuǎn)
};

三、完整實(shí)現(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: `位置已確認(rèn): ${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é)

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

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

五、實(shí)現(xiàn)效果

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

    詳解10分鐘學(xué)會(huì)vue滾動(dòng)行為

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

    vue將某個(gè)組件打包成js并在其他項(xiàng)目使用

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

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

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

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

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

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

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

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

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

最新評(píng)論

同仁县| 余干县| 施秉县| 固原市| 三亚市| 全椒县| 沙田区| 香港| 手机| 娱乐| 昌宁县| 普宁市| 仪征市| 岢岚县| 若尔盖县| 宜章县| 延安市| 大连市| 元氏县| 兖州市| 嘉善县| 赣州市| 姜堰市| 黄山市| 安义县| 营口市| 郑州市| 神农架林区| 达拉特旗| 海盐县| 大城县| 辰溪县| 巴中市| 黎川县| 叙永县| 临漳县| 锦屏县| 叙永县| 琼海市| 永州市| 民权县|