pozhen_web_nuxt/components/Map/index.vue
2024-09-16 17:19:23 +08:00

248 lines
7.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- <client-only> -->
<div class="map-wrapper">
<div id="mapcontainer"></div>
<div class="search-box">
<el-autocomplete v-if="props.isSearch" v-model="location.address" :fetch-suggestions="handleSearch"
:trigger-on-focus="false" clearable placeholder="输入城市+关键字搜索" @select="handleSelect"
style="width: 300px" />
<el-input v-if="props.isShowInput" v-model="location.longitude" placeholder="选择经度" maxlength="15" readonly
style="width: 150px; margin: 0 10px 0 20px"></el-input>
<el-input v-if="props.isShowInput" v-model="location.latitude" placeholder="选择纬度" maxlength="15" readonly
style="width: 150px"></el-input>
</div>
</div>
<!-- </client-only> -->
</template>
<script setup>
const props = defineProps({
// v-model (经纬度)
modelValue: {
type: Object,
default(v) {
return v;
}
},
// 是否显示搜索
isSearch: {
type: Boolean,
default: true
},
// 是否可以点击
isClick: {
type: Boolean,
default: true
},
// 是否展示当前经纬度
isShowInput: {
type: Boolean,
default: true
},
mapCb: {
type: Function,
default: function () {
}
}
});
const emit = defineEmits(['update:modelValue']);
const map = shallowRef(null);
const location = ref(props.modelValue);
onMounted(async () => {
// if (process.client) {
await initMap();
// }
});
watch(location.value, val => {
// if (process.client) {
if (val.longitude && val.latitude) {
drawMarker();
}
// }
});
const keyword = ref('');
let placeSearch, AMapObj, marker, geocoder;
async function initMap() {
const AMapLoader = await import('@amap/amap-jsapi-loader');
AMapLoader.load({
key: '582deef9a68a17068f3b7e291807045d', // 申请好的Web端Key首次调用 load 时必填
version: '2.0'
}).then(async AMap => {
await props.mapCb()
AMapObj = AMap;
map.value = new AMap.Map('mapcontainer');
// 添加点击事件
if (props.isClick) {
map.value.on('click', onMapClick);
}
if (location.value.longitude) {
drawMarker();
}
AMap.plugin(
[
'AMap.ToolBar',
'AMap.Scale',
'AMap.Geolocation',
'AMap.PlaceSearch',
'AMap.Geocoder'
],
() => {
// 缩放条
const toolbar = new AMap.ToolBar();
// 比例尺
const scale = new AMap.Scale();
// 定位
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true, //是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位默认5s
position: 'RT', //定位按钮的停靠位置
buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量默认Pixel(10, 20)
zoomToAccuracy: true //定位成功后是否自动调整地图视野到定位点
});
geocoder = new AMap.Geocoder({
city: '全国'
});
map.value.addControl(geolocation);
map.value.addControl(toolbar);
map.value.addControl(scale);
placeSearch = new AMap.PlaceSearch({
map: map.value,
city: '',
pageSize: 30, // 单页显示结果条数
pageIndex: 1, // 页码
citylimit: false, // 是否强制限制在设置的城市内搜索
autoFitView: true
});
}
);
});
}
// 搜索地图
function handleSearch(queryString, cb) {
placeSearch.search(queryString, (status, result) => {
if (result && typeof result === 'object' && result.poiList) {
const list = result.poiList.pois;
list.forEach(item => {
item.value = item.name;
item.label = item.name;
});
cb(list);
} else {
cb([]);
}
});
}
// 点击地图
function onMapClick(e) {
const { lng, lat } = e.lnglat;
// 逆地理编码
geocoder.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.info === 'OK') {
const { addressComponent, formattedAddress } = result.regeocode;
let { city, province, district } = addressComponent;
if (!city) {
// 直辖市
city = province;
}
// location.value = {
// longitude: lng,
// latitude: lat,
// address: formattedAddress,
// zone: [province, city, district],
// };
location.value.longitude = lng;
location.value.latitude = lat;
location.value.address = formattedAddress;
location.value.zone = [province, city, district];
}
});
}
// 点击搜索项
function handleSelect(item) {
// const { pname, cityname, adname, address, name } = item;
const { lng, lat } = item.location;
// 逆地理编码
geocoder.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.info === 'OK') {
const { addressComponent, formattedAddress } = result.regeocode;
let { city, province, district } = addressComponent;
if (!city) {
// 直辖市
city = province;
}
// location.value = {
// longitude: lng,
// latitude: lat,
// address: formattedAddress,
// zone: [province, city, district],
// };
location.value.longitude = lng;
location.value.latitude = lat;
location.value.address = formattedAddress;
location.value.zone = [province, city, district];
}
});
// location.value = {
// longitude: lng,
// latitude: lat,
// address,
// zone: [pname, cityname, adname],
// name
// };
// location.value.longitude = lng;
// location.value.latitude = lat;
// location.value.address = address;
// location.value.name = name;
// location.value.zone = [pname, cityname, adname];
map.value.setZoomAndCenter(16, [lng, lat]);
}
// 绘制地点marker
function drawMarker(val) {
const { longitude, latitude } = location.value || val;
if (marker) {
marker.setMap(null);
}
marker = new AMapObj.Marker({
position: new AMapObj.LngLat(longitude, latitude),
anchor: 'bottom-center'
});
map.value.add(marker);
map.value.setZoomAndCenter(16, [longitude, latitude]);
}
</script>
<style lang="scss" scoped>
.map-wrapper {
position: relative;
width: 100%;
height: 400px;
display: flex;
#mapcontainer {
width: 100%;
height: 100%;
}
.search-box {
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
display: flex;
flex-wrap: wrap;
align-items: center;
}
}
</style>