前言
项目中用到的信息窗体是比较复杂的,复杂在,在地图中,不只有围栏,还有人员,即既有多边形覆盖物,又有点状覆盖物,且每一个覆盖物都有自己的信息窗,不止要展示各自的信息,还有按钮操作,要展示dialog或是跳转页面
本章代码虽然用在vue项目中,但是基本还是参照JS API 示例 来写的,所以会有拼接字符串的操作,比较简单易懂的
后台返回的数据是一个数组对象,所有围栏,人员数据都在一起,且具有层级关系,围栏相关的组,组里相关的人员,想像一下把这一层一层的数据关系捋清楚,再体现在信息窗上。。。总之,功能实现了,花了很多功夫,记录一下
一、代码
以下代码主要涉及,展示多个点标记,给多个点标记添加信息窗体,给信息窗体添加点击事件
代码如下(示例):
<script>
import MapLoader from "@/assets/js/AMap.js";
export default {
data() {
return {
map: null,
marker: null,
lineLists: [],
infoWindow: null,
};
},
mounted() {
this.$nextTick(function () {
let that = this;
that.initData(); //调用初始化请求
MapLoader().then(
(AMap) => {
that.map = new AMap.Map("container", {
zoom: 12,
});
},
(e) => {
console.log("地图加载失败", e);
}
);
});
},
methods: {
// 添加全部点覆盖物
showUserAll() {
var that = this;
var markers = [];
// 因为好几层的数据,所以一直for循环
for (let i = 0; i < that.lineLists.length; i++) {
const listss = that.lineLists[i];
for (let index = 0; index < listss.length; index++) {
const element = that.formatArr(listss[index].dWorkerInfosList);
for (var j = 0, marker; j < element.length; j++) {
var marker = new AMap.Marker({
position: element[j],
map: that.map,
extData: {
item: listss[index].dWorkerInfosList[j],
tips: listss[index].workerGroupName,
},
});
markers.push(marker);
marker.on("click", that.markerClick);
marker.emit("click", { target: that.marker });
}
}
}
// 当有员工没有数据时,点位信息为0,将会定位到非洲,
// 处理:将所有点位信息存到markers中,再删除这些特殊信息,
// 视野定位到当前有效点位上
// 原因是:需要所有点位的i和index,以展示信息窗,所以不能一开始就删除
for (let j = 0; j < markers.length; j++) {
const element = markers[j].getPosition();
if (element.lat == null || element.lat == "" || element.lat == 0) {
markers.splice(j, 1);
j = j - 1;
}
}
// that.map.setFitView(markers);
},
// 点标记点击事件
markerClick(e) {
this.infoWindow = new AMap.InfoWindow({
offset: new AMap.Pixel(0, -35),
content: this.content(e.target.getExtData()), // 覆盖物自定义extData
});
this.infoWindow.open(this.map, e.target.getPosition()); // 在地图的指定位置打开信息窗体
// 在信息弹窗内添加交互事件
// 因为添加到infowindow中的button绑定的是window的全局方法,所以这里需要将组件的局部方法赋值给全局方法。
if (!window.updateUser) {
window.updateUser = this.updateUser;
}
},
// 信息弹窗 content,用的是拼接字符串的方法
content(val) {
var tips = val.tips;
var v = val.item;
var content = `<div class="map_tips">
<div class="map_tips_head">
<div class="m_border">${tips}</div>
<div class="map_tips_head_button">
<button class="btn2" onClick="updateUser(${v.id});"></button>
</div>
</div>
<div class="map_tips_user">
<div class="user_list_one">
<span>小组</span>
<span class="user_list_text">${v.workerName}</span>
</div>
</div></div>`;
return content;
},
// 弹窗的onClick事件
updateUser(id) {
this.editVisible = true;
this.updateId = id;
},
},
};
</script>
二、bug
事件交互
主要参考:信息窗体内的事件交互
包括信息窗体的content用字符串拼接,还有里面的点击事件写法,但是因为我是用在Vue项目里,所以,点击事件不起作用,查了好久的解决方法,最后解决:
if (!window.updateUser) {
window.updateUser = this.updateUser;
}
具体为什么,上述代码里有解释。 这是我翻遍全网得到的解决方法,因为不是所有人都是用拼字符串的方法来写content的,我是全照例子来,其他都写完了,就差点击事件了,不能为了这个全部推翻重写不是
extData
这是覆盖物属性,官方定义是:用户自定义属性,支持JavaScript API任意数据类型,如Marker的id等。利用这个属性,把每个点标记在数据中的index添加进去,这样子,当点击点标记获取信息窗体时,就能通过extData的index,得到这个点标记的数据总结
信息窗体挺麻烦的,初期看遍了JS API 示例,简单的功能有,但是涉及到复杂数据的交互,就略显简单了,翻遍了度娘,找了好多参考,写下了这篇,上述代码是精简过的,只涉及到多个点标记的信息窗,但大致涉及到的功能都有