项目场景:
实现百度地图工具栏–标记功能。包括点标记和手绘路线测距。
百度地图链接
解决方案:
引用高德地图和使用到的插件
index.html
<script type="text/javascript">
window._AMapSecurityConfig = {
//您的code
securityJsCode: '',
}
</script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=您申请的key值&plugin=AMap.Geocoder,AMap.RangingTool"></script>
vue2文件
<template>
<div class="mapWrap">
<div id="wMap" @click="handleClickBtn"></div>
<div class="mouseToolWrap">
<div v-for="(item,index) in tools" @click="changeTool(index)" class="tool">
<img :src=" curTool == index+1 ? require(`@/assets/img/${item.icon}1.png`): require(`@/assets/img/${item.icon}.png`)" alt="">
<span :style="{color:curTool == index+1 ? '#3988FB':'#3d3d3d'}">{{ item.name }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: '',
components: {},
data() {
return {
map: null, // 地图
curTool: 1, // 选中工具
tools: [
{ icon: 'cj', name: '测距' },
{ icon: 'bj', name: '标记' },
],
distanceTool: null, // 打分
geocoder: null, // 地理编码
iconlist: [
{
url: require(`@/assets/img/img1.png`),
offset: new AMap.Pixel(-20, 20),
size: new AMap.Size(34, 46),
},
{
url: require(`@/assets/img/img2.png`),
offset: new AMap.Pixel(17, 23),
size: new AMap.Size(34, 46),
},
{
url: require(`@/assets/img/img3.png`),
offset: new AMap.Pixel(17, 23),
size: new AMap.Size(34, 46),
},
{
url: require(`@/assets/img/img4.png`),
offset: new AMap.Pixel(17, 23),
size: new AMap.Size(34, 46),
},
],
showIcon: false, // 展示图标列表
infoWindow: null, // 窗体
curMark: null, // 当前鼠标打点
curMarkInfo: { // 当前鼠标打点点位信息
lnglat: '',
icon: '',
addr: ''
},
markers: [], // 打点列表
polylines: [], // 测距列表
delArr: []
}
},
created() { },
mounted() {
this.initMap()
if (this.curTool == 2) {
this.cancelRangingTool()
} else if (this.curTool == 1) {
this.drawRangingTool()
}
},
methods: {
changeTool(index) {
if (this.curMarkInfo.lnglat !== '') {
this.saveMarkInfo()
}
this.curTool = index + 1
},
// 地图和窗体初始化并监听
initMap() {
this.map = new AMap.Map('wMap', {
center: [116.40285,39.900912],
zoom: 15,
pitch: 50, // 俯仰角度
resizeEnable: true, // 是否监控地图容器尺寸变化
viewMode: "3D",
features: ["bg", "road", "point", "building"]
})
this.map.on('click', (e) => {
if (this.curMarkInfo.lnglat == '' && this.curTool == 2) {
// 点标记
this.drawPoint(e)
this.curTool = 0
} else if (this.curMarkInfo.lnglat !== '') {
// 保存,同 saveMark 事件
this.saveMarkInfo()
} else {
this.infoWindow.close()
}
})
this.infoWindow = new AMap.InfoWindow({
offset: new AMap.Pixel(0, -46),
autoMove: false
})
this.infoWindow.on('close', () => {
this.saveMarkInfo(true)
})
},
// 清空地图
clearAll() {
this.map.clearMap()
this.markers = []
this.curMarkInfo.lnglat = ''
this.curMarkInfo.icon = ''
this.curMarkInfo.addr = ''
},
// 窗体点击事件
handleClickBtn(e) {
// 保存
if (e.target.dataset.event == "saveMark") {
this.saveMarkInfo()
// 删除
} else if (e.target.dataset.event == "delMark") {
this.markers = this.markers.filter(i => i._amap_id != this.curMark._amap_id)
this.map.remove(this.curMark)
this.infoWindow.close()
// 更换窗体页面
} else if (e.target.dataset.event == "isShowIcon") {
this.showIcon = !this.showIcon
this.drawInfo()
} else if (e.target.dataset.event == "choseIcon") {
this.curMark.setIcon(this.iconlist[Number(e.target.dataset.chosedicon)].url)
this.markers.find(i => i._amap_id == this.curMark._amap_id).icon = Number(e.target.dataset.chosedicon)
this.showIcon = false
this.curMarkInfo.icon = Number(e.target.dataset.chosedicon)
this.drawInfo()
}
},
// 测距
drawRangingTool() {
this.distanceTool = new AMap.RangingTool(this.map)
this.distanceTool.turnOn()
this.distanceTool.on('addnode', ({ marker, positon, type }) => {
this.curTool = 0
})
this.distanceTool.on('removenode', ({ target, polyline, points, distance }) => {
console.log('target', target);
console.log('polyline', polyline);
console.log('points', points);
console.log('distance', distance);
})
this.distanceTool.on('end', ({ target, polyline, points, distance }) => {
this.cancelRangingTool()
polyline.onlyid = this.polylines.length
this.polylines.push(polyline)
// 删除事件(官网没有)
this.delArr = document.getElementsByClassName('delimg');
this.delArr[this.delArr.length - 1].setAttribute("curindex", this.delArr.length - 1)
this.delArr[this.delArr.length - 1].addEventListener('click', (e) => this.getCurImg(e))
})
},
getCurImg(e) {
this.polylines.splice(Number(e.target.getAttribute("curindex")), 1)
},
// 保存点位
saveMarkInfo(notClose) {
if (!notClose && this.infoWindow.getIsOpen()) {
this.infoWindow.close()
}
if (this.curMarkInfo.lnglat !== '') {
this.markers.forEach((i, index) => {
let obj = JSON.parse(JSON.stringify(this.curMarkInfo))
if (!i.addr) {
i.addr = obj.addr
i.icon = obj.icon
i.lnglat = obj.lnglat
i.setLabel({
content: obj.addr, //设置文本标注内容
});
} else {
i.setLabel({
content: i.addr
})
}
// 确保每一个点只有一次点击事件
if (index == this.markers.length - 1 && i.uniqueId == undefined) {
i.uniqueId = index
i.on('click', (e) => {
this.getClick(e)
})
}
})
this.curMarkInfo.lnglat = ''
this.curMarkInfo.icon = ''
this.curMarkInfo.addr = ''
}
},
// 点的点击事件
getClick(e) {
if (e.originEvent.target.getAttribute("class") == 'amap-marker-label') {
if (this.infoWindow.getIsOpen()) {
// 保存其他点位的信息
if (this.markers[this.markers.length - 1].uniqueId) {
this.markers.forEach(i => {
i.setLabel({
content: i.addr
})
})
} else {
this.saveMarkInfo()
}
}
this.curMark = e.target
this.curMarkInfo =
{
addr: e.target.addr,
icon: e.target.icon,
lnglat: e.target.lnglat
}
this.showIcon = false
this.curMark.setLabel({ content: '' })
this.drawInfo(true)
}
},
// 关闭测距
cancelRangingTool() {
if (this.distanceTool) {
this.distanceTool.turnOff(false)
this.distanceTool = null
}
},
// 画点
drawPoint(e) {
this.curMark = new AMap.Marker({
position: e.lnglat,
icon: this.iconlist[0].url,
offset: new AMap.Pixel(-17, -40),
});
this.curMarkInfo.lnglat = e.lnglat
this.regeoCode(e.lnglat)
this.markers.push(this.curMark);
this.map.add(this.markers);
},
// 窗体
drawInfo(setLocation) {
var _html = "";
let iconhtml =
`${this.iconlist.map((item, index) => {
return `<img class="icons" src="${item.url}" data-event="choseIcon" data-chosedIcon=${index}></img>`
}).join('')
}`
_html =
`<div class="mouseMarker-wrap">` +
`<div class="mouseMarker-topTitle">添加标记</div>` +
(!this.showIcon ?
(`<div class="mouseMarker-bottomWrap" >` +
`<div class="mouseMarker-leftPart">` +
`<div class="mouseMarker-location">${this.curMarkInfo.addr}</div>` +
`<div class="mouseMarker-btns">` +
`<div data-event="saveMark">保存</div>` +
`<div data-event="delMark">删除</div>` +
`</div>` +
`</div>` +
`<div class="mouseMarker-rightPart" >` +
`<img src="${this.curMarkInfo.icon ? this.iconlist[this.curMarkInfo.icon].url : this.iconlist[0].url}" alt="" data-event="isShowIcon" >` +
`<div data-event="isShowIcon" }>更换</div>` +
`</div>` +
`</div>`) :
(
`<div class="mouseMarker-iconWrap" >` +
iconhtml +
`</div>`
)
) +
`</div>`;
this.infoWindow.setContent(_html);
// 在地图上打开信息窗体
if (setLocation) {
this.infoWindow.open(this.map, this.curMarkInfo.lnglat);
}
},
// 逆地理解码
regeoCode(lnglat) {
if (!this.geocoder) {
this.geocoder = new AMap.Geocoder({
city: "010", //城市设为北京,默认:“全国”
radius: 1000 //范围,默认:500
});
}
this.geocoder.getAddress(lnglat, (status, result) => {
if (status === 'complete' && result.regeocode.formattedAddress) {
this.showIcon = false
this.curMarkInfo.addr = result.regeocode.formattedAddress
this.drawInfo(true)
} else {
this.showIcon = false
this.curMarkInfo.addr = JSON.stringify(result)
this.drawInfo(true)
}
});
}
},
computed: {},
watch: {
curTool: {
handler(newVal, oldVal) {
if (newVal == 2) {
this.cancelRangingTool()
} else if (newVal == 1) {
this.drawRangingTool()
}
}
},
}
}
</script>
<style lang="scss">
#wMap .amap-icon {
overflow: hidden !important;
}
#wMap .amap-info-content {
padding: 0px !important;
border: none !important;
}
#wMap .amap-info-close {
top: 7px !important;
}
#wMap .amap-marker-label {
cursor: pointer;
background-color: rgb(255, 255, 255);
border: 1px solid rgb(128, 128, 128);
padding: 1px 2px;
white-space: nowrap;
font-size: 12px;
color: rgb(51, 51, 51);
}
.mouseMarker-wrap {
width: 345px;
.mouseMarker-topTitle {
width: 100%;
border-bottom: 1px solid #ccc;
height: 31px;
background-color: #f9f9f9;
font-size: 14px;
font-family: Arial, Helvetica, SimSun, sans-serif;
color: #4d4d4d;
padding-left: 11px;
font-weight: 700;
white-space: nowrap;
overflow: hidden;
line-height: 31px;
}
.mouseMarker-iconWrap {
margin: 10px;
display: flex;
justify-content: space-evenly;
.icons {
cursor: pointer;
}
}
.mouseMarker-bottomWrap {
margin: 8px 0 0 11px;
color: #333;
font-size: 12px;
font-family: tahoma, arial, 宋体;
.mouseMarker-leftPart {
width: 285px;
float: left;
.mouseMarker-btns {
display: flex;
justify-content: end;
margin: 8px -1px 15px 0;
div {
width: 46px;
height: 24px;
line-height: 20px;
text-align: center;
padding: 0;
vertical-align: middle;
cursor: pointer;
border: 1px solid #cbcbcb;
border-radius: 2px;
background: -webkit-linear-gradient(top, #fff, #efefef);
background: -o-linear-gradient(top, #fff, #efefef);
background: -moz-linear-gradient(top, #fff, #efefef);
background: -webkit-gradient(
linear,
left top,
left bottom,
from(#fff),
to(#efefef)
);
background: linear-gradient(to bottom, #fff, #efefef);
&:first-of-type {
margin-right: 5px;
}
}
}
}
.mouseMarker-rightPart {
float: left;
width: 32px;
text-align: center;
margin-left: 6px;
cursor: pointer;
img {
width: 20px;
}
div {
color: #4673cc;
text-decoration: underline;
}
}
}
}
</style>
<style scoped lang='scss'>
.mapWrap,
#wMap {
width: 100%;
height: 100%;
position: relative;
}
.mouseToolWrap {
width: 200px;
height: 40px;
position: absolute;
top: 110px;
right: 20px;
background-color: #fff;
display: flex;
align-items: center;
padding: 6px 0;
.tool {
width: calc(calc(100% - 1px) / 2);
height: 100%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
img {
margin-right: 8px;
}
span {
font-family: Source Han Sans, Source Han Sans;
font-weight: 400;
font-size: 14px;
}
&:first-child {
border-right: 1px solid #ebebeb;
img {
width: 16px;
height: 16px;
}
}
&:last-child {
img {
width: 12px;
height: 16px;
}
}
}
}
</style>
问题描述
功能其实还是有不完善的地方,RangingTool测距工具每条路线的删除事件没有。这个只能通过获取删除图片的dom元素处理。还有一个未解决的bug是:当路线只有两个点,随意点击任意一点的移除事件触发RangingTool测距工具的removenode事件,但是没办法确定删除的是哪条路线。
真心觉得难的不是需求,是官方Api不完善,全网找了好多天都找不到解决办法。如果有幸被官方看见,可以完善一下吗?或者有人能把提建议的地址告诉我吗?