本文已参与「新人创作礼」活动,一起开启掘金创作之路。
实现效果: 需求:点击输入框弹窗地图弹窗,输入框输入地址模糊搜索列表结果,点击列表添加相应得marker标记,并且添加标记拖拽选址功能。
![]()
项目中引入了 element-ui ,自行安装引入,这里不写了......
JSAPI 的加载
JS API 2.0 版本提供了两种方案引入地图 JSAPI:
-
使用官网提供的 JSAPI Loader 进行加载;
-
以常规 JavaScript 脚本的方式加载;
注意:为避免地图数据协议和前端资源不匹配导致页面运行报错,只允许在线加载 JSAPI,禁止进行本地转存、与其它代码混合打包等用法。
使用 JSAPI Loader (推荐)
JSAPI Loader是我们提供的 API 加载器,可帮助开发者快速定位、有效避免加载引用地图 JSAPI 各种错误用法,具有以下特性:
支持以 普通JS 和 npm包 两种方式使用; 有效避免错误异步加载导致的 JSAPI 资源加载不完整问题; 对于加载混用多个版本 JSAPI 的错误用法给予报错处理; 对于不合法加载引用 JSAPI 给予报错处理; 支持指定 JSAPI 版本; 支持插件加载; 允许多次执行加载操作,网络资源不会重复请求,便于大型工程模块管理; 支持IE9以上的浏览器,不支持IE8以下 注意(您在2021年12月02日申请以后的key需要配合您的安全密钥一起使用)
JSAPI key和安全密钥的使用
JSAPI key搭配代理服务器并携带安全密钥转发(安全)
1) 引入 JSAPI 使用 Loader 之前增加代理服务器设置脚本标签,设置代理服务器域名或地址,将下面示例代码中的「您的代理服务器域名或地址」替换为您的代理服务器域名或ip地址,其中_AMapService为代理请求固定前缀,不可省略或修改。 (注意您这 个设置必须是在加载loader.js的脚本引入之前进行设置,否则设置无效。)
项目代码步骤:
1、在index.html页面body中添加秘钥
<body>
<noscript>
<strong>We're sorry but map-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script type="text/javascript">
window._AMapSecurityConfig = {
// serviceHost:'您的代理服务器域名或地址/_AMapService',
securityJsCode:"xxxxxx"//申请的秘钥
}
</script>
</body>
......
2、安装@amap/amap-jsapi-loader 使用
npm i @amap/amap-jsapi-loader --save
3、重要代码:
<div class="positionBox">
<el-input style="width:600px;margin:100px 0 0 100px;" v-model="positionVal" placeholder="请输入内容" @focus="handleOpen"></el-input>
<div class="wrapper" v-show="dialogVisible">
<div class="mapcontainer">
<div class="el-dialog__header">
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click="handleClose">
<i class="el-dialog__close el-icon el-icon-close" style="font-size:25px;"></i>
</button>
</div>
<div class="mapContent">
<div id="all" style="height: 100%">
<div class="posInput">
<el-input
style="width: 100%"
id="tipinput"
class="form-control input-style"
type="text"
placeholder="请输入搜索地址"
prefix-icon="el-icon-search"
v-model="MapAdress"
>
</el-input>
</div>
<div id="allmap"></div>
<div class="posSubmit">
<el-form ref="form" label-width="100px">
<div class="btn_box">
<el-form-item label="地址坐标:" style="width:45%">
<el-input disabled type="text" v-model="insureAdress" >
</el-input>
</el-form-item>
<el-form-item label="经纬度:" style="width:45%">
<el-input disabled type="text" v-model="insureAdress2" >
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" style="margin-left: 10px" @click="insureMapAdress">确定</el-button>
</el-form-item>
</div>
</el-form>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
export default {
name: "app",
data() {
return {
dialogVisible:false,
positionVal:"",
map: null,
marker: null,
geocoder: null, // 地理编码与逆地理编码类,用于地址描述与坐标之间的转换
startAutoComplete: null,
startPlaceSearch: null,
positionPicker: null,
startSeacrh: [],
stratInfo: {},
thisPosition: {
location: "",
lng: "",
lat: "",
},
mapinitCode: 0, //地理编码:1;地理逆编码:2
MapAdress: "",
insureAdress: "",
insureAdress2: "",
};
},
mounted() {
// this.loadmap();//因为使用的弹窗加载,所以这里不用执行了,在打开弹窗时候在调用此方法
},
methods: {
loadmap() {
const that = this;
return new Promise((reslove, reject) => {
AMapLoader.load({
key: "xxxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
// version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.ToolBar","AMap.Scale", "AMap.Geocoder"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
// 是否加载 AMapUI,缺省不加载
version: "1.1", // AMapUI 缺省 1.1
plugins: [], // 需要加载的 AMapUI ui插件
},
}).then((AMap) => {
that.map = new AMap.Map("allmap", {
resizeEnable: true,
zoom: 10,
center: [116.397428, 39.90923], //中心点坐标
});
// 地图点击事件
// that.map.on("click", (e) =>{
// let lnglatXY = [e.lnglat.getLng(), e.lnglat.getLat()];
// console.log(lnglatXY)//当前经纬度
// })
//地图控件
that.map.addControl(new AMap.Scale());
that.map.addControl(new AMap.ToolBar());
// that.map.setMapStyle("amap://styles/blue")
// that.map.setMapStyle("amap://styles/darkblue")
// 地理编码与逆地理编码类,用于地址描述与坐标之间的转换
that.geocoder = new AMap.Geocoder();
//地点查询
AMap.plugin(["AMap.PlaceSearch", "AMap.Autocomplete"], function () {
let autoOptions1 = {
input: "tipinput",
city: "全国"
};
that.startAutoComplete = new AMap.Autocomplete(autoOptions1);
that.startPlaceSearch = new AMap.PlaceSearch({
map: that.map,
});
that.startAutoComplete.on("select", that.handleStartSelect); //注册监听,当选中某条记录时会触发
});
that.handlePositionPickerEvent(); //实现地图拖拽选址功能
that.map.setZoom(14);//设置缩放大小
reslove();
}).catch((e) => {
console.log(e, "高德地图加载失败");
reject(e);
});
});
},
handlePositionPickerEvent() {
let that = this;
AMapUI.loadUI(["misc/PositionPicker"], (PositionPicker) =>{
console.log("拖拽加载成功");
that.positionPicker = new PositionPicker({
// mode: 'dragMap',//拖拽地图
mode: "dragMarker",//拖拽图标
map: that.map,
});
that.positionPicker.on("success", (positionResult)=> {
console.log(positionResult, "拖拽信息");
console.log(positionResult.position,"拖拽经纬度")
if(positionResult.address){
this.insureAdress = positionResult.address;
this.insureAdress2 = "[" + positionResult.position + "]"
}else{
this.insureAdress="";
this.insureAdress2 = "";
};
});
that.positionPicker.on("fail", (positionResult) =>{
// 海上或海外无法获得地址信息
});
});
},
handleStartSelect(event) {
console.log(event, "起点经纬度 [lng,lat]");
if (event.poi.location == "") {
this.$message({
type: "warning",
message: "该地点无经纬度数据,请输入具体一点的地点!",
duration: 5 * 1000,
});
return;
}
if (this.marker) {
this.map.remove(this.marker);
this.marker = null;
}
this.startSeacrh = [];
this.stratInfo = {};
this.startSeacrh = [event.poi.location.lng, event.poi.location.lat];
this.stratInfo = {
district: event.poi.district,
address: event.poi.address,
name: event.poi.name,
};
this.insureAdress = event.poi.district + event.poi.address + event.poi.name;
this.insureAdress2 = "[" + event.poi.location.lng + "," + event.poi.location.lat + "]";
// marker添加地图上
// this.marker = new AMap.Marker({
// position: this.startSeacrh, //位置
// });
// this.map.add(this.marker); //添加到地图
// 传入经纬度,设置地图中心点
this.map.setCenter(this.startSeacrh);
this.positionPicker.start(this.startSeacrh); //启动这句控制 地图出现一个maker点,可以移动
// this.positionPicker.stop(); //取消移动的maker
this.map.setZoom(15);
// 添加自定义弹窗
// this.addDialog(this.insureAdress);
},
addDialog(address){
this.map.setCenter(this.startSeacrh);
this.marker.content = address;
this.marker.on('click', this.markerClick);
this.marker.emit('click', {target: this.marker});
},
markerClick(e){
let infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -30)});
infoWindow.setContent(e.target.content);
infoWindow.open(this.map, e.target.getPosition());
},
insureMapAdress() {
//确定地址
this.positionVal = this.insureAdress;
this.dialogVisible = false;
this.MapAdress = "";
this.insureAdress = "";
this.insureAdress2 = "";
this.positionPicker.stop(); //取消移动的maker
},
maplocal(address) {
//地理逆编码
this.geocoder.getLocation(address, (status, result) => {
console.log(address);
if (status === "complete" && result.geocodes.length) {
console.log(result);
const lnglat = result.geocodes[0].location;
const lat = lnglat.lat;
const lng = lnglat.lng;
that.mapinit(lat, lng); //tips:使用地理逆编码,此时解析出的经纬度位置也应逆换
} else {
console.log(result);
}
});
},
handleOpen(){
this.dialogVisible = true;
this.loadmap();
},
handleClose(){
this.dialogVisible = false;
this.MapAdress = "";
this.insureAdress = "";
this.insureAdress2 = "";
this.positionPicker.stop(); //取消移动的maker
}
},
};
</script>
<style scoped>
.mapContent{
/* position: absolute;
left:0;
top:0;
width:100%; */
height:460px;
}
#all {
position: relative;
}
#allmap {
width: 100%;
height: calc(100% - 50px);
font-family: "微软雅黑";
}
.posInput {
position: absolute;
z-index: 1;
width: 80%;
margin-top: 20px;
margin-left: 10%;
}
::v-deep .el-form-item {
margin-bottom: 0 !important;
}
.btn_box{
display: flex;
}
/* 去除高德水印 */
::v-deep .amap-logo {
display: none;
opacity: 0 !important;
}
::v-deep .amap-copyright {
opacity: 0;
}
.wrapper{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgb(0 0 0 / 30%);
}
.mapcontainer{
position: absolute;
left:50%;
top:50%;
width:80%;
height:460px;
transform: translate(-50%,-50%);
background: #fff;
padding:50px;
}
</style>