百度地图实现自定义覆盖物
效果展示
实现目的:
其实这种东西完全可以去用Echars实现,人家做的散点图很方便,但是这不是需要自定义样式了吗,就弄了这个,基本上就是照着人家的写的
人家写的https://www.cnblogs.com/zuobaiquan01/p/9626452.html
但是我觉得他写的不好,不方便别人抄,哈哈哈
缺点:
没有实现点聚合的功能,不能标注下有几个位置
实现方案:
使用的就是 百度地图的覆盖类Overlay
覆盖类Overlay
咋说的这个东西其实慢慢弄就行,但是就是自己的样式有点麻烦,最好的办法就是,照着案例去学,
原生的案例:
链接:https://pan.baidu.com/s/13O8J9a9_xaoD2NmeiLoD1g
提取码:ixnz
复制这段内容后打开百度网盘手机App,操作更方便哦
vue的相关介绍
我是直接写在了一个vue文件里面 方便展示,应该把css 和 js 去拆开写
template里面放入百度地图
<template>
<div class="map">
<!-- <div id="container"></div>-->
<div id="allmap" style="100%; height:calc(100vh - 145px);margin:0 auto;"></div>
</div>
</template>
在script里面的 声明周期里面进行初始化
mounted() {
// // eslint-disable-next-line no-undef
// let map = new BMapGL.Map('container'); // 创建Map实例
// // eslint-disable-next-line no-undef
// map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 12); // 初始化地图,设置中心点坐标和地图级别
// map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放
// eslint-disable-next-line no-undef
let map = new BMap.Map("allmap");
// eslint-disable-next-line no-undef
let point = new BMap.Point(110, 34.5);
map.enableScrollWheelZoom();
map.centerAndZoom(point, 6);
function ComplexCustomOverlay(point, item) {
this._point = point;
this._text = item.name;
this._child = item.id
this._number = item.number
}
// eslint-disable-next-line no-undef
ComplexCustomOverlay.prototype = new BMap.Overlay();
ComplexCustomOverlay.prototype.initialize = function (map) {
let that = this
that._map = map;
let div = that._div = document.createElement("div");
//div.style.zIndex = BMap.Overlay.getZIndex(that._point.lat);
div.setAttribute('data-id', that._child);
div.setAttribute('class', 'map-circle');
div.setAttribute('data-lng', that._point.lng);
div.setAttribute('data-lat', that._point.lat);
let pname = document.createElement("p");
pname.setAttribute('class', 'map-areaname');
pname.appendChild(document.createTextNode(that._text));
div.appendChild(pname);
let pnum = document.createElement("p");
pnum.setAttribute('class', 'map-areanumber');
div.appendChild(pnum);
pnum.appendChild(document.createTextNode(`${that._number}个`));
// div.onmouseover = function(){
// this.style.zIndex = 9999;
// }
// div.onmouseout = function(){
// this.style.zIndex = BMap.Overlay.getZIndex(that._point.lat);
// }
if (that._number == 0) {
let tipspan = document.createElement("span");
tipspan.setAttribute('class', 'map-nodatatips');
tipspan.appendChild(document.createTextNode("暂无数据"));
div.appendChild(tipspan);
let itips = document.createElement("i");
itips.setAttribute('class', 'map-itips');
tipspan.appendChild(itips);
}
div.onclick = function () {
if (that._number == 0) {
return;
}
let curlng=parseInt(div.getAttribute('data-lng'))
let curlat=parseInt(div.getAttribute('data-lat'))
map.clearOverlays();
let point1 = new BMap.Point(curlng,curlat);
// eslint-disable-next-line no-undef
let point1 = new BMap.Point("123", "42");
map.enableScrollWheelZoom();
map.centerAndZoom(point1, 9);
let districtData = [
{"lng": 123.848569, "lat": 42.302504, "name": '西大标准件大全批发商店'},
{"lng": 124.848569, "lat": 42.302504, "name": '测试地点111'},
{"lng": 122.28569, "lat": 42.22504, "name": '测试地点222'},
{"lng": 122.29569, "lat": 42.3504, "name": '测试地点333'}
]
for (let i = 0; i < districtData.length; i++) {
let temp2 = districtData[i]
// eslint-disable-next-line no-undef
let myCompOverlay2 = new ComplexCustomOverlay2(new BMap.Point(temp2.lng, temp2.lat), temp2);
map.addOverlay(myCompOverlay2);
}
}
map.getPanes().labelPane.appendChild(div);
return div;
}
function tiaozhuan(data){
that.openProject(data)
}
ComplexCustomOverlay.prototype.draw = function () {
let map = this._map;
let pixel = map.pointToOverlayPixel(this._point);
this._div.style.left = pixel.x + "px";
this._div.style.top = pixel.y + "px";
}
function ComplexCustomOverlay2(point, item) {
this._point = point;
this._text = item.name;
this._child = item.id;
}
// eslint-disable-next-line no-undef
ComplexCustomOverlay2.prototype = new BMap.Overlay();
ComplexCustomOverlay2.prototype.initialize = function (map) {
this._map = map;
let div2 = this._div2 = document.createElement("a");
// div2.style.zIndex = BMap.Overlay.getZIndex(this._point.lat);
div2.setAttribute('href', `www.baidu.com`);
div2.setAttribute('class', 'circlebox');
div2.setAttribute('target', '_blank');
let div2Child1 = document.createElement("div");
div2Child1.setAttribute('class', 'bg-circle');
div2.appendChild(div2Child1);
let div2Child2 = document.createElement("div");
div2Child2.setAttribute('class', 'sm-circle');
div2.appendChild(div2Child2);
let div2Child3 = document.createElement("div");
div2Child3.setAttribute('class', 'line');
div2.appendChild(div2Child3);
let div2Child4 = document.createElement("div");
div2Child4.setAttribute('class', 'ctx');
div2Child4.setAttribute('title', '点击查看详情');
div2Child4.appendChild(document.createTextNode(this._text));
div2.appendChild(div2Child4);
div2.onmouseover = function () {
div2.setAttribute('class', 'circlebox hoverbox');
}
div2.onmouseout = function () {
div2.setAttribute('class', 'circlebox');
}
map.getPanes().labelPane.appendChild(div2);
return div2;
}
ComplexCustomOverlay2.prototype.draw = function () {
let map2 = this._map;
let pixel2 = map2.pointToOverlayPixel(this._point);
this._div2.style.left = pixel2.x + "px";
this._div2.style.top = pixel2.y + "px";
}
let that = this
//这个是初始化,也就是渲染相关的位置,proviceData 就循环的数据
//{"lng":116.405289,"lat":39.904987,"name":"北京","id":1,"number":123},
// 数据要处理成上边的格式 要不然需要改好多地方
function initMap() {
for (let i = 0; i < that.proviceData.length; i++) {
let temp = that.proviceData[i]
// eslint-disable-next-line no-undef
let myCompOverlay = new ComplexCustomOverlay(new BMap.Point(temp.lng,temp.lat),temp);
map.addOverlay(myCompOverlay);
}
}
initMap()
let scrollFunc = function (e) {
console.log(e)
e = e || window.event;
// let t1=document.getElementById("allmap");
let zommValue = map.getZoom();
if (zommValue < 8) {
map.clearOverlays();
// eslint-disable-next-line no-undef
new BMap.Point(110, 35.2);
map.centerAndZoom(point, 6);
initMap()
}
}
if (document.addEventListener) {
document.addEventListener('DOMMouseScroll', scrollFunc, false);
}
window.onmousewheel = document.onmousewheel = scrollFunc;
}
css在写的时候style 不能加scope 要不然样式加不上
<style>
.map {
100%;
height: 100%;
}
/*引入相关css*/
html,
body,
h1,
h2,
h3,
h4,
h5,
h6,
div,
dl,
dt,
dd,
ul,
ol,
li,
p,
pre,
hr,
table,
caption,
th,
td,
form,
input,
button,
textarea {
margin: 0;
padding: 0
}
table {
border-collapse: collapse;
border-spacing: 0
}
caption,
th {
text-align: left;
font-weight: normal
}
html,
body,
img,
iframe {
border: 0
}
li {
list-style: none
}
textarea {
appearance: none;
resize: none;
overflow: auto;
}
textarea:focus {
border-color: rgba(43, 160, 43, .9) !important
}
u,
s {
text-decoration: none
}
a {
text-decoration: none;
-webkit-transition: color .3s;
-moz-transition: color .3s;
-ms-transition: color .3s;
-o-transition: color .3s;
transition: color .3s
}
a:hover {
text-decoration: none
}
body,
textarea,
input,
button,
select {
/*font: 12px/1.14 arial, 5b8b4f53;*/
color: #333;
outline: 0;
border: 0
}
/* a {
color: #333
} */
.map-circle {
position: absolute;
height: 66px;
66px;
-webkit-border-radius: 50%;
border-radius: 50%;
cursor: pointer;
font-size: 13px;
text-align: center;
color: #fff;
background: rgba(43, 160, 43, .9);
margin-top: -33px;
margin-left: -33px
}
.map-circle:hover {
background: #EE5D5B;
z-index: 99;
}
.map-circle:hover .map-nodatatips {
display: block
}
.map-circle .map-nodatatips {
position: absolute;
top: 50%;
right: -88px;
padding: 0 10px;
margin: -12px 0 0 0;
60px;
cursor: pointer;
white-space: nowrap;
height: 24px;
line-height: 24px;
background: #EE5D5B;
-webkit-border-radius: 2px;
border-radius: 2px;
text-align: center;
color: #fff;
font-size: 12px;
display: none
}
.map-circle .map-nodatatips .map-itips {
position: absolute;
top: 7px;
left: -10px;
0;
height: 0;
border-style: solid;
border- 5px;
border-color: transparent #EE5D5B transparent transparent
}
.map-areaname {
margin-top: 17px;
display: block;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
66px;
white-space: nowrap;
font-size: 12px;
color: #fff
}
.map-areanumber {
margin-top: 6px;
white-space: nowrap;
font-size: 14px;
color: #fff
}
.circlebox {
20px;
height: 20px;
position: relative
}
.circlebox .bg-circle {
position: absolute;
left: -10px;
bottom: -10px;
20px;
height: 20px;
background: #007dd4;
-webkit-border-radius: 50%;
border-radius: 50%;
opacity: .2;
filter: alpha(opacity=20)
}
.circlebox .sm-circle {
6px;
height: 6px;
background: #007dd4;
-webkit-border-radius: 50%;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
margin: -3px 0 0 -3px
}
.circlebox .line {
2px;
height: 18px;
background: #007dd4;
opacity: .6;
filter: alpha(opacity=60);
position: absolute;
bottom: 0;
left: -1px
}
.circlebox .ctx {
display: block;
position: absolute;
top: -42px;
left: 50%;
margin-left: -50px;
min- 80px;
padding: 0 10px;
cursor: pointer;
white-space: nowrap;
height: 24px;
line-height: 24px;
background: #007dd4;
-webkit-border-radius: 12px;
border-radius: 12px;
text-align: center;
color: #fff;
font-size: 12px
}
.circlebox.hoverbox .bg-circle {
background: #EE5D5B;
z-index: 99
}
.circlebox.hoverbox .sm-circle {
background: #EE5D5B;
z-index: 99
}
.circlebox.hoverbox .line {
background: #EE5D5B;
z-index: 99
}
.circlebox.hoverbox .ctx {
background: #EE5D5B;
z-index: 99
}
</style>
提示: 要是使用vue的话 可能有的地方需要修改,Eslint会报语法错误,另外里面的代码我没去加注释,但是写的很清楚,相关事件,都很清楚,直接改就行,还有就是如果需要交互的时候 , 有点地方会出现获取不到值,那就可以进行语法修改 比如function 改成 ()=>{} 等等啥的 有时间我会整理一下,
看不明白的就是去原生的那个案例 慢慢看