百度地图范围拖动框选实现

638 阅读3分钟

一:实现效果

地图范围.gif

二:实现方式

范围圆边线半径设置使用百度Api设置,虚线和拖动圆点原生绘制和MapView在 FrameLayout下通过设置margin动态改变在屏幕中位置。

  1. 地图缩放控制 地图定位完成后返回当前经纬度centerLongLat,初始比例尺默认圆直径130dp实际范围3公里计算出每像素代表实际距离多少米,有centerLongLat也有了比例尺可以计算出屏幕左右2边的经纬度。调用百度地图sdk中设置范围Api完成缩放设置,LatLngBounds.Builder(),MapStatusUpdateFactory.newLatLngBounds,BaiduMap.setMapStatus。
  2. 虚线和拖动点位置更新 根据centerLongLat和圆半径距离方向计算出拖动圆点经纬度,调用百度api将经纬度转换成屏幕xy坐标点计算虚线长度,公里显示位置等。
//经纬度获取屏幕坐标
val centerPoint: Point = mBaiduMap?.projection?.toScreenLocation(centerLatLng) as Point
//屏幕坐标获取经纬度
val lanlngFromXy=mBaiduMap?.projection?.fromScreenLocation(centerPoint)
 
  1. 圆绘制及拖动半径变化 圆CircleOptions,边线Stroke。圆点设置OnTouchListener,根据拖动x方向移动距离和比例尺计算出当前圆半径。拖动结束后重新计算比例尺,更新缩放值及地图中心点位置。

三:注意事项

缩放设置200毫秒后再计算虚线和拖动点在屏幕中位置,每次拖动结束后重新计算比例尺,拖动过程中禁用百度地图缩放平移手势。

//旋转
mBaiduMap?.uiSettings?.isRotateGesturesEnabled = false
//俯视
mBaiduMap?.uiSettings?.isOverlookingGesturesEnabled = false
//双击缩放
mBaiduMap?.uiSettings?.setDoubleClickZoomEnabled(false)
mBaiduMap?.uiSettings?.setTwoTouchClickZoomEnabled(false)
//缩放
mBaiduMap?.uiSettings?.isZoomGesturesEnabled
//平移
mBaiduMap?.uiSettings?.isScrollGesturesEnabled

四:IOS实现百度地图等效API

//控制缩放
 BMKCoordinateRegion region = BMKCoordinateRegionMakeWithDistance(self.userLocation.location.coordinate, (_radius/Or)*kScreenWidth, (_radius/Or)*kScreenWidth);
  [self.mapView setRegion:region animated:NO];
//经纬度转屏幕坐标点
 _locationPoint = [self.mapView convertCoordinate:self.userLocation.location.coordinate toPointToView:self.mapView];

五:已知方向距离计算经纬度实现

 /*
  * 大地坐标系资料WGS-84 长半径a=6378137 短半径b=6356752.3142 扁率f=1/298.2572236
  */
  //地球 半长轴
  private const val a = 6378137.0

  //地球 半短轴
  private const val b = 6356752.3142

  /** 扁率f=1/298.2572236  */
  private const val flat = 298.257223563

  /**
   * 计算另一点经纬度
   * @param lon  已知一点的经度
   * @param lat  已知一点的纬度
   * @param brng 已知一点与另一点的方向 正北方0度,正东90度 (角度)
   * @param dist 已知一点与另一点的距离 :米
   */
  fun computerThatLonLat(lon: Double, lat: Double, brng: Double, dist: Double): LatLng {
      // 角度转弧度
      val lat1 = lat * Math.PI / 180
      val lon1 = lon * Math.PI / 180
      val brg = brng * Math.PI / 180

      val f = 1 / flat
      val sb = sin(brg)
      val cb = cos(brg)
      val tu1 = (1 - f) * tan(lat1)
      val cu1 = 1 / sqrt((1 + tu1 * tu1))
      val su1 = tu1 * cu1
      val s2 = atan2(tu1, cb)
      val sa = cu1 * sb
      val csa = 1 - sa * sa
      val us = csa * (a * a - b * b) / (b * b)
      val A = 1 + us / 16384 * (4096 + us * (-768 + us * (320 - 175 * us)))
      val B = us / 1024 * (256 + us * (-128 + us * (74 - 47 * us)))
      var s1 = dist / (b * A)
      var s1p = 2 * Math.PI
      var cs1m = 0.0
      var ss1 = 0.0
      var cs1 = 0.0
      var ds1 = 0.0

      while (abs(s1 - s1p) > 1e-12) {
          cs1m = cos(2 * s2 + s1)
          ss1 = sin(s1)
          cs1 = cos(s1)
          ds1 =
              B * ss1 * (cs1m + B / 4 * (cs1 * (-1 + 2 * cs1m * cs1m) - B / 6 * cs1m * (-3 + 4 * ss1 * ss1) * (-3 + 4 * cs1m * cs1m)))
          s1p = s1
          s1 = dist / (b * A) + ds1
      }

      val t = su1 * ss1 - cu1 * cs1 * cb
      val lat2 = atan2(su1 * cs1 + cu1 * ss1 * cb, (1 - f) * sqrt(sa * sa + t * t))
      val l2 = atan2(ss1 * sb, cu1 * cs1 - su1 * ss1 * cb)
      val c = f / 16 * csa * (4 + f * (4 - 3 * csa))
      val l = l2 - (1 - c) * f * sa * (s1 + c * ss1 * (cs1m + c * cs1 * (-1 + 2 * cs1m * cs1m)))
      val lon2 = lon1 + l
      return LatLng(lat2 * 180 / Math.PI, lon2 * 180 / Math.PI)
  }