一:实现效果
二:实现方式
范围圆边线半径设置使用百度Api设置,虚线和拖动圆点原生绘制和MapView在 FrameLayout下通过设置margin动态改变在屏幕中位置。
- 地图缩放控制 地图定位完成后返回当前经纬度centerLongLat,初始比例尺默认圆直径130dp实际范围3公里计算出每像素代表实际距离多少米,有centerLongLat也有了比例尺可以计算出屏幕左右2边的经纬度。调用百度地图sdk中设置范围Api完成缩放设置,LatLngBounds.Builder(),MapStatusUpdateFactory.newLatLngBounds,BaiduMap.setMapStatus。
- 虚线和拖动点位置更新 根据centerLongLat和圆半径距离方向计算出拖动圆点经纬度,调用百度api将经纬度转换成屏幕xy坐标点计算虚线长度,公里显示位置等。
//经纬度获取屏幕坐标
val centerPoint: Point = mBaiduMap?.projection?.toScreenLocation(centerLatLng) as Point
//屏幕坐标获取经纬度
val lanlngFromXy=mBaiduMap?.projection?.fromScreenLocation(centerPoint)
- 圆绘制及拖动半径变化 圆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)
}