百度地图(vue、加载海量点、点聚合)
1. 异步加载百度地图
export default function loadBMap (ak) {
return new Promise((resolve, reject) => {
//聚合API依赖基础库,因此先加载基础库再加载聚合API
asyncLoadBaiduJs(ak)
.then(() => {
// 调用加载第三方组件js公共方法加载其他资源库
// 加载聚合API
// MarkerClusterer_min.js依赖TextIconOverlay.js。因此先加载TextIconOverlay.js
asyncLoadJs('http://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay.js')
.then(() => {
asyncLoadJs('http://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js')
.then(() => {
asyncLoadJs('http://api.map.baidu.com/library/InfoBox/1.2/src/InfoBox_min.js')
.then(() => {
resolve()
return true
})
.catch(err => { reject(err) })
})
.catch(err => { reject(err) })
})
.catch(err => { reject(err) })
})
.catch(err => {
reject(err)
})
})
}
// 加载百度地图基础组件js
export function asyncLoadBaiduJs (ak) {
return new Promise((resolve, reject) => {
if (typeof BMap !== 'undefined') {
resolve(BMap)
return true
}
window.onBMapCallback = function () {
resolve(BMap)
}
let script = document.createElement('script')
script.type = 'text/javascript'
script.src = 'http://api.map.baidu.com/api?v=3.0&ak=' + ak + '&callback='
script.onerror = reject
document.head.appendChild(script)
})
}
// 加载第三方组件js公共方法
export function asyncLoadJs (url) {
return new Promise((resolve, reject) => {
let script = document.createElement('script')
script.type = 'text/javascript'
script.src = url
document.head.appendChild(script)
script.onload = () => {
resolve()
}
script.onerror = reject
})
}
2. 创建地图
import loadBMap from '..../tool/loadBMap.js;
data() {
return : {
pointerAllData: [], // 存放获取的所有的点
allMapData:[], // 存放接口请求的所有的数据
markerClusterer: null // 点聚合
}
}
loadBMap(ak).then( () => {
this.newMap = new BMap.Map('mapContain', {
enableMapClick: false,
maxZoom: 18,
minZoom: 6
});
// 初始化地图实例
this.newMap.enableScrollWheelZoom(true);
let point = new BMap.Point(log, lat);
// 设置中心点
this.newMap.centerAndZoom(point, .zoom);
// 个性化地图(自定义样式)
this.newMap.setMapStyleV2({
styleJson: mapStyleJson
});
// 初始化点聚合
this.markerClusterer = new BMapLib.MarkerClusterer(this.newMap, {markers: this.markers})
// 获取地图上所有点数据
this.getAllData();
})
3.处理获取的数据
思路:将1000个点的数据,以100个或者200个截取,去加载。避免一次加载1000个点,地图加载很慢的效果。
getAllData() {
// 模拟1000个点数据
let resultData= []
for (let i = 0; i < 1000; i++){
let new_point = new BMap.Point(Math.random() * 40 + 85, Math.random() * 30 + 21);
resultData.push(new_point);
}
// 数据分流截取
let partArr = resultData;
// this.cutOutData 截取数据
partArr = this.cutOutData(resultData, 100);
let i = 0;
this.timer = setInterval(() => {
if (i > partArr .length - 1) {
clearInterval(this.timer);
} else {
// 加载海量点方法:
this.addPointCollection(partArr [i])
}
i++
}, 500)
},
// 加载海量点
addPointCollection(partArr) {
this.pointerAllData.push(...partArr);
// 我的思路是 分流截取汇总的点数据 和 接口请求的数据 条数 相同时候,加载海量点
if (this.pointerAllData.length === this.allMapData.length) {
let resultData = [...this.pointerAllData]
if (document.createElement('canvas').getContext) {
// 一顿处理数据(站点图标, 自定义popup样式等)
let myIcon = new BMap.Icon(mapPicUrl, new BMap.Size(28, 32), {
imageSize: new BMap.Size(28, 32),
offset: new BMap.Size(29, 40),
imageOffset: new BMap.Size(0, 1)
})
let marker = new BMap.Marker(pointM, {
icon: myIcon // 设计给的图标
});
// 利用插件 自定义样式,html 是自己画的样式,
// 如果要循环,在html 外面处理好,放入,如_table
let html = `<div>
<p class="mapclass">${v.name}</p>
<table>${_table}</table>
</div>`
let infoBox = new BMapLib.InfoBox(this.map, html, {
offset: new BMap.Size(10, 20),
// enableAutoPan: true,
closeIconMargin: "14px 8px 12px 10px",
closeIconUrl: closeUrl,
enableAutoPan: true,
align: INFOBOX_AT_TOP
});
infoBox.open(marker);
// 官网方法:
let options = {
size: BMAP_POINT_SIZE_BIG,
shape: BMAP_POINT_SHAPE_WATERDROP,
color: '#d340c3'
};
let pointCollection = new BMap.PointCollection(pointerAll, options);
this.newMap.addOverlay(pointCollection); // 添加Overlay
// 点聚合方法:
this.markers = 【处理好的数据】
this.toAddMarkerClusterer(this.markers)
}
}
},
// 点聚合【和官网方法一样】
toAddMarkerClusterer() {
// 清除聚合点
this.markerClusterer.clearMarkers();
this.markerClusterer.addMarkers(this.markers);
// 修改点聚合的样式
let myStyles = [
{
url: this.iconLocation,
size: new BMap.Size(35, 41),
opt_anchor: [16, 0], // 16
textColor: '#ffffff',
opt_textSize: 10
}
]
this.markerClusterer.setStyles(myStyles);
}
// 分流数据
cutOutData (array, size) {
const length = array.length;
if (!length || !size || size < 1) {
return [];
}
let index = 0; //用来表示切割元素的范围start
let resIndex = 0; //用来递增表示输出数组的下标
let result = new Array(Math.ceil(length / size));
while (index < length) {
result[resIndex++] = array.slice(index, (index += size));
}
return result;
},
// onBMapCallback
// InfoBox ,好像还有 openWindow方法, 或者自定义复杂样式
// 还有,自定义样式,最好自己在页面上画好,js里面创建的时 就便捷多了。
感谢同事们的帮助~,希望自己不断进步!