vue 高德地图显示一级数据的图标,鼠标移入一级图标,显示标题,单击一级图标放大地图,双击一级图标显示弹窗。
当一级图标放大后显示二级图标,鼠标移入二级图标后弹出显示信息,地图缩小后二级图标移除。
图标根据状态显示不同的图标
演示地址
首先引入高德地图
在vue项目中的index.html中引入高德地图,这里的key需要自己申请。
<script
type="text/javascript"
src="https://webapi.amap.com/maps?v=1.4.15&key=your key&plugin=AMap.Geocoder,AMap.RangingTool,AMap.Heatmap"
></script>
<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
html
使用div用来渲染高德地图
<template>
<div class="maps">
<div ref="allmap" class="mapsMain"></div>
</div>
</template>
高德地图
这里的地图使用的是卫星图,通过路网new AMap.TileLayer.RoadNet()
来让地图上显示地名等信息。
首先准备数据,因为有两种类型的弹窗,为了避免冲突所以我们创建两个方法来处理这两种图标。
一级图标逻辑处理
1.鼠标移入显示标题,我们通过创建给AMap.Marker添加title来实现
2.单击放大地图,我们给图标绑定单击事件双击后,触发单大地图的方法。
3.双击显示详细信息,当双击图标后,我们需要显示一个弹窗来显示详细信息。
二级图标逻辑处理
鼠标移入二级图标后弹窗显示详细信息,鼠标移开后关闭弹窗
当地图缩小后,图标移除。
实例代码
// 创建一级图标
createMarker(location, iconSrc, type, baseName = '') {
var that = this;
// 创建 marker
const marker = new AMap.Marker({
position: location.coordinates,
icon: new AMap.Icon({
size: new AMap.Size(38, 43),
image: location.icon,
imageSize: new AMap.Size(38, 43)
}),
offset: new AMap.Pixel(-19, -21.5),
title: type === 'jidilist' ? baseName : '' // 仅在类型为基地时设置标题
});
// 根据类型定制弹窗内容
let title = '';
let icon = '';
let infoClass = '';
let statusHTML = ''; // 状态信息的HTML字符串
let bodyHTML = ''; // 状态信息的HTML字符串
switch (type) {
case 'jidilist':
title = '基地信息';
icon = icon_jidi2;
infoClass = 'jidilist';
bodyHTML = `<div class="bodyInfo2">
<div class="bodyInfo2l">
<img src="${img}" alt="">
</div>
<div class="bodyInfo2r">
<div class="bodyInfoItem2">
<img src="${dot}" alt="">
<span>基地名称:<em>${location.baseName}</em></span>
</div>
<div class="bodyInfoItem2">
<img src="${dot}" alt="">
<span>位置:<em>${location.address}</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>经纬度:<em>49°15′</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>场景:<em>${location.scene}</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>海拔:<em>29.354002</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>种植面积:<em>${location.demonstrationArea}亩</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>种植作物:<em>${location.specificCrop}</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>联系人:<em>${location.contactPerson}</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>联系电话:<em>${location.contactPhone}</em></span>
</div>
</div>
</div>`
break;
}
const infoWindow = new AMap.InfoWindow({
isCustom: true, // 使用自定义窗口
content: document.createElement('div'), // 创建一个div元素用于内容填充
offset: new AMap.Pixel(0, -40)
});
// 设置内容
const content = document.createElement('div');
content.className = 'gdPopWin' + ' ' + infoClass
content.innerHTML = `
<div class="gdPopWinInner">
<div class="gdPopWinInnerTop">
<div class="gdPopWinInnerTopLeft">
<img src="${icon}" alt="icon" class="gdPopWinIcon" />
<span class="gdPopWinTitle">${title}</span>
${statusHTML} <!-- 这里插入状态 -->
</div>
<div class="gdPopWinInnerTopRight">
<img src="${close}" alt="close" class="gdPopWinClose" />
</div>
</div>
<!-- 这里可以根据需要添加更多的信息 -->
${bodyHTML}
</div>
`;
// 找到关闭按钮,并为其添加点击事件监听器
const closeButton = content.querySelector('.gdPopWinClose');
closeButton.addEventListener('click', function () {
infoWindow.close();
});
// 更新信息窗口内容
infoWindow.setContent(content);
// marker 点击时显示信息窗口
marker.on('dblclick', function () {
infoWindow.open(that.map, marker.getPosition());
});
// // 修改marker的点击事件
if (type === 'jidilist') {
marker.on('click', function () {
// 放大并且居中到该基地
that.map.setZoomAndCenter(15, location.coordinates);
// // 渲染该基地下的车辆和地块
console.log(location.dikuaiList)
location.dikuaiList.forEach((dikuai) => {
that.createMarker2(dikuai, icon_dikuai, 'dikuaiList', location);
});
location.carList.forEach((car) => {
const icon = car.onLine === '在线' ? icon_cheliang : icon_cheliang_lixian;
that.createMarker2(car, icon, 'carList', location);
});
});
}
// 添加 marker 到地图
that.map.add(marker);
},
// 创建二级图标
createMarker2(location, iconSrc, type, data) {
var that = this;
// 创建 marker
const marker = new AMap.Marker({
position: location.coordinates,
icon: new AMap.Icon({
size: new AMap.Size(38, 43),
image: iconSrc,
imageSize: new AMap.Size(38, 43)
}),
offset: new AMap.Pixel(-19, -21.5),
});
that.marker2Array.push(marker);
// 根据类型定制弹窗内容
let title = '';
let icon = '';
let infoClass = '';
let statusHTML = ''; // 状态信息的HTML字符串
let bodyHTML = ''; // 状态信息的HTML字符串
switch (type) {
case 'dikuaiList':
title = '地块信息';
icon = icon_dikuai2;
infoClass = 'dikuaiList';
bodyHTML = `<div class="bodyInfo">
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>作物品种:<em>${data.specificCrop}</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>经纬度:<em>49°15′</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>种植面积:<em>${data.demonstrationArea}亩</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>海拔:<em>29.354002</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>土壤类型:<em>沙土</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>坡度:<em>${data.scene}</em></span>
</div>
<div class="bodyInfoItem2">
<img src="${dot}" alt="">
<span>所属基地:<em>${data.baseName}</em></span>
</div>
<div class="bodyInfoItem2">
<img src="${dot}" alt="">
<span>位置:<em>${data.address}</em></span>
</div>
</div>`
break;
case 'carList':
title = '车辆信息';
icon = icon_cheliang2;
infoClass = location.onLine === '在线' ? 'carlist-online' : 'carlist-offline';
// 根据在线状态动态添加status
console.log(location.onLine)
console.log(1111)
statusHTML = location.onLine === '在线' ?
'<span class="status" style="color: green;">在线</span>' :
'<span class="status2" style="color: grey;">离线</span>';
bodyHTML = `<div class="bodyInfo">
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>车辆类型:<em>耕种机</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>当日作业面积:<em>102亩</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>编号:<em>Y-7-S0208</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>电话:<em>${data.contactPhone}</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>驾驶员:<em>${data.contactPerson}</em></span>
</div>
<div class="bodyInfoItem">
<img src="${dot}" alt="">
<span>无故障作业时间:<em>42分</em></span>
</div>
<div class="bodyInfoItem2">
<img src="${dot}" alt="">
<span>所属基地:<em>${data.baseName}</em></span>
</div>
<div class="bodyInfoItem2">
<img src="${dot}" alt="">
<span>当前位置:<em>${data.address}</em></span>
</div>
</div>
`
break;
}
const infoWindow = new AMap.InfoWindow({
isCustom: true, // 使用自定义窗口
content: document.createElement('div'), // 创建一个div元素用于内容填充
offset: new AMap.Pixel(0, -40)
});
// 设置内容
const content = document.createElement('div');
content.className = 'gdPopWin' + ' ' + infoClass
content.innerHTML = `
<div class="gdPopWinInner">
<div class="gdPopWinInnerTop">
<div class="gdPopWinInnerTopLeft">
<img src="${icon}" alt="icon" class="gdPopWinIcon" />
<span class="gdPopWinTitle">${title}</span>
${statusHTML} <!-- 这里插入状态 -->
</div>
<div class="gdPopWinInnerTopRight">
<img src="${close}" alt="close" class="gdPopWinClose" />
</div>
</div>
<!-- 这里可以根据需要添加更多的信息 -->
${bodyHTML}
</div>
`;
// 找到关闭按钮,并为其添加点击事件监听器
const closeButton = content.querySelector('.gdPopWinClose');
closeButton.addEventListener('click', function () {
infoWindow.close();
});
// 更新信息窗口内容
infoWindow.setContent(content);
// marker 点击时显示信息窗口
marker.on('mouseover', function () {
infoWindow.open(that.map, marker.getPosition());
});
// 添加 mouseout 事件监听器
marker.on('mouseout', function () {
infoWindow.close();
});
// 添加 marker 到地图
that.map.add(marker);
},
// 高德地图相关
getGdMap() {
var that = this;
that.map = new AMap.Map(this.$refs.allmap, {
scrollWheel: true,
viewMode: '2D',
resizeEnable: true,
layers: [ //使用多个图层
new AMap.TileLayer.Satellite(), //使用卫星图
// 路网
new AMap.TileLayer.RoadNet()
],
zoom: 4,
maxZoom: 30,
minZoom: 0,
center: [106.413099, 34.952327],
});
// 渲染基地列表,不立即渲染车辆和地块
this.jidilist.forEach((location) => {
this.createMarker(location, icon_jidi, 'jidilist', location.baseName);
});
// 地图zoom变化事件监听器
this.map.on('zoomend', function() {
var zoom = that.map.getZoom(); // 获取当前地图的zoom等级
if (zoom < 10) {
// 如果zoom等级小于10,移除所有createMarker2创建的markers
that.marker2Array.forEach(function(marker) {
that.map.remove(marker);
});
// 清空存储的marker2的markers数组
that.marker2Array = [];
}
});
},
到这里vue vue3 自定义图标点击放大地图显示子图标移入后显示弹窗效果就完成了。
更多高德地图实例
实例代码下载
项目基于vue3 vite js node.js 16 开发