起因:写了一个软件要地图选点,最初设计时候没有考虑到地图缩小情况下要选的点不在地图上。这样对用户而言要不然要缩小地图,拖动点,放大,再拖点。对用户十分不友好
这个问题在5月份计算机设计大赛的时候被挑刺了,到现在还耿耿于怀
由于高德api没有提供这种场景,ai写的也不能用,只好自己写了
先明确需求:我要拖动点到边框附近的时候自动将地图朝那个方向移动
拆分下来就是:判断是不是在边框附近,以及在哪个方向→通过animateCamera方法移动视图
在判断之前,我们要先获取当前点:
getaMap().setOnMarkerDragListener(new AMap.OnMarkerDragListener()
中强制要求重写了一个方法获取到的maker对象可以得到:
public void onMarkerDrag(Marker marker) {
LatLng newPosition = marker.getPosition();
}
判断是不是在边框附近:
高德提供了一个方法可以获取界面上的边界范围:
LatLngBounds visibleBounds = getaMap().getProjection().getVisibleRegion().latLngBounds;
从这里我们可以得到四个极限方向
double north = visibleBounds.northeast.latitude;
double west = visibleBounds.southwest.longitude;
double south = visibleBounds.southwest.latitude;
double east = visibleBounds.northeast.longitude;
( visibleBounds.northeast与southwest放回到的是一个latlng对象)
有了极限方向,我们就可以计算出当前的点距离边多少距离,有了距离就可以算比例,有了比例就可以判断在不在边框附近了
double totalLength=Math.abs(east-west)/2;
double totalHeight=Math.abs(north-south)/2;
double distanceToNorth=Math.abs(nowLocation.getLatitude() - north);
double distanceToSouth=Math.abs(nowLocation.getLatitude() - south);
double distanceToEast=Math.abs(nowLocation.getLongitude() - east);
double distanceToWest=Math.abs(nowLocation.getLongitude() - west);
我们将问题分为north/south,west/east考虑:
以north/south为例:先判断偏向哪个方向:
if (distanceToNorth<distanceToSouth)
然后再测试比例的百分比,经过测试,个人认为0.2左右合适
判断在0.2范围内就做移动处理,移动尺度测试发现采用hight/length的0.01合适
即:
LatLng target=null;
double moveRate=0.01;
if (distanceToNorth<distanceToSouth){
if (distanceToNorth/totalHeight<0.2){
target = new LatLng(nowLocation.getLatitude() + totalHeight*moveRate, nowLocation.getLongitude());
}
}else {
if (distanceToSouth/totalHeight<0.2){
target = new LatLng(nowLocation.getLatitude() - totalHeight*moveRate, nowLocation.getLongitude());
}
}
最后再移动到这个点:
getaMap().animateCamera(CameraUpdateFactory.newLatLng(target));
另外,要注意对移动逻辑做限制,否则你会发现点一到边界就飞快地朝旁边移动
测试认为0.3s左右合适
全部代码:
public void onMarkerDrag(Marker marker) {
// 用户拖拽标记时的操作
Location nowLocation=editNowLocation(marker);
if(System.currentTimeMillis()-lastEditTime>300){
lastEditTime = System.currentTimeMillis();
LatLngBounds visibleBounds = getaMap().getProjection().getVisibleRegion().latLngBounds;
double north = visibleBounds.northeast.latitude;
double west = visibleBounds.southwest.longitude;
double south = visibleBounds.southwest.latitude;
double east = visibleBounds.northeast.longitude;
double totalLength=Math.abs(east-west)/2;
double totalHeight=Math.abs(north-south)/2;
double distanceToNorth=Math.abs(nowLocation.getLatitude() - north);
double distanceToSouth=Math.abs(nowLocation.getLatitude() - south);
LatLng target=null;
double moveRate=0.01;
if (distanceToNorth<distanceToSouth){
if (distanceToNorth/totalHeight<0.2){
target = new LatLng(nowLocation.getLatitude() + totalHeight*moveRate, nowLocation.getLongitude());
}
}else {
if (distanceToSouth/totalHeight<0.2){
target = new LatLng(nowLocation.getLatitude() - totalHeight*moveRate, nowLocation.getLongitude());
}
}
getaMap().animateCamera(CameraUpdateFactory.newLatLng(target));
double distanceToEast=Math.abs(nowLocation.getLongitude() - east);
double distanceToWest=Math.abs(nowLocation.getLongitude() - west);
if (distanceToEast<distanceToWest){
if (distanceToEast/totalLength<0.2){
target = new LatLng(nowLocation.getLatitude(), nowLocation.getLongitude() + totalLength*moveRate);
}
}else {
if (distanceToWest/totalLength<0.2){
target = new LatLng(nowLocation.getLatitude(), nowLocation.getLongitude() - totalLength*moveRate);
}
}
getaMap().animateCamera(CameraUpdateFactory.newLatLng(target));
}
}