微信小程序map自定义组件实现

  • Post author:
  • Post category:小程序




效果

实际手机效果不会点击时突然闪一下,气泡弹窗也不会被其他坐标点挡住




图片




子组件WXML

<map
  id="map"
  setting="{{setting}}"
  markers="{{markers}}"
  bindmarkertap="markerTap"
  style="width: 100%; height: 100%;"></map>
  <cover-image wx:if="{{showZoom}}" src="/images/zoom.png" bind:tap="zoomTap" class="zoom-img" />



子组件JS

Component({
  data: {
    markers: [], // 坐标点数据
    tapMarker: {}, // 点击过的坐标点
    setting: {
      scale: 14, // 缩放级别,取值范围为 3-20,默认为 16
      includePoints: [], // 缩放视野以包含所有给定的坐标点
      showLocation: false, // 是否显示带有方向的当前定位点,默认为 false
      showScale: false, // 是否显示比例尺,工具暂不支持,默认为 false
      subKey: '', // 个性化地图使用的key,默认为空
      layerStyle: 1, // 个性化地图配置的 style,不支持动态修改,默认为 1
      enableZoom: true, // 是否支持缩放,默认为 true
      enableScroll: true, // 是否支持拖动,默认为 true
      enableRotate: false, // 是否支持旋转,默认为 false
      showCompass: false, // 显示指南针,默认为 false
      enable3D: false, // 是否展示3D楼块(工具暂不支持),默认为 false
      enableOverlooking: false, // 是否开启俯视,默认为 false
      enableSatellite: false, // 是否开启卫星图,默认为 false
      enableTraffic: false, // 是否开启实时路况,默认为 false
    }
  },
  properties: {
    // 父组件传入的坐标点数组
    markerList: {
      type: Array,
      value: []
    },
    // 父组件没有传值的情况下默认地图中心定位坐标点:北京
    loglat: {
      type: Object,
      value: {
        latitude: 39.904469, // 地图中心纬度
        longitude: 116.398087 // 地图中心经度
      }
    },
    // 显示右上角定位按钮
    showZoom: {
      type: Boolean,
      value: true
    },
  },
  // 监听坐标点数组
  observers: {
    'markerList' (val) {
      this.initMap()
    }
  },
  /**
  * 组件在视图层布局完成后执行
  */
  ready() {

  },
  methods: {
    // 获取 MapContext 对象,这里封装到方法里方便使用
    getMapCtx() {
      if (this.mapCtx) {
        return this.mapCtx
      }
      // 创建 map 上下文 MapContext 对象
      this.mapCtx = wx.createMapContext('map', this)
      return this.mapCtx
    },
    // 初始化地图
    initMap() {
      const { tapMarker } = this.data
      this.resetMarkers(tapMarker, true)
    },
    // 处理父组件传进来的数据
    resetMarkers(tapMarker, initFlag = false) {
      const { markerList } = this.data
      const newList = markerList.map((item) => {
        let obj = {
          ...item,
          width: 28, // 标注图标宽度
          height: 28, // 标注图标高度
          // 显示的图标,项目目录下的图片路径,支持网络路径、本地路径、代码包路径
          iconPath: '/images/location.png', 
          // 在这里先设置一个气泡背景色和字体色,可以避免点击坐标点显示气泡弹窗时的闪现变色
          callout: {
            color: '#fff', // 气泡文本的颜色
            bgColor: '#ff7732' // 气泡背景色
          }
        }
        // 坐标点上方的气泡窗口,点击哪个坐标点就让哪个标记点显示气泡弹窗
        // 同时隐藏其他坐标点的气泡弹窗
        if(!!tapMarker && tapMarker.id === item.id) {
          obj.zIndex = 9, // 显示层级,解决点击的坐标点被其他坐标点压住的问题
          obj.callout = {
            content: item.title, // 气泡文本
            color: '#fff', // 气泡文本的颜色
            fontSize: 12, // 气泡文本字体大小
            borderRadius: 5, // 气泡边框圆角
            bgColor: '#ff7732', // 气泡背景色
            padding: 8, // 气泡文本边缘留白
            textAlign: 'left', // 气泡文本对齐方式,有效值: left, right, center
            display: "ALWAYS", // 'BYCLICK':点击显示; 'ALWAYS':常显
            anchorX: 0, // 横向偏移量,向右为正数
            anchorY: 2 // 纵向偏移量,向下为正数
          }
        }
        return obj
      })
      // 第一次初始化地图时执行以下代码,点击坐标点时不执行此代码
      if(initFlag) {
        // 如果初始化地图时有数据传入,则展示所有经纬度坐标点,否则将地图中心移置当前定位坐标点
        if(newList.length > 0) {
          const box = this.getBox(newList)
          // includePoints() 缩放视野展示所有经纬度
          this.getMapCtx().includePoints({
            // 坐标点形成的矩形边缘到地图边缘的距离,单位像素。
            // 格式为[上,右,下,左],安卓上只能识别数组第一项,上下左右的padding一致。
            // 开发者工具暂不支持padding参数
            // 防止坐标点溢出
            padding: [40, 40, 40, 40],
            // 要显示在可视区域内的坐标点列表,必填须
            points: [
              { latitude: box.top, longitude: box.left },
              { latitude: box.bottom, longitude: box.right }
            ],
            success: function (res) {
              // console.log(res)
            }
          })
        } else {
          // moveToLocation() 将地图中心移置当前定位坐标点
          this.getMapCtx().moveToLocation(this.data.loglat)
        }
      }
      this.setData({
        markers: newList,
        tapMarker: tapMarker
      })
    },
    // 获取所有坐标点的最大经纬度范围
    getBox(markers) {
      let left = null
      let right = null
      let top = null
      let bottom = null
      markers.forEach((item) => {
        if (!item.longitude || !item.latitude) {
          return
        }
        if (!left) {
          left = item.longitude
        }
        if (!right) {
          right = item.longitude
        }
        if (!top) {
          top = item.latitude
        }
        if (!bottom) {
          bottom = item.latitude
        }
        left = Math.min(left, item.longitude)
        right = Math.max(right, item.longitude)
        top = Math.max(top, item.latitude)
        bottom = Math.min(bottom, item.latitude)
      })
      return { left, right, top, bottom }
    },
    // 点击定位到初始中心坐标位置
    zoomTap (e) {
      const { markerList } = this.data
      if (markerList.length > 0) {
        const box = this.getBox(markerList)
        // includePoints() 缩放视野展示所有经纬度
        this.getMapCtx().includePoints({
          // 坐标点形成的矩形边缘到地图边缘的距离,单位像素。
          // 格式为[上,右,下,左],安卓上只能识别数组第一项,上下左右的padding一致。
          // 开发者工具暂不支持padding参数
          // 防止坐标点溢出
          padding: [40, 40, 40, 40],
          // 要显示在可视区域内的坐标点列表,必填须
          points: [
            { latitude: box.top, longitude: box.left },
            { latitude: box.bottom, longitude: box.right }
          ],
          success: function (res) {
            // console.log(res)
          }
        })
      } else {
        // moveToLocation() 将地图中心移置当前定位点
        this.getMapCtx().moveToLocation(this.data.loglat)
      }
    },
    // 点击坐标点时触发,e.detail = {markerId}
    markerTap(e) {
      const that = this
      const { tapMarker, markerList } = this.data
      const markerId = e.detail.markerId
      const marker = markerList.find((item) => item.id === markerId)
      if (!marker) {
        return
      }
      // 首次点击显示气泡弹窗,二次点击触发自定义点击事件
      if (tapMarker && tapMarker.id === marker.id) {
        this.triggerEvent('markerTap', tapMarker)
        return
      }
      // getRegion() 获取当前地图的视野范围
      this.getMapCtx().getRegion({
        success: function(res) {
          that.resetMarkers(marker) // 调用地图初始化方法,点击坐标点时显示气泡弹窗
        }
      })
    }
  }
})



子组件JSON

{
  "component": true,
  "usingComponents": {}
}



子组件WXSS

.zoom-img {
  width: 80rpx;
  height: 80rpx;
  position: absolute;
  right: 12rpx;
  top: 20rpx;
}



父组件WXML

<view class="container">
  <view class="map">
    <custom-map loglat="{{loglat}}" markerList="{{markerList}}" bind:markerTap="markerTap"></custom-map>
  </view>
</view>



父组件JS

Page({
  data: {
    markerList: [
      {
        id: 1,
        title: '深圳市民中心',
        latitude: 22.543689,
        longitude: 114.059626
      },
      {
        id: 2,
        title: '深圳站',
        latitude: 22.531680,
        longitude: 114.117209
      },
      {
        id: 3,
        title: '深圳北站',
        latitude: 22.609581,
        longitude: 114.029225
      },
      {
        id: 4,
        title: '深圳西站',
        latitude: 22.527874,
        longitude: 113.907731
      },
      {
        id: 5,
        title: '深圳东站',
        latitude: 22.602148,
        longitude: 114.120102
      },
      {
        id: 6,
        title: '福田站',
        latitude: 22.538122,
        longitude: 114.057241
      },
      {
        id: 7,
        title: '坂田站',
        latitude: 22.624926,
        longitude: 114.053187
      },
      {
        id: 8,
        title: '福田区人民政府',
        latitude: 22.521078,
        longitude: 114.054110
      },
      {
        id: 9,
        title: '南山区人民政府',
        latitude: 22.533109,
        longitude: 113.930547
      },
      {
        id: 10,
        title: '宝安区人民政府',
        latitude: 22.554999,
        longitude: 113.883805
      },
      {
        id: 11,
        title: '罗湖区人民政府',
        latitude: 22.548306,
        longitude: 114.131747
      }
    ], 
    // 地图中心定位坐标点
    loglat: {
      latitude: 22.556416, // 地图中心纬度
      longitude: 114.049144 // 地图中心经度
    }
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    
  },
  // 点击地图坐标点触发此方法
  markerTap(e) {
    const { title } = e.detail
    wx.showToast({
      title: title,
      icon: 'none',
      duration: 1600
    })
  }
})



父组件JSON

{
  "navigationBarTitleText": "搜索",
  "usingComponents": {
    "custom-map": "../../components/custom-map/index"
  }
}



父组件WXSS

page {
  background: #fff;
}
.container {
  width: 100%;
}
.map {
  width: 100%;
  height: 600rpx;
  position: relative;
}



版权声明:本文为fu983531588原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。