百度、google、高德 地图比例尺功能实现(算法&&地图分辨率和zoomlevel之间的关系)

一、什么是比例尺?

比例尺是表示图上距离比实地距离缩小的程度,因此也叫缩尺。用公式表示为:比例尺=图上距离/实地距离。

例如地图上1厘米代表实地距离500千米,可写成:1∶50,000,000或写成:1/50,000,000。

在当前移动端或是web端地图上显示:

baidu   google

图中的公里或英里数会随着黑条宽度的改变而改变,并且它的数值和地图当前区域的地图图层分辨率和缩放等级有关。浅显的来看,拿百度地图举例,百度地图移动端地图缩放等级分为:3-21,也就是19个等级,在同一缩放等级下,无论你移动到世界的每一个角落,比例尺的数值,公里\米 都是一样的。反之,googl地图就不一样,在同一缩放等级下,移动到世界不同的区域,显示的公里\ 英里 数值是不一样的,以赤道为中心,向两级延伸。google真正做到了球形的地球,而百度缩放到世界地图,你会看到整个地球是一张纸:

先看看google地图:

以下是百度地图:

二、移动端的实现

大家无论使用ios还是android的,会发现,三个地图api,有的提供了比例尺组件,有的没有,所以,只能我们自己来实现,接下来我就说一下如何实现,以百度地图android版(v2.1.2)为例。

首先简单说一下实现原理:

获取屏幕上两个点的位置坐标(中心点为起点,终点的x坐标为设计的比例尺最宽宽度),通过这两个点的图上坐标转换为真实经纬度,然后使用地图api提供的两点之间真是距离的函数,算出真实距离,即为当前缩放等级下,代表的大概比例尺数值。

2-1,定义一个要显示比例尺数值的数组:

 
  1. public static final int[] SCALE = { 1, 20, 50, 100, 200, 500, 1000, 2000,

  2. 5000, 10000, 20000, 25000, 50000, 100000, 200000, 500000, 1000000,

  3. 2000000, 5000000 };

2-2 在当前地图Activity中实现 MKMapViewListener 接口,覆盖其中的方法,并设置监听:

mMapView.regMapViewListener(mBMapManager, this);
 
  1. @Override

  2. public void onClickMapPoi(MapPoi arg0) {

  3. }

  4. @Override

  5. public void onGetCurrentMap(Bitmap arg0) {

  6. }

 
  1. //当地图完成缩放,移动等动画效果后,回调此方法

  2. @Override

  3. public void onMapAnimationFinish() {

 
  1. showScaleView();

  2. }

  3. @Override

  4. public void onMapMoveFinish() {

  5. }

2-3 声明并实例化组件:

 
  1. protected View mScaleView;

  2. protected int mScaleMaxWidth;

  3. protected int mScaleMaxHeight;

  4. protected TextView mScaleTextView;

  5. protected ImageView mScaleImageView;

 
  1. mScaleView = getLayoutInflater().inflate(R.layout.main_scale, null);

  2. LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,

  3. LayoutParams.WRAP_CONTENT);

  4. layoutParams.setMargins(10, 10, 0, 0);

  5. mScaleView.setLayoutParams(layoutParams);

  6. mScaleTextView = (TextView) mScaleView.findViewById(R.id.scale_text);

  7. mScaleImageView = (ImageView) mScaleView.findViewById(R.id.scale_image);

2-4 main_scale,xml

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:layout_width="wrap_content"

  4. android:layout_height="wrap_content"

  5. android:orientation="vertical" >

  6. <TextView

  7. android:id="@+id/scale_text"

  8. android:layout_width="wrap_content"

  9. android:layout_height="wrap_content"

  10. android:layout_gravity="center"

  11. android:singleLine="true"

  12. android:textColor="@color/text_black" />

  13. <ImageView

  14. android:id="@+id/scale_image"

  15. android:layout_width="match_parent"

  16. android:layout_height="wrap_content"

  17. android:background="@drawable/scale"

  18. android:contentDescription="@null" />

  19. </LinearLayout>

2-5,showScaleView()

 
  1. /** 计算两处经纬度的实际距离并换算成实际比例尺单位 */

  2. public void showScaleView() {

  3. //获取设置默认屏幕宽度480

  4. int default_screen_width = this.getResources()

  5. .getDimensionPixelSize(R.dimen.default_screen_width);

  6. //获取设置默认屏幕高度800

  7. int default_screen_height = this.getResources()

  8. .getDimensionPixelSize(R.dimen.default_screen_height);

  9. //mScaleMaxWidth = 默认屏幕宽度四分之一

  10. mScaleMaxWidth = default_screen_width>>2;

  11. //mScaleMaxHeight = 默认屏幕高度二分之一

  12. mScaleMaxHeight = default_screen_height>>1;

  13. //转换为起点的经纬度GeoPoint

  14. GeoPoint fromGeopoint = mMapView.getProjection().fromPixels(0,

  15. mScaleMaxHeight);

  16. //转换为终点的经纬度GeoPoint

  17. GeoPoint toGeopoint = mMapView.getProjection().fromPixels(

  18. mScaleMaxWidth, mScaleMaxHeight);

  19. //通过getDistance函数得出两点间的真实距离

  20. double distance = DistanceUtil.getDistance(fromGeopoint, toGeopoint);

  21. String discripition = null;

  22. int dis = 0;

  23. int width = 20;

  24. //出于百度地图缩放最小为世界地图时,以纸的形式展现,这里强制规定如果zoomlevel=最高级

  25. //比例尺数值恒定wie:2000公里,黑条宽度恒定为52像素,缩放最大时同样的道理,如果是google

  26. //地图,不需要if和 else if

  27. if (mMapView.getZoomLevel() == 19) {

  28. dis = Constants.SCALE[1];

  29. width = 52;

  30. } else if (mMapView.getZoomLevel() == 3) {

  31. dis = Constants.SCALE[17];

  32. width = 80;

  33. } else {

  34. //真实距离和数组中相近的两个值循环比较,以小值为准,得出规定好的比例尺数值赋值给dis

  35. for (int j = 1; j < Constants.SCALE.length; j++) {

  36. if (Constants.SCALE[j - 1] <= distance

  37. && distance < Constants.SCALE[j]) {

  38. dis = Constants.SCALE[j - 1];

  39. break;

  40. }

  41. }

  42. //比例尺黑条的宽度 =(dis*默认屏幕宽度四分之一)/真实的距离

  43. width = (int) (dis * mScaleMaxWidth / distance);

  44. }

  45. //如果比例尺数值大于1000,则discripition = 2500 km(公里),否则 为 900 m(米)

  46. if (dis >= 1000) {

  47. discripition = dis / 1000 + getString(R.string.units_km);

  48. } else {

  49. discripition = dis + getString(R.string.units_m);

  50. }

  51. //设置TextView组件要显示的比例尺数值

  52. mScaleTextView.setText(discripition);

  53. //设置比例尺黑条ImageView的的长度

  54. android.view.ViewGroup.LayoutParams lp = mScaleImageView

  55. .getLayoutParams();

  56. lp.width = width;

  57. mScaleImageView.setLayoutParams(lp);

  58. }

至此,代码部分就结束了,咱们看一下运行效果

如果你想要实时的动态效果,也就是说双指触控到屏幕(缩放地图)时,(手指未离开)就不断变化比例尺,就不能写在onMapAnimationFinish回调函数内了,因为它不是实时调用,只有当每次动画结束后(双指也离开屏幕了),才会调用;那就覆盖onTouchEvent方法:

 
  1. @Override

  2. public boolean onTouchEvent(MotionEvent arg0) {

  3. showScaleView();

  4. return super.onTouchEvent(arg0);

  5. }

这样,每当手指触摸到屏幕,就会实时调用算法啦。不过看样子cpu应该会很累的。

至于google和高德地图,把showScaleView()写在其地图缩放的回调函数内即可,google的好像是 onCameraChange();

三、结尾

到此,比例尺的功能就被我们自己实现了,这个算法不知道算不算严格的科学,但是至少应该不会差很多,如果谁有同样的兴趣,欢迎和我一起探讨噢。

百度、google、高德 地图比例尺功能实现(算法地图分辨率和zoomlevel之间的关系)相关推荐

  1. 算法时间复杂度与问题规模之间的关系

    [知识点] 算法竞赛中,所设计的算法都有时空限制. 为了做到心中有数,必须预判所设计的算法在给定数据规模的前提下,是否符合要求. 为了达到此目的,必须熟悉算法时间复杂度与问题规模之间的关系. 常见的对 ...

  2. 腾讯、百度、高德、谷歌、天地图地图瓦片

    以下是各地图的瓦片地图地址,可以在QGIS中加载,也可以在openlayer或leaflet前端页面中加载. 腾讯.百度.高德,加上谷歌和天地图应该足够用了.腾讯.高德是GCJ02坐标系,百度是BD0 ...

  3. php 百度转高德经纬度,PHP腾讯地图经纬度转百度地图经纬度

    /** * 中国正常GCJ02坐标---->百度地图BD09坐标 * 腾讯地图用的也是GCJ02坐标 * @param double $lat 纬度 * @param double $lng 经 ...

  4. 数据结构与算法--9.常见时间复杂度及其之间的关系

    文章目录 1.常见时间复杂度 2.常见时间复杂度之间的关系 1.常见时间复杂度 2.常见时间复杂度之间的关系

  5. GPS纠偏算法,适用于google,高德体系的地图

    GPS纠偏算法,适用于google,高德体系的地图,精确度还比较高.我试了一下比高德本身的纠偏还精确点. /*** gps纠偏算法,适用于google,高德体系的地图* @author Adminis ...

  6. 一个可以地址和各种格式的经纬度查询互换的网址,支持百度、高德、Google等地图对比查询。

    最近找到一个可以地址和各种格式的经纬度查询互换的网址,支持百度.高德.Google等地图对比查询. http://www.gpsspg.com/maps.htm

  7. android 通过scheme唤起百度、高德、腾讯地图路线规划功能,唤起滴滴出行打车功能

    import android.content.Context; import android.content.Intent; import android.net.Uri;import java.ut ...

  8. android app调用第三方地图路线规划导航(百度,高德,腾讯)

    android app调用第三方地图路线规划导航(百度,高德,腾讯) 因为直接使用高德的sdk提供的导航被投诉说不准,所以需要接第三方. 把BAT系的地图都接上了,有兄弟找到其他的地图调用方法告诉下小 ...

  9. osgEarth的Rex引擎原理分析(七十九)如何加载百度、高德、谷歌、微软的在线地图

    目标:(七十八)中的问题155 瓦片生成后,就是一堆图片.怎么对这堆图片进行编号,是目前主流互联网地图商分歧最大的地方.总结起来分为四个流派: 谷歌XYZ:Z表示缩放层级,Z=zoom:XY的原点在左 ...

  10. BIGEMAP谷歌(百度、高德)离线地图开发环境搭建

    谷歌(百度.高德)离线地图开发环境搭建 发布时间:2018-01-17 版权: 1.说明 离线地图开发环境支持谷歌地图.百度地图.高德地图等等所有常用地图类型,支持在局域网内的地图部署.二次开发. 2 ...

最新文章

  1. ES transport client使用
  2. python用pywin32库来隐藏windows文件
  3. antd From 中 Form.Item里含有自己封装的组件,获取不到值的解决方法
  4. 使用Adobe Audition生成基本音频
  5. 在windows 2008 R2上安装sharepoint 2013时遇到提示必须安装 .netframeword4.5的处理办法...
  6. Bailian4101 晶矿的个数【DFS】
  7. HTTP请求报文格式与HTTP2.0
  8. VSCode下载安装最新详细教程2022(win10)
  9. matlab积分计算面积,定积分的近似计算(数学实验报告matlab版).doc
  10. Cups打印机驱动延迟Bug解决
  11. Java 架构师是怎样练成的
  12. snapchat为什么_什么是Snapchat?
  13. python求一元二次方程的解
  14. 稀释消费次元壁,华为的移动生活新范式
  15. 架构:常用的三种架构模式
  16. pinpoint监控学习笔记
  17. 数据点太多matlab曲线较粗,matlab数据太多怎么拟合曲线
  18. 用MySQL创建数据库和数据库表(linux终端操作)
  19. 电池_电池容量的测试——手机、电池、充电器三件套之电池篇3
  20. android跳转小程序 bad_param

热门文章

  1. 移动支付走入线下商家
  2. 数据库的第一范式、第二范式、第三范式,BCNF范式
  3. 进销存小程序(一)项目整体功能和设计
  4. JS 阻止键盘输入event.preventDefault 和window.event.returnValue
  5. centos查看内存使用最多_CentOs中查看内存插槽数、最大容量和频率 查看内存插槽数、最大容量和频率...
  6. 设计分享 | STM32F103RCT6利用ULN2003驱动步进电机正反转
  7. 腾讯云申请免费短信验证码
  8. 传奇私服服务器怎么增加npc,传奇添加NPC的方法以及形象代码计算
  9. 制作ppt时如何使logo背景变成透明
  10. 将一个负数赋值给一个无符号数会出现什么情况呢