3、地图控制:移动地图、缩放地图、获取当前视野范围、地图事件监听

地图控制,说白了就是让地图听你的话。你想让它往哪看,它就往哪看;你想让它放大看细节,它就放大。这一节,我带你把这几个核心操作彻底搞明白。

3.1 移动地图:让地图“走”起来

移动地图,其实就是改变地图的中心点坐标。小程序里,我们用的是 moveToLocationtranslateMap 这两个方法。

moveToLocation 最简单,直接定位到当前用户的经纬度。我早期做外卖项目时,用户一进来就调用这个,地图“嗖”一下定位到用户位置,体验很好。

// 移动到用户当前位置
this.mapCtx.moveToLocation({
  latitude: 39.92,
  longitude: 116.46,
  success: () => {
    console.log('移动成功');
  }
});

translateMap 则更灵活,可以指定一个偏移量。比如你想让地图往东平移100像素,就这么写:

this.mapCtx.translateMap({
  x: 100,  // 水平偏移,单位像素
  y: 0,    // 垂直偏移
  success: () => {
    console.log('平移完成');
  }
});
我的习惯: 移动地图前,先判断一下地图上下文是否存在。不然在页面还没渲染完就调用,会报错。我一般放在 onReady 生命周期里操作。

3.2 缩放地图:看得更远或更细

缩放地图,控制的是 scale 属性。范围是 3 到 20,数字越大,看得越细。

举个例子:3 级能看到整个中国,20 级能看到你家楼下的便利店。我个人做景区导览时,常用 15-18 级,这个范围既能看清路,又不会太碎。

// 设置缩放级别
this.mapCtx.setScale({
  scale: 15,
  duration: 300,  // 动画时长,单位毫秒
  success: () => {
    console.log('缩放成功');
  }
});

还有一种方式,直接调用 zoomInzoomOut

// 放大一级
this.mapCtx.zoomIn();

// 缩小一级
this.mapCtx.zoomOut();
注意: 缩放级别不是越大越好。我曾经在项目中把地图缩放到 20 级,结果用户手机性能差,地图卡得不行。建议根据场景动态调整,别一上来就拉满。

3.3 获取当前视野范围

有时候,你需要知道用户当前看到了地图的哪一块。比如,用户拖动地图后,你想重新加载这个区域内的标记点。

getRegion 方法就能拿到:

this.mapCtx.getRegion({
  success: (res) => {
    const { southwest, northeast } = res;
    console.log('西南角:', southwest.latitude, southwest.longitude);
    console.log('东北角:', northeast.latitude, northeast.longitude);
  }
});

返回的是西南角和东北角的经纬度,说白了就是一个矩形范围。我经常拿这个来做“视野内数据加载”——用户拖到哪,就加载哪里的数据,省流量又高效。

另外,getScale 可以拿到当前的缩放级别:

this.mapCtx.getScale({
  success: (res) => {
    console.log('当前缩放级别:', res.scale);
  }
});

3.4 地图事件监听:让地图“说话”

地图不能光会动,还得会“说话”。用户点击、拖动、缩放,地图都应该能告诉我们。

点击事件(bindtap)

用户点地图上的某个位置,我们拿到经纬度,然后可以做点事,比如添加标记:

<map
  id="myMap"
  bindtap="onMapTap"
/>
onMapTap(e) {
  const { latitude, longitude } = e.detail;
  console.log('点击位置:', latitude, longitude);
  // 在这里添加标记点
}

移动事件(bindregionchange)

用户拖动地图时触发。注意,这个事件会触发两次:开始拖动和结束拖动。我一般只关心结束那次:

<map
  id="myMap"
  bindregionchange="onRegionChange"
/>
onRegionChange(e) {
  if (e.type === 'end') {
    console.log('拖动结束,视野变了');
    // 重新加载数据
  }
}

缩放事件(bindscalechange)

用户双指缩放时触发。同样有开始和结束两个阶段:

onScaleChange(e) {
  const { scale } = e.detail;
  console.log('当前缩放级别:', scale);
  // 根据缩放级别调整标记点的大小
}
避坑指南: 我曾经在 bindregionchange 里直接调接口加载数据,结果用户快速拖动时,接口被调了几十次,页面直接卡死。后来我加了防抖处理,只取最后一次结果,问题就解决了。

3.5 综合示例:一个可交互的地图

把上面这些串起来,就是一个完整的地图控制组件。我贴一个我项目里用过的简化版:

Page({
  data: {
    latitude: 39.92,
    longitude: 116.46,
    scale: 15,
    markers: []
  },

  onReady() {
    this.mapCtx = wx.createMapContext('myMap');
  },

  // 移动到我当前的位置
  goToMyLocation() {
    this.mapCtx.moveToLocation();
  },

  // 放大
  zoomIn() {
    this.mapCtx.zoomIn();
  },

  // 缩小
  zoomOut() {
    this.mapCtx.zoomOut();
  },

  // 点击地图添加标记
  onMapTap(e) {
    const { latitude, longitude } = e.detail;
    this.setData({
      markers: [{
        id: Date.now(),
        latitude,
        longitude,
        title: '新标记'
      }]
    });
  },

  // 视野变化后更新数据
  onRegionChange(e) {
    if (e.type === 'end') {
      this.mapCtx.getRegion({
        success: (res) => {
          console.log('新视野范围:', res);
          // 这里可以加载新区域的数据
        }
      });
    }
  }
});

嗯,到这里,地图控制的核心操作就全了。你想想看,移动、缩放、获取视野、监听事件,这几个能力组合起来,基本能覆盖 90% 的地图交互场景。下一节,我们聊聊怎么在地图上画路线和覆盖物,那才是真正好玩的地方。