uni-app 开发小程序 地图选点
摘要:单独封装成一个页面 // mapselectorpage.vue import MapSelector from './components/map-selector/index.vue' export default { components: { MapSelector }, methods: { onConfirm(address { // 这里可以将选中的地址保存到Vuex或全局变量 <!--autointro-->...
单独封装成一个页面
// mapselectorpage.vue
<template>
<map-selector @confirm="onConfirm"></map-selector>
</template>
<script>
import MapSelector from './components/map-selector/index.vue'
export default {
components: { MapSelector },
methods: {
onConfirm(address) {
// 这里可以将选中的地址保存到Vuex或全局变量
this.$store.commit('setSelectedAddress', address)
// 返回上一页
// uni.navigateBack()
}
}
}
</script>
组件代码
<template>
<view class="map-selector">
<!-- 搜索框区域 -->
<view class="search-bar">
<u-search
v-model="searchKeyword"
placeholder="请输入地点搜索"
:clearable="true"
@custom="handleSearch"
@confirm="handleSearch"
@clear="handleClear"
:input-style="{ fontSize: '28rpx' }"
></u-search>
</view>
<!-- 搜索结果列表 -->
<!-- -->
<view
class="search-result"
v-if="showResult && resultList.length"
>
<view
class="result-item"
v-for="(item, index) in resultList"
:key="index"
@click="handleSelectResult(item)"
>
<u-icon name="map-marker" color="#246ED2" size="32rpx"></u-icon>
<view class="result-info">
<view class="result-title">{{ item.title }}</view>
<view class="result-address">{{ item.address }}</view>
</view>
</view>
</view>
<!-- 地图容器 -->
<view class="map-container">
<!-- 微信小程序地图 -->
<map
:longitude="longitude"
:latitude="latitude"
:markers="markers"
:show-location="true"
@markertap="handleMarkerTap"
@regionchange="handleRegionChange"
style="width: 100%; height: 100%;"
></map>
</view>
<!-- 确认按钮 -->
<view class="confirm-btn" @click="handleConfirm">
<u-button
type="primary"
shape="circle"
:disabled="!selectedAddress"
>
确认选择
</u-button>
</view>
</view>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'MapSelector',
data() {
return {
// 基础参数
isMiniProgram: uni.getSystemInfoSync().platform === 'devtools' || uni.getSystemInfoSync().platform === 'mp-weixin',
searchKeyword: '',
showResult: false,
resultList: [],
// 地图参数
longitude: 116.39747, // 默认经度(北京)
latitude: 39.90882, // 默认纬度
markers: [], // 地图标记点
selectedAddress: null, // 选中的地址信息
}
},
computed: {
...mapGetters(['userLocation'])
},
onLoad() {
// 初始化获取当前位置
this.getUserLocation()
},
methods: {
// 获取用户当前位置
getUserLocation() {
uni.getLocation({
type: 'gcj02',
success: (res) => {
this.longitude = res.longitude
this.latitude = res.latitude
this.updateMarker(res.longitude, res.latitude, '当前位置')
},
fail: (err) => {
console.error('获取位置失败', err)
uni.showToast({ title: '请允许获取位置信息', icon: 'none' })
}
})
},
// 搜索地点
handleSearch() {
if (!this.searchKeyword.trim()) return
// uni.chooseLocation 打开地图选择位置。
if (this.isMiniProgram) {
uni.chooseLocation({
keyword: this.searchKeyword,
success: (res) => {
this.updateMarker(res.longitude, res.latitude, res.name)
this.selectedAddress = {
name: res.name,
address: res.address,
longitude: res.longitude,
latitude: res.latitude
}
this.showResult = false
}
})
}
},
// 选择搜索结果
handleSelectResult(item) {
this.updateMarker(item.longitude, item.latitude, item.title)
this.selectedAddress = {
name: item.title,
address: item.address,
longitude: item.longitude,
latitude: item.latitude
}
this.showResult = false
this.searchKeyword = ''
},
// 清除搜索
handleClear() {
this.searchKeyword = ''
this.resultList = []
this.showResult = false
},
// 更新地图标记
updateMarker(longitude, latitude, title) {
this.markers = [{
id: 1,
longitude,
latitude,
title,
iconPath: '/static/images/marker.webp', // 可替换为自己的标记图标
width: 40,
height: 40,
anchor: { x: 0.5, y: 0.5 }
}]
},
// 地图标记点击
handleMarkerTap() {
console.log('handle')
if (this.selectedAddress) {
uni.showToast({
title: `已选中: ${this.selectedAddress.name}`,
icon: 'none'
})
}
},
// 地图视野变化 (小程序)
handleRegionChange(e) {
if (e.type === 'end') {
this.mapCtx = wx.createMapContext('map')
this.mapCtx.getCenterLocation({
success: (res) => {
this.longitude = res.longitude
this.latitude = res.latitude
this.getAddressByLocation(res.longitude, res.latitude)
}
})
}
},
// 通过经纬度获取地址信息
getAddressByLocation(lng, lat) {
if (this.isMiniProgram) {
wx.reverseGeocoder({
location: { longitude: lng, latitude: lat },
success: (res) => {
const address = res.result
this.selectedAddress = {
name: address.formatted_addresses.recommend,
address: address.address,
longitude: lng,
latitude: lat
}
this.updateMarker(lng, lat, address.formatted_addresses.recommend)
}
})
}
},
// 确认选择
handleConfirm() {
if (this.selectedAddress) {
// 触发父组件事件,返回选中的地址信息
this.$emit('confirm', this.selectedAddress)
// 关闭当前页面(如果是模态框形式可注释)
uni.navigateBack()
} else {
uni.showToast({ title: '请先选择地点', icon: 'none' })
}
}
}
}
</script>
<style scoped>
.map-selector {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
background-color: #fff;
}
.search-bar {
padding: 20rpx;
background-color: #fff;
z-index: 10;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.search-result {
position: absolute;
top: 120rpx;
left: 0;
right: 0;
max-height: 400rpx;
overflow-y: auto;
background-color: #fff;
z-index: 9;
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.1);
}
.result-item {
display: flex;
align-items: center;
padding: 20rpx 30rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.result-info {
margin-left: 15rpx;
}
.result-title {
font-size: 28rpx;
color: #333;
}
.result-address {
font-size: 24rpx;
color: #999;
margin-top: 5rpx;
}
.map-container {
/* flex: 1;
position: relative; */
width: 100%;
height: calc(100% - 120rpx - 120rpx);
}
.confirm-btn {
padding: 30rpx;
background-color: #fff;
}
</style>
注意
微信小程序 chooseLocation 无结果:
需在 app.json (manifest.json 源码视图)中声明权限(否则接口会静默失败):"mp-weixin" : { "requiredPrivateInfos" : [ "chooseLocation", "getLocation" ] },
本文链接:https://blog.smallhao.fun/?id=39 转载需授权!
Chen’Blog版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!