基于openLayerMap标注滑动高亮及diff优化(项目实战)

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都不需要关心.极大的优化了用户体验。最后放上效果实现图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值