项目背景:要做一个数据大屏,需要用到地图以及点标记,UI大致是这样:
我是结合vue使用的,vue调用高德地图有一个组件是vue-amap,基于vue2.0和高德地图的
我是后端开发,vue是才上手,没有使用npm安装,整个实现上可能走了一些弯路,下面整理一下实现步骤
1.引入amap的js,将key修改为你的高德key
<script type="text/javascript" src='https://webapi.amap.com/maps?v=1.4.15&key=XXXXXXXXXXXXXXX&plugin=AMap.ToolBar'></script>
2.初始化地图
// 初始化高德地图的 key 和插件
var MapsEvent = window.VueAMap.initAMapApiLoader({
key: '{$mapkey}',
plugin: [
'AMap.Autocomplete', //输入提示插件
'PlaceSearch', 'Scale', 'OverView', 'ToolBar', 'MapType', 'PolyEditor', 'AMap.CircleEditor','MarkerClusterer'],
v: '1.4.4' // 默认高德 sdk 版本为 1.4.4
});
3.页面引入
1.使用3D的话就设置viewMode为3D
2.设置center中心点,一般数据大屏都会默认固定一个中心点,所以不用费心去实时获取当前定位点,直接选个坐标点了写死在页面就行了,或者是把中间点的坐标做成后台动态配置
3.zoom缩放比例根据实际业务
4.el-amap-marker 是点标记
5.el-amap-info-window是信息窗体,不是说每个点标记都要有一个独立的信息窗体,是共用的同一个信息窗体,所以点击每个点标记的时候将信息窗体的内容变化就好了
<el-amap
ref="map"
:vid="'mapDiv2'"
viewMode="3D"
map-style="dark"
:center="center"
:zoom="zoom"
:events="events"
class="amap-demo"
rotateEnable="true"
>
<el-amap-marker v-for="(marker,index) in markers" :position="marker.position" :title="marker.title" :icon="marker.icon" :key="index" :events="marker.events"></el-amap-marker>
<el-amap-info-window
:position="currentWindow.position"
:content="currentWindow.content"
:visible="currentWindow.visible"
:events="currentWindow.events">
</el-amap-info-window>
</el-amap>
4.配置数据
var app = new Vue({
el: '#app',
data: {
center: [112.987526,28.220296],
zoom: 22,
position: [112.987526,28.220296],
icon:'/assets/webimg/location_blue.png',
currentWindow: {
position: [112.987526,28.220296],
content: '内容内容',
events: {},
visible: false
},
events: {
init(o){
o.setMapStyle("amap://styles/bf0b2bdda16d28c16977f0ca38d412fc"); //自定义的高德地图的样式
o.setFeatures(['bg','building','road']); //设置地图里面显示的内容
},
//地图移动的时候关闭信息窗体
mapmove(){
app.currentWindow.visible = false //这里得用”app.~“去调用vue里面的方法,我的vue的对象就是定义的”var app = new Vue({})“
},
//地图缩放的时候关闭信息窗体
zoomchange(){
app.currentWindow.visible = false
},
},
markers: [],
}
mounted(){
this.servicepoint() //调用方法
}
methods:{
//关闭信息窗体
closeWindow(){
this.currentWindow.visible = false
},
//服务网点
servicepoint(){
var that = this;
axios({
method: 'post',
url: '/api/organization/servicepoint',
}).then(function(res){
if(res.data.code == 1){
var data = res.data.data;
var markers = [];
$.each(data,function(k,item){
if(item.longitude && item.latitude){
//三种点标记,设置三种不同的图标
if(item.type == 1){
var icon = '/assets/webimg/location_yellow.png';
}else if(item.type == 2){
var icon = '/assets/webimg/location_blue.png';
}else{
var icon = '/assets/webimg/location_white.png';
}
//定义每个点标记
var marker = {
id:item.id, //自定义,做业务判断
position:[item.longitude,item.latitude], //必填
icon: icon, //必填
title:item.name, //必填
events:{ //events里面定义点标记的事件,比如点击事件
click:()=>{
// alert('click marker');
if(item.type == 1){
//给窗体内容赋值 content内容自定义,这个内容是纯字符串,可以使用原生写法,字符串拼接,但是这里面的所有事件都只能原生,不能使用vue的v-on:事件定义
that.currentWindow = {
visible:true, //窗体显示
position:[item.longitude,item.latitude],
content:'<div class="infowindow">' +
'<div class="title">'+item.name+'</div>' +
'<div class="people">社区负责人:'+item.contact+' '+item.mobile+'</div>'+
'<div class="closeicon" οnclick="closeWindow()"><i class="fa fa-close"></i></div>'+
'</div>',
};
}else if(item.type == 2){
that.currentWindow = {
visible:true,
position:[item.longitude,item.latitude],
content:'<div class="infowindow">' +
'<div class="title">'+item.name+'</div>' +
'<div class="activitytime">活动时间:'+item.service_start+'-'+item.service_end+'</div>'+
'<div class="people">报名人数:'+item.people+'人</div>'+
'<div class="closeicon" οnclick="closeWindow()"><i class="fa fa-close"></i></div>'+
'</div>',
};
}else{
that.currentWindow = {
visible:true,
position:[item.longitude,item.latitude],
content:'<div class="infowindow">' +
'<div class="title">'+item.name+'</div>' +
'<div class="activitytime">求助人:'+item.contact+' '+item.mobile+'</div>'+
'<div class="people">' +
'<div>需要人数:'+item.people+'人</div>'+
'<div class="deal" style="cursor: pointer" οnclick="dealnowouter('+item.id+',2)">立即安排</div>'+
'</div>'+
'<div class="closeicon" οnclick="closeWindow()"><i class="fa fa-close"></i></div>'+
'</div>',
};
}
console.log('clicked marker')
}
},
offset: new AMap.Pixel(-13, -30), //偏移量
clickable:true, //点标记是否可以点击
visible: true, //点标记是否显示
}
if(item.type == 3){
marker.contact = item.contact;
marker.mobile = item.mobile;
marker.address = item.address;
}
//将定义的点赋值到markers中
markers.push(marker);
}
})
that.markers = markers;
that.ismap = true;
}
}).catch(function (error) {
// handle error
console.error(error);
}).then(function () {
// always executed
});
},
}
})
5.信息窗体中的点击事件
//使用原生写法
<script>
//关闭信息窗体
function closeWindow(){
app.closeWindow();
}
</script>
6.需要注意的地方
1.信息窗体自带的关闭按钮,一旦点击,后面再想让信息窗体出现,怎么都不会出现了,所以我换了一种方法实现,自己写了一个关闭按钮,然后自己写点击事件,也就是上文中的closeWindow,然后用jquery的点击去调用vue的点击,也就是app.method去调用vue的方法
2.去掉高德地图点标记、信息窗体的默认样式
.amap-container img {
width: 25px;
height: 34px;
}
//窗体关闭按钮样式
.amap-info-close{
display: none;
}
//去掉窗体的sharp那个小三角形
.bottom-center .amap-info-sharp{
display: none;
}
//定义最外框的窗体样式
.amap-info-content{
width: 400px;
background: rgba(22,46,92,0.7);
border: 2px #2d67c3 solid;
padding: 20px;
}
//然后就是针对content里面内容的样式定义了
.infowindow{
width: 100%;
height: 100%;
position: relative;
}
.infowindow .title{
font-size: 20px;
color: #ffffff;
line-height: 26px;
font-weight: bold;
}
.infowindow .activitytime{
font-size: 16px;
color: rgb(181, 208, 255);
margin: 10px 0 6px 0;
}
.infowindow .people{
font-size: 16px;
color: rgb(181, 208, 255);
display: flex;
align-items: center;
justify-content: space-between;
}
.infowindow .people .deal{
color: #EEEEF1;
font-size: 14px;
background: rgba(206, 90, 96, 0.55);
padding: 3px 6px;
border-radius: 2px;
}
.infowindow .closeicon{
cursor: pointer;
}
.infowindow .closeicon i{
position: absolute;
top: 0;
right: 0;
color: #ffffff;
width: 20px;
height: 20px;
}