1、准备工作
首先需要去高德开放平台注册账号,并创建一个应用的key和私钥
https://lbs.amap.com/

然后在你的项目中安装高德依赖
npm install @amap/amap-jsapi-loader
2、封装一个画围栏组件 名为MapContainer.vue(可直接使用)
<template>
<div class="campus-page">
<div id="campusMap"></div>
<div class="searchMap">
<a-input v-model="input" placeholder="请输入地点" id="tipinput" style="width: 100%; padding-right: 10px"></a-input>
</div>
<div class="input-card" style="width: 120px" v-if="title !== '详情'">
<button class="btn" @click="createPolygon()" style="margin-bottom: 5px"> 新建 </button>
<button class="btn" @click="closePolygon()" style="margin-bottom: 5px">结束</button>
<button class="btn" @click="clearPolygon()">清除</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref, watch } from 'vue';
import AMapLoader from '@amap/amap-jsapi-loader';
interface PolygonData {
key: number[][];
mapId: string;
}
export default defineComponent({
props: {
path: {
type: String,
required: false,
},
title: {
type: String,
required: false,
},
},
setup(props, { emit }) {
const pathArr = ref<PolygonData[]>([]);
const searchKeyword = ref('');
const map = ref<any>(null);
const input = ref('');
const auto = ref<any>(null);
const placeSearch = ref<any>(null);
const polygon = ref<any>(null);
let polyEditor: any = null;
const onSearch = () => {
if (searchKeyword.value !== '') {
const bounds = map.value.getBounds(); // 获取当前视野的南北边界经纬度
placeSearch.value.searchInBounds(searchKeyword.value, bounds);
}
};
const initMap = async () => {
window._AMapSecurityConfig = {
securityJsCode: '你的秘钥',
};
await AMapLoader.load({
key: '你应用的key',
version: '2.0',
plugins: [
'AMap.PolygonEditor',
'AMap.AutoComplete',
'AMap.PlaceSearch',
'AMap.Scale',
'AMap.OverView',
'AMap.ToolBar',
'AMap.MapType',
'AMap.PolyEditor',
'AMap.CircleEditor',
'AMap.Geolocation',
'AMap.Geocoder',
'AMap.Polygon',
'AMap.AMapUI',
'AMap.DragPolygon',
],
})
.then((AMap) => {
map.value = new AMap.Map('campusMap', {
viewMode: '3D',
zoom: 11,
});
searchMap();
if(props.title === '新增'){
clearPolygon()
}
if (props.path) {
const pathson = props.path.split(',');
let pathUse: number[][] = [];
for (let i = 0; i < pathson.length; i += 2) {
pathUse.push([Number(pathson[i]), Number(pathson[i + 1])]);
}
polygon.value = new AMap.Polygon({
map: map.value,
path: pathUse,
strokeColor: '#f6cdf6',
fillColor: '#74b6fd',
});
map.value.addOverlay(polygon.value);
map.value.setFitView();
}
})
.catch((e) => {
console.log(e);
});
initEditor();
};
const searchMap = () => {
auto.value = new AMap.AutoComplete({
input: 'tipinput',
});
placeSearch.value = new AMap.PlaceSearch({
map: map.value,
});
auto.value.on('select', selectSite);
};
const selectSite = (e: any) => {
if (e.poi.location) {
placeSearch.value.setCity(e.poi.adcode);
placeSearch.value.search(e.poi.name);
} else {
console.error('查询地址失败,请重新输入地址');
}
};
const initEditor = () => {
polyEditor = new AMap.PolygonEditor(map.value);
polyEditor.on('add', (data: any) => {
const polygon = data.target;
polyEditor.addAdsorbPolygons(polygon);
polygon.on('dblclick', () => {
polyEditor.setTarget(polygon);
polyEditor.open();
});
});
polyEditor.on('end', (data: any) => {
const obj: PolygonData = {
key: data.target._opts.path,
mapId: data.target._amap_id,
};
if (pathArr.value.length > 0) {
const isRepeat = pathArr.value.some((item, index) => {
if (item.mapId === obj.mapId) {
pathArr.value[index] = obj;
return true;
}
});
if (!isRepeat) {
pathArr.value.push(obj);
}
} else {
pathArr.value.push(obj);
}
console.log(pathArr.value);
});
polyEditor.open();
};
const createPolygon = () => {
polyEditor.close();
polyEditor.setTarget();
polyEditor.open();
};
const closePolygon = () => {
polyEditor.close();
emit('onPatharr', pathArr.value);
};
const clearPolygon = () => {
polyEditor.close();
map.value.clearMap();
pathArr.value = [];
emit('onPatharr', pathArr.value);
};
const startPolygon = () => {
polyEditor.open();
};
const campusOk = () => {
polyEditor.close();
if (pathArr.value.length < 1) {
console.warn('请划至少划分一个区域位置!');
}
};
const submit = () => {
console.log(pathArr.value);
};
onMounted(() => {
initMap();
});
return {
pathArr,
searchKeyword,
map,
input,
auto,
placeSearch,
polygon,
onSearch,
createPolygon,
closePolygon,
clearPolygon,
startPolygon,
campusOk,
submit,
};
},
});
</script>
<style scoped lang="less">
#campusMap {
padding: 0px;
margin: 0px;
width: 100%;
height: 80vh;
flex: 7;
position: relative;
}
.campus-page {
position: relative;
}
.searchMap {
position: absolute;
top: 10px;
right: 0;
}
.input-card {
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border-width: 0;
border-radius: 25px;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, 0.5);
position: absolute;
bottom: 10%;
right: 20px;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 7.5px 12.5px;
}
.btn {
display: inline-block;
font-weight: 400;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid transparent;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
background-color: transparent;
background-image: none;
color: #25a5f7;
border-color: #25a5f7;
padding: 0.25rem 0.5rem;
line-height: 1.5;
border-radius: 1rem;
-webkit-appearance: button;
cursor: pointer;
}
.btn:hover {
color: #fff;
background-color: #25a5f7;
border-color: #25a5f7;
}
.btn:hover {
text-decoration: none;
}
</style>
3、引入使用
先导入 修改为你组件存放地址
import regionMap from '../../components/MapContainer.vue';
在你需要使用的地方放入
path要是不需要回显
<regionMap v-if="visible" :path="preRegion" :title="title" @onPatharr="getPatharr"></regionMap>
得到围栏经纬度方法
function getPatharr(e) {
regionList.value = e[0].key;
}
至此就可以实现高德地图+vue3画电子围栏了!