微信小程序map地图Marker过多优化

实现原理

map地图能拿到当前地图显示范围和缩放比例,根据当前显示范围排除掉范围之外的marker,再根据缩放比例控制每个marker在一定的范围内只出现1个markers,来控制当前显示区域内marker过多的问题

 <map id="map" longitude="{{center.longitude}}" latitude="{{center.latitude}}" show-location="{{true}}" bindregiοnchange="onRegionChange" ></map>

工具函数


/**
 * 防抖函数
 * @param func
 * @param delay
 * @returns {(function(...[*]): void)|*}
 */
function debounce(func, delay) {
    let timeoutId;

    return function (...args) {
        clearTimeout(timeoutId);

        timeoutId = setTimeout(() => {
            func.apply(this, args);
        }, delay);
    }
}


/**
 * 获取地图区域当前显示范围
 * @param ctx
 * @returns {Promise<{
 *   southwest
 *   northeast
 * }>}
 */
export function getMapRegion(ctx){
  return new Promise((resolve, reject)=>{
    ctx.getRegion({
      success(data){
        resolve(data)
      },
      fail(err){
        reject(err)
      }
    })
  })
}

/**
 * 获取地图当前缩放大小
 * @param ctx
 * @returns {Promise<unknown>}
 */
export function getMapScale(ctx){
  return new Promise((resolve, reject)=>{
    ctx.getScale({
      success(data){
        resolve(data)
      },
      fail(err){
        reject(err)
      }
    })
  })
}
/**
 * 获取地图中心的位置坐标
 * @param ctx
 * @returns {Promise<unknown>}
 */
export function getCenterLocation(ctx){
  return new Promise((resolve, reject)=>{
    ctx.getCenterLocation({
      success(data){
        resolve(data)
      },
      fail(err){
        reject(err)
      }
    })
  })
}

/**
 *  计算两点之间的距离
 * @param lat1
 * @param long1
 * @param lat2
 * @param long2
 * @returns {number}
 */
export function calculateLongitudeDistance(lat1, long1, lat2, long2) {

  const radius = 6371; // 地球半径,单位为千米

  const deltaLatByRad = (lat2 - lat1) * (Math.PI / 180);
  const deltaLongByRad = (long2 - long1) * (Math.PI / 180);

  const a = Math.sin(deltaLatByRad / 2) * Math.sin(deltaLatByRad / 2) +
    Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) *
    Math.sin(deltaLongByRad / 2) * Math.sin(deltaLongByRad / 2);

  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  const distance = parseFloat((radius * c * 1000).toFixed(2));
  // const distance = radius * c;

  return distance;
}

/**
 * 设置两点之间的间距
 * @param scale  当前地图的缩放比例
 * @returns {number}
 */
export function setSpaceBetween(scale) {
  if (scale <= 8) {
    return 6000
  }
  if (scale > 8 && scale <= 9) {
    return 5000
  }

  if (scale > 9 && scale <= 10) {
    return 2500
  }

  if (scale > 10 && scale <= 11) {
    return 1250
  }

  if (scale > 11 && scale <= 12) {
    return 500
  }

  if (scale > 12 && scale <= 13) {
    return 250
  }

  if (scale > 13 && scale <= 14) {
    return 125
  }

  if (scale > 14 && scale <= 15) {
    return 50
  }

  if (scale > 15 && scale <= 16) {
    return 25
  }
  if (scale > 16 && scale <= 17) {
    return 12.5
  }
  if (scale > 17 && scale <= 18) {
    return 0
  }
}


/**
 * 判断当前点是否在范围之内
 * @param point
 * @param region
 * @returns {boolean}
 */
export function pointIsInRange(point,region){
  const range = {
    leftLongitudeLine: region.northeast.longitude,
    rightLongitudeLine: region.southwest.longitude,
    topLatitudeLine:region.northeast.latitude,
    bottomLatitudeLine:region.southwest.latitude,
  }
  return point.latitude >= range.bottomLatitudeLine &&
    point.latitude <= range.topLatitudeLine    &&
    point.longitude <= range.leftLongitudeLine &&
    point.longitude >= range.rightLongitudeLine
}

/**
 * 过滤所有marker标记点,返回符合两点间隔的marker数组
 * @param data
 * @returns {*[]}
 */
export function filterSpaceBetweenPoint(data,scale){
  let result = []
  if (!data.length) return result
  // 默认加载第一个marker
  result.push(data[0])

  for (let i = 1; i <data.length; i++) {
    const item  = data[i]
    // 查看当前的标记点,看限定范围内是否存在其它标记点,有的话舍弃掉,没有则加入
    if(
!result.find(_item=>calculateLongitudeDistance(item.latitude,item.longitude,_item.latitude,_item.longitude)  < setSpaceBetween(scale))
    ){
      result.push(item)
    }
  }
  return result
}

业务代码



onLoad(){
	this.mapContext = wx.createMapContext("map");
},

onRegionChange(e){
	if(e.type==='end'){
	this.updateMarkers()
},

updateMarkers:debounce(async function(data){
	
     if(!this.mapContext){
       return
     }
 	const mapInfo = {
       region:{},
       scale:0,
     }
     const regionRes = await getMapRegion(this._mapContext)
     mapInfo.region = {
       northeast: regionRes.northeast,
       southwest: regionRes.southwest
     }

     const scaleRes = await getMapScale(this._mapContext)
     mapInfo.scale = scaleRes.scale
     console.log('mapInfo:',mapInfo)

	const inRangeMarkers= data..filter(item=>pointIsInRange({
         latitude:item.latitude,
         longitude:item.longitude
       },mapInfo.region))

	const needUpdateMarkers = filterSpaceBetweenPoint(inRangeMarkers,mapInfo.scale)

	this.mapContext.addMarkers({
		markers:needUpdateMarkers
		clear:true
	})

},500)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 微信小程序中,map地图)组件可以显示地图并标注多个地点。标注多个地点的方法如下: 1. 在小程序后台管理中心中,进入“小程序设置”页面,找到“服务设置”菜单,在“开发者设置”中选择“获取经纬度”选项,并填写自己的域名。 2. 在小程序的js文件中,调用API获取当前位置的经纬度,然后在地图上以标志或图标的形式显示出来,例如: wx.getLocation({ type: 'gcj02', success: function(res) { var latitude = res.latitude var longitude = res.longitude wx.openLocation({ latitude: latitude, longitude: longitude, scale: 18 }) } }) 3. 要标注多个地点,在小程序的js文件中使用markers属性添加标记点,例如: Page({ data: { markers: [{ id: 1, latitude: 23.099994, longitude: 113.324520, name: 'T.I.T 创意园' }, { id: 2, latitude: 23.099840, longitude: 113.327529, name: '华南理工大学' }, { id: 3, latitude: 23.110994, longitude: 113.339512, name: '番禺区' }] } }) 4. 在map地图)组件中使用markers属性来展示多个标记点,例如: <map markers="{{markers}}" /> 以上就是微信小程序map组件标注多个地点的方法。通过这种方法,用户可以在小程序中方便地查看多个地点的地理位置,为小程序的使用者提供更便捷的服务。 ### 回答2: 微信小程序中的map组件可以用来标注多个地点。标注地点的方法如下: 1. 在地图上找到第一个要标注的地点,将其坐标记录下来。 2. 在小程序中添加一个map组件,设置其地图的中心坐标为第一个要标注的地点的坐标。 3. 在小程序中添加一个marker(标记)组件,将其坐标设置为第一个要标注的地点的坐标,并设置相应的图标和标记文字。 4. 重复上述步骤,将所有要标注的地点都添加到地图上,每一个地点对应一个marker(标记)组件。 5. 根据需要,可以进一步设置marker(标记)的点击事件,以便让用户查看更多地点信息或进行相关操作。 以上就是在微信小程序中通过map组件标注多个地点的简单方法。需要注意的是,如果要标注的地点较多,可能会对小程序的性能产生一定影响,因此需要合理使用标注功能,避免过多、过于密集的标记。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值