2025-06-24 vue2 引入高德地图实现搜索显示位置标记
2025-06-24 本文已影响0人
木木呀暮暮
1.申请高德地图key
1.1登录 高德开放平台,注册成为开发者并登录
1.2 创建新应用
进入【应用管理】,点击页面右上角【创建新应用】,填写表单即可创建新的应用。
image.png
1.3 创建 Key
进入【应用管理】,在我的应用中选择需要创建 Key 的应用,点击【添加 Key】,表单中的服务平台选择【Web 端】。
image.png
2.引入到vue2项目中
2.1. 安装amap
cnpm i @amap/amap-jsapi-loader --save
2.2 在components组件中创建MapCon.vue 文件
<template>
<div id="container"></div>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader'
window._AMapSecurityConfig = {
securityJsCode: '你的秘钥'
}
export default {
data() {
return {
map: null
}
},
methods: {
initMap() {
AMapLoader.load({
key: '你的key', // 申请好的Web端开发者Key,首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [''] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then(AMap => {
this.map = new AMap.Map('container', {
zoom: 6
})
})
.catch(e => {
console.log(e)
})
}
},
mounted() {
//DOM初始化完成进行地图初始化
// this.initMap()
}
}
</script>
<style lang="less">
#container {
padding: 0px;
margin: 0px;
width: 100%;
height: 100%;
min-height: 500px;
border:1px solid #ccc;
}
</style>
2.3 在需要的页面引入
<template>
<div>
<map-container></map-container>
</div>
</template>
<script>
import MapCon from "@/components/MapCon";
export default {
components: {MapContainer},
}
</script>
效果如下:
image.png
3. 搜索定位,标记等
3.1 components中修改MapCon.vue 文件
<template>
<el-row :gutter="15" class="container">
<!-- 地图 -->
<div class="mapbox">
<div class="search_box">
<div class="label">地址搜索</div>
<el-input v-model="input" placeholder="请输入内容" id="tipinput"></el-input>
</div>
<div ref="gaode_Map" id="gaode_Map"></div>
</div>
</el-row>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
window._AMapSecurityConfig = {
securityJsCode: "你的秘钥",
};
export default {
props: {
initData: [],
},
data() {
return {
district: null,
polygons: [],
form: {},
loading: false,
visible: true,
isDetail: false,
dataForm: {
kqName: undefined,
kqLocation: undefined,
kqLongitude: undefined,
kqLatitude: undefined,
kqWorkUnit: undefined,
cronkqAccredit: [],
kqValidCardRange: undefined,
},
rules: {},
input: "",
map: null,
auto: null,
placeSearch: null,
lnglat: [],
markers: [],
position: {
longitude: null,
latitude: null,
address: "",
},
circleMarker1: null,
marker: null,
geocoder: null, // 复用 Geocoder 实例
province: "",
city: "",
};
},
mounted() {
AMapLoader.reset();
this.initMap();
},
beforeUnmount() {
if (this.map) {
this.map.off("click", this.clickMapHandler);
this.map.destroy();
this.map = null; // 清空引用
}
},
methods: {
dataFormSubmit() {
this.setCircle(this.lnglat, this.dataForm.kqValidCardRange);
},
setCircle(lnglat, radius = 500, fillColor = "#ff00ff") {
if (this.marker) {
this.map.remove(this.marker);
}
if (this.circleMarker1) {
this.map.remove(this.circleMarker1);
}
this.marker = new AMap.Marker({ position: lnglat });
this.marker.setMap(this.map);
this.circleMarker1 = new AMap.CircleMarker({
map: this.map,
center: lnglat,
radius,
fillColor,
});
this.circleMarker1.setMap(this.map);
},
searchMap() {
this.auto = new AMap.AutoComplete({ input: "tipinput" });
this.placeSearch = new AMap.PlaceSearch({ map: this.map });
this.auto.on("select", this.selectSite);
},
// 选择地址
selectSite(e) {
console.log(e);
if (e.poi.location) {
const lnglat = [e.poi.location.lng, e.poi.location.lat];
console.log('选择地址', lnglat);
this.lnglat = lnglat;
this.setCircle(lnglat);
this.placeSearch.setCity(e.poi.adcode);
this.placeSearch.search(e.poi.name);
this.geocoder.getAddress(lnglat, (status, result) => {
if (status === "complete" && result.regeocode) {
const addrComp = result.regeocode.addressComponent;
this.form = {
province: addrComp.province,
city: addrComp.city,
address: e.poi.name,
coordinate: `${e.poi.location.lng},${e.poi.location.lat}`,
};
console.log(this.form);
this.dataForm.kqLongitude = e.poi.location.lat;
this.dataForm.kqLatitude = e.poi.location.lng;
this.dataForm.kqLocation = e.poi.name
this.$emit("updateLocation", this.dataForm);
} else {
console.log("查询地址失败");
}
});
} else {
this.placeSearch.setCity(e.poi.adcode)
this.placeSearch.search(e.poi.name) //关键字查询查询
// this.drawBounds(e.poi.name)
this.map.setZoom(16, true, 1)
}
},
feedBack(msg, feedBackType) {
this.$message({
showClose: true,
message: msg,
type: feedBackType
})
},
// 行政区区域划分
drawBounds(newValue) {
//加载行政区划插件
if (!this.district) {
//实例化DistrictSearch
var opts = {
subdistrict: 1, //获取边界不需要返回下级行政区
extensions: 'all', //返回行政区边界坐标组等具体信息
level: 'district' //查询行政级别为 市
}
this.map.plugin(['AMap.DistrictSearch'], () => {
this.district = new AMap.DistrictSearch(opts)
})
// this.district = new AMap.DistrictSearch(opts)
}
//行政区查询
this.district.search(newValue, (status, result) => {
console.log(result)
if (result != null) {
this.feedBack('区域搜索成功', 'success')
if (this.polygons != null) {
this.map.remove(this.polygons) //清除上次结果
this.polygons = []
}
var bounds = result.districtList[0].boundaries
if (bounds) {
for (var i = 0, l = bounds.length; i < l; i++) {
//生成行政区划polygon
var polygon = new AMap.Polygon({
strokeWeight: 1,
path: bounds[i],
fillOpacity: 0.4,
fillColor: '#80d8ff',
strokeColor: '#0091ea'
})
this.polygons.push(polygon)
}
}
this.map.add(this.polygons)
this.map.setFitView(this.polygons) //视口自适应
} else {
this.feedBack('区域搜索失败', 'error')
}
})
},
clickMapHandler(e) {
console.log(e);
const lng = e.lnglat.getLng();
const lat = e.lnglat.getLat();
this.dataForm.kqLongitude = lat;
this.dataForm.kqLatitude = lng;
this.lnglat = [lng, lat];
this.setCircle(this.lnglat);
this.geocoder.getAddress(this.lnglat, (status, result) => {
if (status === "complete" && result.regeocode) {
const regeo = result.regeocode;
this.dataForm.kqLocation = regeo.formattedAddress;
this.dataForm.localName = regeo.addressComponent.neighborhood || "";
this.input = regeo.formattedAddress;
this.position = {
longitude: lng,
latitude: lat,
address: regeo.formattedAddress,
};
this.$emit("updateLocation", this.dataForm);
} else {
console.log("查询地址失败");
}
});
},
initMap() {
AMapLoader.load({
key: "你的key",
version: "2.0",
plugins: ['AMap.Scale', 'AMap.ToolBar',"AMap.AutoComplete", 'AMap.ControlBar', "AMap.PlaceSearch", "AMap.Geocoder"],
})
.then((AMap) => {
this.map = new AMap.Map("gaode_Map", {
viewMode: "3D",
zoom: 18,
center: this.initData,
resizeEnable: true,
});
this.geocoder = new AMap.Geocoder({
// city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
city: '全国'
});
this.map.addControl(new AMap.Scale()); //比例尺
this.map.addControl(new AMap.ToolBar()); //缩放工具条
this.map .addControl(new AMap.ControlBar()); //控制罗盘
this.setCircle(this.initData);
this.searchMap();
this.map.on("click", this.clickMapHandler);
})
.catch(() => {
this.$message.error("地图加载失败");
});
},
},
};
</script>
<style lang="less">
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.mapbox {
width: 100%;
}
}
.search_box {
display: flex;
justify-content: flex-start;
align-items: center;
height: 50px;
margin-bottom: 20px;
.label {
color: #000;
width: 100px;
}
}
#gaode_Map {
overflow: hidden;
width: 100%;
height: 350px;
margin: 0;
margin-bottom: 50px;
}
.amap-sug-result {
z-index: 2999 !important;
}
</style>
3.2 修改引用的文件
<template>
<div>
<el-button type="primary" plain icon="el-icon-plus" @click="handleAdd">新增打卡位置</el-button>
<el-table v-loading="loading" :data="recordsList" border @selection-change="handleSelectionChange">
<!-- <el-table-column type="selection" width="55" align="center" /> -->
<el-table-column label="序号" type="index" align="center" width="100" />
<el-table-column label="打卡地点" align="center" prop="clockInLocation" />
<el-table-column label="打卡详细地址" align="center" prop="clockInAddress" />
<el-table-column label="有效范围/米" align="center" prop="range" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改打卡位置记录对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<Map ref="map" v-if="open" :initData="maprops" @updateLocation="updateLocation"></Map>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="打卡地点" prop="clockInLocation">
<el-input v-model="form.clockInLocation" placeholder="请输入打卡地点名称" />
</el-form-item>
<el-form-item label="详细地址" prop="clockInAddress">
<el-input v-model="form.clockInAddress" placeholder="自动带出" disabled />
</el-form-item>
<el-form-item label="经度坐标" prop="longitude">
<el-input v-model="form.longitude" placeholder="自动带出" disabled />
</el-form-item>
<el-form-item label="纬度坐标" prop="latitude">
<el-input v-model="form.latitude" placeholder="自动带出" disabled />
</el-form-item>
<el-form-item label="有效范围" prop="range">
<el-select v-model="form.range" placeholder="请选择有效范围">
<el-option label="300米" value="300"></el-option>
<el-option label="500米" value="500"></el-option>
<el-option label="1000米" value="1000"></el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
// import { 打卡列表, 某条打卡位置详情, 删除打卡数据, 新增打卡, 修改打卡 } from "@/api/modules/打卡api文件";
import Map from "@/components/MapCon";
export default {
components: { Map },
data() {
return {
loading: true,
ids: [],
single: true,
multiple: true,
total: 0,
recordsList: [],
title: "",
open: false,
queryParams: {
pageNum: 1,
pageSize: 10,
mapType: null,
longitude: null,
latitude: null,
range: null,
clockInLocation: null,
clockInAddress: null,
updateTime: null
},
form: this.getInitialForm(),
rules: {
longitude: [
{ required: true, message: "经度坐标不能为空", trigger: "blur" }
],
latitude: [
{ required: true, message: "纬度坐标不能为空", trigger: "blur" }
],
range: [
{ required: true, message: "定位范围不能为空", trigger: "blur" }
],
clockInLocation: [
{ required: true, message: "打卡地点名称不能为空", trigger: "blur" }
],
clockInAddress: [
{ required: true, message: "打卡详细地址不能为空", trigger: "blur" }
]
},
map: null,
maprops: [] // 初始化为空数组
};
},
created() {
this.getList();
},
methods: {
getInitialForm() {
return {
id: 0,
mapTypeEnum: 2,
longitude: null,
latitude: null,
range: null,
clockInLocation: null,
clockInAddress: null
};
},
updateLocation(mapData) {
this.form = {
id: this.form.id,
mapTypeEnum: 2,
longitude: mapData.kqLongitude,
latitude: mapData.kqLatitude,
clockInAddress: mapData.kqLocation
};
},
getList() {
this.loading = true;
// 打卡列表().then(response => {
// this.recordsList = response.data;
// this.total = response.total;
// this.loading = false;
// });
},
cancel() {
this.open = false;
this.reset();
if (this.map) {
this.map.destroy();
this.map = null;
}
},
reset() {
this.form = this.getInitialForm();
this.maprops = []
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
handleAdd() {
this.reset();
this.open = true;
this.title = "添加打卡地点";
this.maprops = [116.397428, 39.90923]
},
handleUpdate(row) {
this.reset();
const id = row.id;
某条打卡位置详情({ id }).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改打卡地点";
// this.maprops = { lat: row.latitude, lng: row.longitude };
this.maprops = [row.latitude, row.longitude]
});
},
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
const request = this.form.id > 0 ? 修改打卡 : 新增打卡;
console.log('this.form.id=', this.form.id)
request(this.form).then(() => {
this.$message.success(`${this.form.id > 0 ? '修改' : '新增'}成功`);
this.open = false;
this.getList();
});
}
});
},
handleDelete(row) {
this.$confirm('是否确认删除该数据项?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
删除打卡数据({ id: row.id }).then(() => {
this.getList();
this.$message.success('删除成功!');
});
}).catch(() => {
this.$message.info('已取消删除');
});
},
handleExport() {
this.download('system/records/export', { ...this.queryParams }, `records_${new Date().getTime()}.xlsx`);
}
}
};
</script>
效果图:
image.png
注意:文章参考[https://blog.csdn.net/ssk777888/article/details/134059902]
<template>
<el-dialog :title="!dataForm.id ? '新建' : isDetail ? '详情' : '编辑'" :close-on-click-modal="false" :visible.sync="visible"
class="rv-dialog rv-dialog_center" lock-scroll width="74%">
<el-row :gutter="15" class="">
<el-col :span="8">
<el-form ref="elForm" :model="dataForm" :rules="rules" size="small" label-width="70px" label-position="right"
:disabled="!!isDetail">
<el-col :span="24">
<el-form-item label="名称" prop="kqName">
<el-input v-model="dataForm.kqName" placeholder="请输入" clearable :style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="地点" prop="kqLocation">
<el-input v-model="dataForm.kqLocation" placeholder="自动带出" clearable :style="{ width: '100%' }" disabled>
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="经度" prop="kqLongitude">
<el-input v-model="dataForm.kqLongitude" placeholder="自动带出" clearable :style="{ width: '100%' }" disabled>
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="纬度" prop="kqLatitude">
<el-input v-model="dataForm.kqLatitude" placeholder="自动带出" clearable :style="{ width: '100%' }" disabled>
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="单位" prop="kqWorkUnit">
<el-input v-model="dataForm.kqWorkUnit" placeholder="请输入" clearable :style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="授权" prop="cronkqAccredit">
<uDSelect v-model="dataForm.cronkqAccredit" :multiple="true" placeholder="选择范围" title="选择范围" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="有效签卡范围(米)" label-width="150px" prop="kqValidCardRange">
<el-input v-model="dataForm.kqValidCardRange" placeholder="请输入" clearable :style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
</el-form>
</el-col>
<el-col :span="16">
<div style="width: 100%">
<div class="search_box">
<div class="label">关键字搜索</div>
<el-input v-model="input" placeholder="请输入内容" id="tipinput"></el-input>
</div>
<div ref="gaode_Map" id="gaode_Map"></div>
</div>
</el-col>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取 消</el-button>
<el-button type="primary" @click="dataFormSubmit()" v-if="!isDetail">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader"; //引入AMapLoader
window._AMapSecurityConfig = {
// 设置安全密钥
securityJsCode: "申请的安全密钥",
};
export default {
components: {},
props: [],
data () {
return {
loading: false,
visible: false,
isDetail: false,
dataForm: {
kqName: undefined,
kqLocation: undefined,
kqLongitude: undefined,
kqLatitude: undefined,
kqWorkUnit: undefined,
cronkqAccredit: [],
kqValidCardRange: undefined,
},
rules: {},
input: "",
map: null,
auto: null,
placeSearch: null,
lnglat: [],
markers: [],
position: {},
};
},
computed: {},
watch: {},
created () { },
mounted() {
AMapLoader.reset();
this.initMap();
},
methods: {
// 地图初始化
initMap () {
let centerLen = [116.397428, 39.90923];
AMapLoader.load({
key: "申请的key值", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.AutoComplete", "AMap.PlaceSearch", "AMap.Geocoder"],
})
.then((AMap) => {
this.map = new AMap.Map("gaode_Map", {
// 设置地图容器id
viewMode: "3D", // 是否为3D地图模式
zoom: 18, // 初始化地图级别
center: centerLen, //中心点坐标
resizeEnable: true,
});
this.setMarker(centerLen)
// 关键字查询
this.searchMap();
// 监听鼠标点击事件
this.map.on("click", this.clickMapHandler);
})
.catch((e) => { });
},
// 关键字查询
searchMap () {
// 搜索框自动完成类
this.auto = new AMap.AutoComplete({
input: "tipinput", // 使用联想输入的input的id
});
//构造地点查询类
this.placeSearch = new AMap.PlaceSearch({
map: this.map,
});
// 当选中某条搜索记录时触发
this.auto.on("select", this.selectSite);
},
//选中查询出的记录
selectSite (e) {
if (e.poi.location) {
// this.lnglat = [e.poi.location.lng, e.poi.location.lat];
this.placeSearch.setCity(e.poi.adcode);
this.placeSearch.search(e.poi.name); //关键字查询
let geocoder = new AMap.Geocoder({});
let that = this;
geocoder.getAddress(this.lnglat, function (status, result) {
if (status === "complete" && result.regeocode) {
that.province = result.regeocode.addressComponent.province;
that.city = result.regeocode.addressComponent.city;
//自己想要赋的值,根据自己的做修改
that.$set(that.form, "province", that.province);
that.$set(that.form, "city", that.city);
that.$set(that.form, "address", e.poi.name);
that.$set(
that.form,
"coordinate",
e.poi.location.lng + "," + e.poi.location.lat
); //纬度,经度
} else {
}
});
} else {
this.$message.error("查询地址失败,请重新输入地址");
}
},
// 点击地图事件获取经纬度,并添加标记
clickMapHandler (e) {
this.dataForm.kqLongitude = e.lnglat.getLng();
this.dataForm.kqLatitude = e.lnglat.getLat();
this.lnglat = [e.lnglat.getLng(), e.lnglat.getLat()];
this.setMarker(this.lnglat);
// 点击地图上的位置,根据经纬度转换成详细地址
let geocoder = new AMap.Geocoder({});
let that = this;
geocoder.getAddress(this.lnglat, function (status, result) {
if (status === "complete" && result.regeocode) {
that.dataForm.kqLocation = result.regeocode.formattedAddress;
} else {
}
});
this.position = {
longitude: e.lnglat.getLng(),
latitude: e.lnglat.getLat(),
address: that.address,
};
this.input = that.address; //把查询到的地址赋值到输入框
},
// 添加标记
setMarker (lnglat) {
this.removeMarker();
let marker = new AMap.Marker({
position: lnglat,
});
marker.setMap(this.map);
this.markers.push(marker);
},
// 删除之前后的标记点
removeMarker () {
if (this.markers) {
this.map.remove(this.markers);
}
},
},
};
</script>
<style lang="scss">
.search_box {
display: flex;
justify-content: flex-start;
align-items: center;
height: 50px;
.label {
color: #000;
width: 100px;
}
}
.content {
position: relative;
}
#panel {
position: absolute;
top: 50px;
right: 20px;
}
#gaode_Map {
overflow: hidden;
width: 100%;
height: 540px;
margin: 0;
}
.amap-sug-result {
z-index: 2999 !important;
}
</style>
image.png
坐标拾取器:https://lbs.amap.com/tools/picker