1:准备工作
在标注数据高达几十万条甚至更多的情况下,如果一次性全部加载出来我相信连开发openLayer的作者也做不到,基于这个条件下,我们需要对标注进行异步加载,笔者这里使用的是范围加载,通过把范围数据传递给后端,在由后端返回过滤后的结果,当然返回的数量也是有限的,我的建议是在10-100之间,超过这个数量地图会变的肉眼可见的卡顿
2: 业务实现
createLabel(pointData) {
let that = this
this.source.forEachFeature((e) => this.source.removeFeature(e));
if (that.layer) {
that.map.removeLayer(that.layer);
}
pointData.map(i => {
let markerimg = that.markerBase64.filter(j => j.name === i.iconName)[0].img
// 初始化标签要素
let feature = new Feature({
geometry: new Point(fromLonLat(i.iconLocation)), // 标签位置
name: i.sight, // 标注显示的文字
img: markerimg, // 标注显示的logo图片
drag: i.sight == '' ? true : false
})
feature.setId(i.id) // 设置ID
if (i.id == this.highlightId) {
feature.setStyle(this.createHighlightStyle(feature)) // 设置高亮样式
} else {
feature.setStyle(this.createLabelStyle(feature)) // 设置标注样式
}
this.source.addFeature(feature) // 将标签要素添加至矢量数据源
})
that.layer = new VectorLayer({ // 创建矢量图层
source: this.source
})
that.map.addLayer(that.layer) // 将矢量图层添加至地图
this.map.on('click', (e) => {
// // 获取点击的标注
let features = this.map.forEachFeatureAtPixel(e.pixel, function(feature, layerVetor) {
return feature
})
let that = this
// 判断是否点击到了标注点
console.log('that.isClick', this.isClick)
if (features && !this.draw && !this.isClick) {
// 向父组件传参
this.isClick = true
UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {
cid: this._$id,
method: 'handelmarker',
args: {
id: features.id_,
bool: false
}
})
}
})
},
样式可以自定义为自己想要的样式,这里用到了比较暴力解决的方案,在滑动轮播图后删除所有的标注,然后在根据是否为高亮点在分别给元素设置样式,最后统一加入到图层里面。在数量小的时候可能差异不是很明显,但在数据量超过20条的时候每次滑动轮播图会有肉眼可见的卡顿感,非常影响用户的体验,尤其是在用户自身的性能不好的情况下尤为明显。
3:持续优化
createLabel(pointData,oldHighlightId) {
let that = this
if (that.layer) {
that.map.removeLayer(that.layer);
}
let feature = this.source.getFeatureById(this.highlightId)
if (feature) {
this.source.removeFeature(feature)
if (oldHighlightId !== undefined) {
let features = this.source.getFeatureById(oldHighlightId)
this.source.removeFeature(features)
}
} else {
this.source.forEachFeature((e) => this.source.removeFeature(e));
}
pointData.map(i => {
let markerimg = that.markerBase64.filter(j => j.name === i.iconName)[0].img
// 初始化标签要素
let feature = new Feature({
geometry: new Point(fromLonLat(i.iconLocation)), // 标签位置
name: i.sight, // 标注显示的文字
img: markerimg, // 标注显示的logo图片
drag: i.sight == '' ? true : false
})
feature.setId(i.id) // 设置ID
if (i.id == this.highlightId) {
feature.setStyle(this.createHighlightStyle(feature)) // 设置高亮样式
this.source.addFeature(feature)
} else if (!this.highlightId) {
feature.setStyle(this.createLabelStyle(feature)) // 设置标注样式
this.source.addFeature(feature) // 将标签要素添加至矢量数据源
} else if (i.id == oldHighlightId && oldHighlightId !== undefined) {
feature.setStyle(this.createLabelStyle(feature)) // 设置标注样式
this.source.addFeature(feature) // 将标签要素添加至矢量数据源
}
})
that.layer.setSource(this.source);
that.map.addLayer(that.layer) // 将矢量图层添加至地图
this.map.on('click', (e) => {
// // 获取点击的标注
let features = this.map.forEachFeatureAtPixel(e.pixel, function(feature, layerVetor) {
return feature
})
let that = this
// 判断是否点击到了标注点
console.log('that.isClick', this.isClick)
if (features && !this.draw && !this.isClick) {
// 向父组件传参
this.isClick = true
UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {
cid: this._$id,
method: 'handelmarker',
args: {
id: features.id_,
bool: false
}
})
}
})
},
这里我们只考虑高亮的节点和上一个高亮的节点,通过对比可以只进行着两个节点的删除和渲染的工作,无论你后续的轮播图节点是20还是50甚至100都不需要关心.极大的优化了用户体验。最后放上效果实现图。