MapBox介绍:

MapBox 最初是与 OpenStreetMaps 合作的开源项目,后来开始独立发展。当 Google 开始为地图 API 收费的时候,Mapbox 获得了巨大的发展机会。它的客户曾有 NPR、卫报、绿色和平组织和 FCC ,如今它为 Foursquare、Evernote 等公司提供地图服务。最近,MapBox 开始了一项野心勃勃的计划——构建世界上最漂亮的地图。它有什么秘密武器?Wired 网站采访了公司的高管。

  如果放大观察我们所使用的卫星地图,你可能会发现接缝,地表颜色的突然变化,以及某些非常模糊的区域。这是因为它是由不同来源的图片拼接起来的。对于 MapBox 来说,消灭这些瑕疵是一种使命。

  一直以来,MapBox 的地图使用的是 OpenStreetMap 的矢量数据。但是从 2012 年 12 月开始,在数据分析师 Chris Herwig 的带领下,公司发布了第一版的卫星地图。今年 2 月,MapBox 雇佣了图形专家 Charlie Loyd,以帮助他们完善产品。在加入 Mapbox 之前,Charlie Loyd 已经着手开发制作漂亮卫星图的方法。他在 Twitter 上的一副对比图引起了公司的兴趣,并很快被聘用。

  Mapbox 使用的数据来自 NASA 的 LANCE-MODIS 数据系统。“在新版中,我们处理了两年的图像,这些图像捕获自 2011 年 1 月 1 日到 2012 年 12 月 31 日,”Loyd 说,“这包括了 33900 个 16 万像素的卫星图片,总共超过 5,687,476,224,000 个像素。我们将其缩减到了大概 50 亿个像素”。

  他们用了 30 至 40 个服务器,从 NASA 下载的压缩数据达到 0.6 TB。在此过程中,NASA 很积极的进行了配合。Chris Herwig 对此心存感激,“当提到开放政府的时候,人们谈论的都是 API。但我们真正需要的是政府有保证大规模下载的基础设施。”

  当 Mapbox 获得这些数据后,他们需要处理这些图像,去掉云层、太阳耀光和大气雾霾。通常的做法是,选择某个区域天气最好的时刻,然后将它们拼接,但是这样会使地图上出现接缝。为解决这个问题,Mapbox 采用了特别的方法。他们将某一个地区的所有图片叠加,然后依据清晰度重新排列每一行的像素。“我们处理世界上的每一个像素”,Loyd 说。他们选出最清晰的像素,使其成为地图上的固定像素。这是一项规模庞大的工作。

  除了清晰度之外,Mapbox 还考虑到地层上的颜色。他们用技术确保图片展示的是植物生长最旺盛的时候。“这是完全自然的产品,”Loyd 说,“每个像素都是空中摄像头捕获的真实像素,但它又是完全合成的。”

  他们的目标是,一个理想化的无云层星球,处于永恒的夏季。

  在公司的 CEO Eric Gundersen 看来,这个项目的意义不仅仅是做出漂亮的地图,更重要的是展示了自己快速处理海量数据的能力。这是一个软件公司的优势所在。另外,公司认为,清晰的卫星地图有助科学研究,也对大型的商业公司有帮助。

  目前,Mapbox 拥有 30 名职工,但它有信心与大型的科技公司竞争。Eric Gundersen 说,“我们能够做到这些,依靠的是开源代码和开源数据,我们会从他们那里夺走客户。”

  图片来自 digitaltrends

  转载自ifanr

或许你没有听说过TileMill,但是应该也有了解过Mapbox吧。Mapbox是国外很不错的一个地图制作及分享的一个网站,而TileMill则是他们使用开源软件而制作的一个地图制图及地图发布的软件。国外foursquare,slate等也都有使用他们提供的在线地图服务。而且提供的地图切片服务不光是在网页上,同样也支持在手机及IPad等不同环境下的运行。

TileMill

TileMill是基于 Mapnik, node.js,backbone.js, express and CodeMirror.这几个开源的软件构建起来的,看看开源的东西也还是非常强大的,只是我们很少去愿意使用他们,并不比商业的软件差多少。对其源码构建的可以去github上看看,地址:https://github.com/mapbox/tilemill。Mapnik提供地图的渲染,node.js及backbone.js等提供地图展示,地图配图使用Carto 的语言进行地图各个图层的配图样式等设计,和css很类似,但是比原先的mapnik的xml要方便和可读性要好很多。TileMill主要的功能有如下:

  • 1、支持 ESRI Shapefile, KML, GeoJSON, GeoTIFF, PostGIS, and SQLite数据来源。
  • 2、新版本支持大数据量栅格数据的加载与显示,支持山体阴影,分层设色等功能。
  • 3、支持数据的查询,也就是属性数据的浏览。
  • 4、支持以Carto css样式语言对地图进行配色设计(比xml要方便很多)
  • 5、支持svg图标,truetype字体样式等,基于Mapnik提供(mapnik2.0出来了又强大了不少)
  • 6、支持地图tooltip、图片、图表、utf-8 Grid(不是很了解这个技术)等自定义信息提示
  • 7、支持直接发布到Mapbox,和朋友共享你制作的地图。

制图教程

地图的制图需要制图人员的主观视觉感受去制作,地图的教程在Mapbox网站上已提供,而且很详细,感兴趣想自己制作一幅属于自己的地图可以参照网站的步骤,下载TileMill自己制作。教程地址:http://mapbox.com/tilemill/docs/guides/add-shapefile/ 。相对于ArcGIS等企业级的制图软件来说,TileMill是一个非常不错的平民应用,通过它你可以制作出非常多不错的地图来,是制图人员一个不错的选择。希望能看到更多基于TileMill制作出来的更多美丽的地图。

本文固定链接: http://www.higis.org/2012/05/29/tilemill/ | Hi,GIS

感谢Mapbox,带来了一整套完整的地图方案。

你可以把你的地图放在Mapbox的网站上。也可以使用他们提供的开源软件自己架设地图服务。

Mapbox的地图方案包括web,ios和android。 不过android目前属于不成熟阶段。但是相信很快就会成熟起来。

一个比较舒服的地图自制流程如下:

Qgis 处理各种GIS数据,导出为shp或GeoJson等格式 ==> TileMill 生成 .mbtile ==> tilestream 在线地图服务 或 直接由Android/IOS SDK 渲染地图。

QGIS的使用推荐教程:http://www.qgistutorials.com/en/

TileMill教程:https://www.mapbox.com/tilemill/docs/crashcourse/introduction/

TileStream的资料稍微少些,这里重点讲下。

首先,假设你在TileMill教程中导出的地图文件为abc.mbtile

存放在/Users/fangjian/Documents/MapBox/export

假设你已经安装了nodejs ,然后安装tilestream.

sudo npm install -g tilestream

装好以后启动服务

tilestream --tiles=/Users/fangjian/Documents/MapBox/export

更多设置参见: http://linuxdev.dk/articles/tilestream-openlayers-and-drupal-7

这个时候访问:http://localhost:8888

已经可以看到地图了。点地图图标进入到地图页面后,点“i"图标可以看到这个地图服务的网址。如:http://localhost:8888/v2/abc/{z}/{x}/{y}.png

下面把这个范例拿来用:https://www.mapbox.com/mapbox.js/example/v1.0.0/external-layers/

保存为mapbox.html

其中的网址部分改成:var stamenLayer = L.tileLayer('http://localhost:8888/v2/abc/{z}/{x}/{y}.png'

打开mapbox.html,就可以看到地图了。

如果使用mapbox.js

对应的tilejson为 http://localhost:8888/v2/abc.json

如果想解包为纯静态的图片,用mbutil https://github.com/mapbox/mbutil

sudo easy_install mbutil

mb-util abc.mbtiles abc

abc/metadata.json为tilejson文件

abc/z/x/y.png是瓦片文件

abc/z/x/y.grid.json是UTFGRID文件

进一步了解详见 http://blog.thematicmapping.org/2012/11/exploring-mapbox-stack-mbtiles-tilejson.html

近期,应公司要求,开始接触MapBox For Android的开发。

经过初步的接触,发现MapBox与我之前使用的Arcgis有很多不同,相比起来,MapBox更清洁,更轻便,也更容易使用,但是相对的,MapBox相对于Arcgis缺少了很多的功能实现,许多的东西都需要自己去进行处理才能实现。
下面是我一步步接触并使用MapBox的记录,可能会比较乱。我这里提供了目录的功能, 请不要使用csdn的极客模式,不然看不到目录的,另外,由于是一步步的写下来了,可能前期的看法或者结论,到了后期就不一样了,我会定期修改,但是可能会存在漏网的,欢迎指出。
首先是接入,相比于Arcgis又需要导入包文件,又需要导入lib,又需要设置jcenter,打包下来,直接就几十兆的Apk,一编译就是一分钟。
MapBox只需要导入一下代码即可

[java] view plain copy
  1. compile('com.mapbox.mapboxsdk:mapbox-android-sdk:5.0.2@aar') {
  2. transitive = true
  3. }

哦,对了,还有mavencentral,一般来说,应该都设置了的

[java] view plain copy
  1. allprojects {
  2. repositories {
  3. jcenter()
  4. mavenCentral()
  5. }
  6. }

一般来说,下载一段时间后,就可以了,如果不可以,就试着翻墙,设置代理什么的,这里不细说了。

MapBox和Arcgis相同,在Xml中添加一个MapView就可以了

[html] view plain copy
  1. <com.mapbox.mapboxsdk.maps.MapView
  2. android:id="@+id/mapView"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"/>

如果是从网上,或者demo上学习的朋友,可能会遇到一个问题
就是在xml上无法设置初始坐标,zoom等参数,只能强行写出来,我估计是该控件item的问题。为了更好的学习,我将这些功能都放到了代码中来实现。

申请accessToken

就和arcgis的key类似,就是一个使用凭证,就不多说了,可以去官方网站申请。

进行初始化

申请完毕后,在Activity的onCreate()中添加如下代码,进行初始化

[java] view plain copy
  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. //设置accessToken
  5. Mapbox.getInstance(this, getString(R.string.accessToken));
  6. setContentView(R.layout.activity_simple_map); }

敲黑板,这里的初始化代码一定要放到setContentView之前,否则无法使用。

初始化Mapview

[java] view plain copy
  1. mapView = (MapView) findViewById(R.id.mapView);
  2. mapView.setStyleUrl("mapbox://styles/mapbox/streets-v9");
  3. mapView.onCreate(savedInstanceState);

注意,其中的setStyleUrl,就是设置地图样式,可以采用默认样式,Light,Dark等,也可以使用网络地址,事实上默认的Style.LIGHT也是一个地址

还有下面的

[java] view plain copy
  1. mapView.onCreate(savedInstanceState);

需要在初始化的时候设置,同时,除了onCreate,还包括以下

[java] view plain copy
  1. // Add the mapView lifecycle to the activity's lifecycle methods
  2. @Override
  3. public void onResume() {
  4. super.onResume();
  5. mapView.onResume();
  6. }
  7. @Override
  8. protected void onStart() {
  9. super.onStart();
  10. mapView.onStart();
  11. }
  12. @Override
  13. protected void onStop() {
  14. super.onStop();
  15. mapView.onStop();
  16. }
  17. @Override
  18. public void onPause() {
  19. super.onPause();
  20. mapView.onPause();
  21. }
  22. @Override
  23. public void onLowMemory() {
  24. super.onLowMemory();
  25. mapView.onLowMemory();
  26. }
  27. @Override
  28. protected void onDestroy() {
  29. super.onDestroy();
  30. mapView.onDestroy();
  31. }
  32. @Override
  33. protected void onSaveInstanceState(Bundle outState) {
  34. super.onSaveInstanceState(outState);
  35. mapView.onSaveInstanceState(outState);
  36. }

都要进行设置,建议封装到baseactvity中

异步加载地图

[java] view plain copy
  1. mapView.getMapAsync(new OnMapReadyCallback() {
  2. @Override
  3. public void onMapReady(MapboxMap mapboxMap) {
  4. }
  5. });

该方法即是对地图进行加载,加载成功后,会返回MapboxMap对象,只有有了这个对象,我们才可能对地图进行各种操作,和Arcgis不同,arcgis的大部分操作,都是在mapview上进行操作的,但是MapBox的mapview并没有太多的功能元素,像地图定点、polygon、marker等操作,都得对mapboxmap进行操作,我估计很多朋友都会和我一样,想进行初始化时中心点设置的时候,尝试了centerAt、location、setCenter、setPosition、moveTo、moveCamere。。等等一系列的姿势去设置,都失败了。

更多操作

从上一步开始,地图已经可以跑起来了,下面就是一些进一步的使用,一下排序不分先后,纯粹是我做到哪,写到哪,不过我提供了目录,需要的朋友可以直接在目录中进行搜索,如果是和我一样才开始学习的,可以跟着我的代码一直敲就可以了。

将地图移动到某一点

这个方法有很多

[java] view plain copy
  1. LatLng latLng = new LatLng(29.735281, 106.99155);
  2. mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

最简单的地图定点,是的,没错,这就centerAt的功能

首先我来看前面的方法moveCamera;这个方法就是简单将地图中心定到某个位置,更多的还有

注意,这个LatLng不仅仅可以传入坐标,还可以传入location的

[java] view plain copy
  1. mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(latLng),2000);//动画移动,花费两秒时间,动态的移动到该位置,时间可以不写
  2. mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(latLng),2000);//讲真,我也没发现和其他的有什么区别

然后是后面的参数

后面可以有四种形式

很显然,一个必填,三个可填。
主要呢是必填项CamerUpdate类型的参数,CameraUpdate呢,其实可以当做一个数据处理命令集来使用,即先将要move到的位置的各种参数设置完成,封装好后,再来进行处理。
CameraUpdate的构造需要用到CamaeraUpdateFactory(目前就我了解的话)
CamaeraUpdateFactory专门是用来构建CameraUpdate的,是他的工厂类,我们来看看他的new方法(zoomby,scrollby我没用过。。)
①.newLatLng 根据简单的坐标点来进行构造

这里只需要传入一个坐标参数即可,LatLng,用过Arcgis等地图的都知道,这就是一个坐标,可以用new LatLng(double latitude,double longitude)来进行构造,同下,我们统一用animateCamera来进行举例。

[java] view plain copy
  1. mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(latLng),2000);

②.newCameraPosition 根据CameraPosition来进行构造

这里需要传入的是一个CameraPosition的对象,初始化

[java] view plain copy
  1. CameraPosition cameraPosition = new CameraPosition.Builder()
  2. .target(new LatLng(latLng.getLatitude(), latLng.getLongitude()))
  3. .zoom(17)//放大尺度 从0开始,0即最大比例尺,最大未知,17左右即为街道层级
  4. .bearing(180)//地图旋转,但并不是每次点击都旋转180度,而是相对于正方向180度,即如果已经为相对正方向180度了,就不会进行旋转
  5. .tilt(30)//地图倾斜角度,同上,相对于初始状态(平面)成30度
  6. .build();//创建CameraPosition对象

敲黑板了,注意其中的参数,这几个参数在很多地方都有用到。

[java] view plain copy
  1. mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 2000);

使用就很简单了,大同小异。

③.newLatLngBounds 根据一个坐标坐标边界进行移动,这个有两种方法,除了必传的LatLngBounds,都一样,不一样的就是padding,一种是统一padding,一种是四个方向,这个我就不细细说了,我只说统一padding

[java] view plain copy
  1. LatLngBounds latLngBounds = new LatLngBounds.Builder()//根据坐标集,初始化一个坐标界限
  2. .include(latlng1)
  3. .include(latlng2)
  4. .include(latlng3)
  5. .include(latlng4)
  6. .build();

构造是很简单的,传入坐标点即可,除了include,每次只添加一个点,也可以采用includes,一次传入一个点的集合

[java] view plain copy
  1. mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(latLngBounds,50), 2000);

其中的50指的是padding,使用这种构造,地图会将比例尺自动调节到刚好能显示全部点以及点外面的padding的程度。
④newLatLngZoom 这个和第一个很相似

无非是这个还可以传入一个zoom即缩放尺度的值

[java] view plain copy
  1. mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng,13),2000);

至此,移动的方法就全部用完了。

mapview在fragment中的使用

用过arcgis的可能都知道,mapview在fragment中的使用和在activity中使用其实是一样的,但是在mapbox中,还为fragment提供了另外一种构造方式,

[java] view plain copy
  1. SupportMapFragment。
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_fragment_map);
  6. //设置accessToken
  7. Mapbox.getInstance(this, getString(R.string.accessToken));
  8. }

为了加深记忆,初始化这个再写一次,可能有人发现了,这里我们的getInstance的方法并没有放到setContentView里面,这是我故意的,因为如果mapview要在activity中使用,就必须放在setContentView之前,但是如果在fragment中使用就不需要了。

[java] view plain copy
  1. // Create fragment
  2. final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  3. if (savedInstanceState == null) {
  4. // Build mapboxMap
  5. MapboxMapOptions options = new MapboxMapOptions();
  6. options.styleUrl(Style.LIGHT);
  7. options.camera(new CameraPosition.Builder()
  8. .target(new LatLng(29.735281, 106.99155))
  9. .zoom(13)
  10. .build());
  11. // Create map fragment
  12. mapFragment = SupportMapFragment.newInstance(options);
  13. // Add map fragment to parent container
  14. transaction.add(R.id.container, mapFragment, "com.mapbox.map");
  15. transaction.commit();
  16. } else {
  17. mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag("com.mapbox.map");
  18. }
  19. mapFragment.getMapAsync(new OnMapReadyCallback() {
  20. @Override
  21. public void onMapReady(MapboxMap mapboxMap) {
  22. }
  23. });

以上就是构建的方法,比较长,一句一句的看,首先我再看看xml文件

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. xmlns:tools="http://schemas.android.com/tools"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. android:background="@color/whitesmoke">
  9. <TextView
  10. android:id="@+id/fragment_below_textview"
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:layout_marginTop="8dp"
  14. android:gravity="center_horizontal"
  15. android:text="集成在fragment上的"/>
  16. <android.support.v7.widget.CardView
  17. android:id="@+id/cardview"
  18. android:layout_width="match_parent"
  19. android:layout_height="300dp"
  20. android:layout_below="@id/fragment_below_textview"
  21. android:layout_marginBottom="8dp"
  22. android:layout_marginEnd="8dp"
  23. android:layout_marginLeft="8dp"
  24. android:layout_marginRight="8dp"
  25. android:layout_marginStart="8dp"
  26. android:layout_marginTop="8dp"
  27. app:cardCornerRadius="2dp"
  28. app:cardElevation="@dimen/cardview_default_elevation">
  29. <FrameLayout
  30. android:id="@+id/container"
  31. android:layout_width="match_parent"
  32. android:layout_height="match_parent"/>
  33. </android.support.v7.widget.CardView>
  34. </RelativeLayout>

只需要看其中的container,这个是用来存放fragment的容器,首先创建一个FragmentTranstion对象

[java] view plain copy
  1. final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

再动态实例化地图对象

[java] view plain copy
  1. // Build mapboxMap
  2. MapboxMapOptions options = new MapboxMapOptions();
  3. options.styleUrl(Style.LIGHT);
  4. options.camera(new CameraPosition.Builder()
  5. .target(new LatLng(29.735281, 106.99155))
  6. .zoom(13)
  7. .build());
  8. // Create map fragment
  9. SupportMapFragment mapFragment = SupportMapFragment.newInstance(options);

再次敲个黑板,这里的MapBoxOptions,是用于地图初始化时给地图初始化设置各种参数的。相当于配置文件,这里使用options初始化了SupportMapFragment

,options也可以在activity中进行使用,比如这样

[java] view plain copy
  1. MapboxMapOptions options = new MapboxMapOptions()
  2. .styleUrl(Style.OUTDOORS)
  3. .camera(new CameraPosition.Builder()
  4. .target(new LatLng(43.7383, 7.4094))
  5. .zoom(12)
  6. .build());
  7. // create map
  8. mapView = new MapView(this, options);
  9. mapView.onCreate(savedInstanceState);
  10. mapView.getMapAsync(new OnMapReadyCallback() {
  11. @Override
  12. public void onMapReady(MapboxMap mapboxMap) {
  13. // Customize map with markers, polylines, etc.
  14. }
  15. });
  16. setContentView(mapView);

其实设置options和在onMapReady中进行设置,或者定位是差不多的,只是一个是动态添加使用,一个是在xml中添加使用,这里就先不细说了。我们继续刚刚的

[java] view plain copy
  1. // Add map fragment to parent container
  2. transaction.add(R.id.container, mapFragment, "com.mapbox.map");
  3. transaction.commit();

这个就是将fragment添加到容器中去,这是android的代码,不是mapbox的代码,没什么好说的。
至此就实现了mapbox在fragment中的使用,如下图

其实设置options和在onMapReady中进行设置,或者定位是差不多的,只是一个是动态添加使用,一个是在xml中添加使用,这里就先不细说了。我们继续刚刚的

[java] view plain copy
  1. // Add map fragment to parent container
  2. transaction.add(R.id.container, mapFragment, "com.mapbox.map");
  3. transaction.commit();

这个就是将fragment添加到容器中去,这是android的代码,不是mapbox的代码,没什么好说的。

至此就实现了mapbox在fragment中的使用,如下图

地图风格,StyleUrl
这个就是mapview.setStyleUrl了,这个参数呢,可以通过mapview来进行设置,也可以通过mapboxmap来进行设置,上面大概的说了一点,这里详细的说一下。
这个就是地图的风格,其实不管是系统自带的风格,还是自己的写的其他的,都是一个url地址而已。
先看系统自带:
[java] view plain copy
  1. Style.MAPBOX_STREETS  默认的
  2. Style.DARK 黑色主题的
  3. Style.LIGHT 亮色主题
  4. Style.OUTDOORS  户外的,具体有什么不同数不清楚我
  5. Style.SATELLITE 影像图
  6. Style.SATELLITE_STREETS 更为详细的影像图

他们都是一个地址,比如DARK,他的地址就是mapbox://styles/mapbox/dark-v9

你也可以尝试一下
"https://www.mapbox.com/android-sdk/files/mapbox-raster-v8.json"
等,更多的我也没有尝试过了,毕竟我一般来说都不会用官方提供的地址,而是使用天地图
地图标记,Marker
很好理解
首先是最基础的使用
[java] view plain copy
  1. mapboxMap.addMarker(new MarkerOptions()
  2. .position(new LatLng(29.619861, 106.515911))
  3. .title("MarkerTitle")
  4. .snippet("Message detail"));
[java] view plain copy

addMarker就是添加一个地图标记,需要传入一个MarkerOptions或者BaseMarkerOptions、BaseMarkerViewOptions这三种的其中一种如果传入BaseMarkerViewOptions,还可以传入一个OnMarkerViewAddedListener,这个之后再说先看最简单的MarkerOptions,这就是一个定点的坐标标记,positon是坐标点,title是点击图标出现的信息的标题,snippet是内容,如图

假如你尝试添加很多个,尝试移除全部重新添加等操作的时候,第一个坑就出现了那就是竟然没有mapboxMap.removeAllMarkers(),这样的方法,一般来说,用脚想这玩意儿也应该是存在的,然而他就是没有。想要移除,一般的方法如下
[java] view plain copy
  1. for (Marker marker : mapboxMap.getMarkers()) {
  2. mapboxMap.removeMarker(marker);
  3. }

这就特别坑了,另外你还可以用

[java] view plain copy
  1. mapboxMap.clear();

这个方法,但是这个主要是用来清空mapview上所有添加上去的东西的,或者就是

[java] view plain copy
  1. mapboxMap.removeAnnotations();

这个是用来移除所有注释,不限于标记,但是至少不会移除layer。所以我建议最好还是封装出来removeAllMarker()这样的方法吧。

然后来试一试使用自己的图标
[java] view plain copy
  1. <span style="white-space:pre;">     </span>IconFactory iconFactory = IconFactory.getInstance(this);
  2. Icon icon = iconFactory.fromResource(R.mipmap.purple_marker);
  3. MarkerOptions markerOptions = new MarkerOptions()
  4. .position(new LatLng(29.619861, 106.515911))
  5. .title("MarkerTitle")
  6. .snippet("MarkerInfo")
  7. .icon(icon);
  8. mapboxMap.addMarker(markerOptions);

如上,想要使用自己的icon,需要先初始化一个icon工厂类,该类可以从bitmap、resource、path、file、asset这几个来源来生成icon

但是,这里又有一个坑,就是大小不是定死的,也就是说,假如你给的图片特别大,他在地图上显示就会特别大,你可以尝试将图片放到不同分辨率的mipmap文件夹中,如果你使用的drawable中来使用,就切换drawable,这是在使用资源文件的情况下,如果你使用的其他类型,一定要提前设置好长和宽。
添加多个Marker
添加多个其实可以采用重复addMarker来实现,这里讲另外一种
[java] view plain copy
  1. MarkerOptions marker1 = new MarkerOptions()
  2. .position(new LatLng(29.619861, 106.515911))
  3. .title("MarkerTitle")
  4. .snippet("Message detail");
  5. MarkerOptions marker2 = new MarkerOptions()
  6. .position(new LatLng(29.612261, 106.154911))
  7. .title("MarkerTitle")
  8. .snippet("Message detail");
  9. MarkerOptions marker3 = new MarkerOptions()
  10. .position(new LatLng(29.519861, 106.547211))
  11. .title("MarkerTitle")
  12. .snippet("Message detail");
  13. MarkerOptions marker4 = new MarkerOptions()
  14. .position(new LatLng(29.657261, 106.152711))
  15. .title("MarkerTitle")
  16. .snippet("Message detail");
  17. List<MarkerOptions> markerList = new ArrayList<>();
  18. markerList.add(marker1);
  19. markerList.add(marker2);
  20. markerList.add(marker3);
  21. markerList.add(marker4);
  22. mapboxMap.addMarkers(markerList);

如上,采用addMarkers来进行添加,很简单,不多说。

带动画的Marker
这个其实并不是mapbox提供的方法,是我在官方demo上发现的,貌似得在android 25.0.0版本以上才能使用,我觉得很不错,特意分享一下
[java] view plain copy
  1. final Marker marker = mapboxMap.addMarker(new MarkerViewOptions()
  2. .position(new LatLng(29.619861, 106.515911))
  3. .title("移动")
  4. .snippet("也不动"));
  5. mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
  6. @Override
  7. public void onMapClick(@NonNull LatLng latLng) {
  8. ValueAnimator maValueAnimator = ObjectAnimator.ofObject(marker, "position",
  9. new LatLngEvaluator(), marker.getPosition(), latLng);
  10. maValueAnimator.setDuration(2000);
  11. maValueAnimator.start();
  12. }
  13. });

需要一个内部类

[java] view plain copy
  1. private static class LatLngEvaluator implements TypeEvaluator<LatLng> {
  2. // Method is used to interpolate the marker animation.
  3. private LatLng latLng = new LatLng();
  4. @Override
  5. public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
  6. latLng.setLatitude(startValue.getLatitude()
  7. + ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
  8. latLng.setLongitude(startValue.getLongitude()
  9. + ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
  10. return latLng;
  11. }
  12. }

实现原理,我没有深度研究,各位可以看看。

marker的详细设置
[java] view plain copy
  1. IconFactory iconFactory1 = IconFactory.getInstance(this);
  2. Icon icon1 = iconFactory1.fromResource(R.mipmap.purple_marker);
  3. // marker view using all the different options available
  4. mapboxMap.addMarker(new MarkerViewOptions()
  5. .position(new LatLng(29.619861, 106.515911))
  6. .icon(icon1)
  7. .rotation(70)//倾斜角度
  8. .anchor(1f, 1f)
  9. .alpha(0.5f)//透明度
  10. .title("Hisense Arena")
  11. .snippet("Olympic Blvd, Melbourne VIC 3001")
  12. .infoWindowAnchor(0.5f, 0.5f)//infowindow的
  13. .flat(false));//是否是平的

这里使用的就不是简单的MarkerOption了,这里使用的是MarkerViewOptions

他可以设置rotation即倾斜调度
anchor,这个东西我一直没搞清楚是什么效果,各种设置都没变化
alpha,透明度,不解释
flat,这个,代表了地图倾斜角变化后,标记是否也跟着变扁平,默认是false
infoWindowAnchor,这个也比较好理解,就是infowindow弹出与图标的相对位置

可以看到图标是倾斜的,另外,两个标记,上面那个的flat设置为false,下面的设置为了true

自定义的infowindow

marker点击出现的infowindow的自定义界面,如下

[java] view plain copy
  1. mapboxMap.addMarker(new MarkerOptions()
  2. .position(new LatLng(29.619861, 106.515911))
  3. .title("infowindow1"));
  4. mapboxMap.addMarker(new MarkerOptions()
  5. .position(new LatLng(29.519861, 106.615911))
  6. .title("infowindow2"));
  7. mapboxMap.addMarker(new MarkerOptions()
  8. .position(new LatLng(29.719861, 106.415911))
  9. .title("infowindow3"));
  10. mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
  11. @Nullable
  12. @Override
  13. public View getInfoWindow(@NonNull final Marker marker) {
  14. LinearLayout parent = new LinearLayout(MarkerActivity.this);
  15. parent.setLayoutParams(new LinearLayout.LayoutParams(ZXSystemUtil.dp2px(MarkerActivity.this, 200), ZXSystemUtil.dp2px(MarkerActivity.this, 80)));
  16. parent.setOrientation(LinearLayout.HORIZONTAL);
  17. parent.setBackgroundColor(ContextCompat.getColor(MarkerActivity.this, R.color.whitesmoke));
  18. ImageView imageView = new ImageView(MarkerActivity.this);
  19. TextView textView = new TextView(MarkerActivity.this);
  20. switch (marker.getTitle()) {
  21. case "infowindow1":
  22. imageView.setImageDrawable(ContextCompat.getDrawable(MarkerActivity.this, R.mipmap.__picker_checkbox_marked));
  23. break;
  24. case "infowindow2":
  25. imageView.setImageDrawable(ContextCompat.getDrawable(MarkerActivity.this, R.mipmap.__picker_ic_camera_p));
  26. break;
  27. case "infowindow3":
  28. imageView.setImageDrawable(ContextCompat.getDrawable(MarkerActivity.this, R.mipmap.__picker_ic_broken_image_black_48dp));
  29. break;
  30. default:
  31. break;
  32. }
  33. textView.setText(marker.getTitle());
  34. textView.setOnClickListener(new View.OnClickListener() {
  35. @Override
  36. public void onClick(View view) {
  37. ZXToastUtil.showToast(MarkerActivity.this, marker.getTitle()+"123");
  38. }
  39. });
  40. parent.addView(imageView);
  41. parent.addView(textView);
  42. return parent;
  43. }
  44. });

可以看到,我添加了三个marker,并使用了setInfoWindowAdapter这个方法,这个方法就是用于给infowindow设置适配器的,我这里是动态生成的界面,也可以使用View.inflater来添加xml界面生成view,就可以实现在infowindow上进行各种操作。同时可以实现点击事件等,marker是MarkerOption,MarkerViewOption等的父类,可以根据这个marker传过来的title来进行判断是哪一个marker,来区分不同marker实现不同的界面。

但是需要注意的是,这里的parent是无法设置点击事件的,也就是说infowindow内部的view的各种事件可以在这里实现,但是infowindow本身不能在这里设置点击事件,如果需要设置,需要使用另外一个方法,

[java] view plain copy
  1. mapboxMap.setOnInfoWindowClickListener(new MapboxMap.OnInfoWindowClickListener() {
  2. @Override
  3. public boolean onInfoWindowClick(@NonNull Marker marker) {
  4. ZXToastUtil.showToast(MarkerActivity.this, marker.getTitle());
  5. return true;
  6. }
  7. });

注:里面的ZXToastUtil是我自己封装的一个Toast方法,你们使用Toast.makeToast就可以了。

同样的,还可以实现setOnInfoWindowLongClickListener和setOnInfoWindowCloseListener两个监听

地图定位
地图定位,不多说了,都懂,直接看代码
1.基础使用
[java] view plain copy
  1. //获取定位引擎并激活
  2. LocationSource locationEngine = LocationSource.getLocationEngine(this);
  3. locationEngine.activate();

ps:地图基础设置那些,我就不写了,和前面一样。

我这里添加了一个FloatingActionButton,为了测试定位的开启和关闭,你们可以使用按钮什么的  都可以
[java] view plain copy
  1. fab.setOnClickListener(new View.OnClickListener() {
  2. @Override
  3. public void onClick(View view) {
  4. if (mapboxMap != null) {
  5. toggleGps();
  6. }
  7. }
  8. });

只需要看里面的toggleGps();这个方法。

[java] view plain copy
  1. //开关定位
  2. private void toggleGps() {
  3. if (mapboxMap.isMyLocationEnabled()) {//已开启
  4. enableLocation(false);//若已开启,就将它关闭
  5. } else {//未开启
  6. if (ZXPermissionUtil.checkLocationPermissions(this)) {
  7. enableLocation(true);//若未开启,就在检查完权限后,将它打开
  8. } else {
  9. ZXPermissionUtil.requestLocationPermissions(this);
  10. }
  11. }
  12. }

这个方法呢其实就是打开或者关闭定位

里面有个判断语句

[java] view plain copy
  1. mapboxMap.isMyLocationEnabled()

很好理解,就字面意思,判断定位是否开启。

如果开启,就关闭定位,如果未开启,就先检查权限,如果有权限就打开定位,如果没有权限就开启权限,里面的ZXPermissionUtil是我封装的权限工具,这里就不说的,你们使用checkPermission就可以了,后面有空再将我整合的工具类、view类、manager等拿出来分享。

好,然后是里面的
[java] view plain copy
  1. enableLocation(true)

如下

[java] view plain copy
  1. //设置定位
  2. private void enableLocation(boolean enable) {
  3. if (enable) {
  4. //获取上次定位参数,如果存在先直接使用
  5. final Location lastlocation = locationEngine.getLastLocation();
  6. if (lastlocation != null) {
  7. mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lastlocation), 15), 1000);
  8. }
  9. locationEngineListener = new LocationEngineListener() {
  10. @Override
  11. public void onConnected() {
  12. //连接到定位服务,不需要操作
  13. }
  14. @Override
  15. public void onLocationChanged(Location location) {
  16. if (location != null) {
  17. mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15), 1000);
  18. locationEngine.removeLocationEngineListener(this);
  19. }
  20. }
  21. };
  22. //设置监听器
  23. locationEngine.addLocationEngineListener(locationEngineListener);
  24. fab.setImageResource(R.drawable.ic_location_disabled_24dp);
  25. } else {
  26. fab.setImageResource(R.drawable.ic_my_location_24dp);
  27. }
  28. //添加或移除定位图层
  29. mapboxMap.setMyLocationEnabled(enable);
  30. }

这个就比较长了,慢慢看

[java] view plain copy
  1. //获取上次定位参数,如果存在先直接使用
  2. final Location lastlocation = locationEngine.getLastLocation();
  3. if (lastlocation != null) {
  4. mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lastlocation), 15), 1000);
  5. }
这个呢就是获取上次定位时保存好的坐标位置,先给地图一个定位坐标,让地图先定过去再说。这个的用意,用过其他地图的应该都知道。
[java] view plain copy
  1. locationEngineListener = new LocationEngineListener() {
  2. @Override
  3. public void onConnected() {
  4. //连接到定位服务,不需要操作
  5. }
  6. @Override
  7. public void onLocationChanged(Location location) {
  8. if (location != null) {
  9. mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15), 1000);
  10. locationEngine.removeLocationEngineListener(this);
  11. }
  12. }
  13. };
  14. //设置监听器
  15. locationEngine.addLocationEngineListener(locationEngineListener);

然后就初始化一个监听器,并设置给定位引擎,我们可以看到,在得到定位的时候,就将地图定了过去。

[java] view plain copy
  1. //添加或移除定位图层
  2. mapboxMap.setMyLocationEnabled(enable);

这个就简单啦,就是是否要显示定位的那个标记的

[java] view plain copy
  1. fab.setImageResource(R.drawable.ic_location_disabled_24dp);
  2. fab.setImageResource(R.drawable.ic_my_location_24dp);

里面这两句是设置按钮的背景的,不细说。

另外,还要注意几个生命周期的重写
[java] view plain copy
  1. @Override
  2. protected void onStart() {
  3. super.onStart();
  4. mapView.onStart();
  5. if (locationEngine != null && locationEngineListener != null) {
  6. locationEngine.activate();
  7. locationEngine.requestLocationUpdates();
  8. locationEngine.addLocationEngineListener(locationEngineListener);
  9. }
  10. }
  11. @Override
  12. protected void onStop() {
  13. super.onStop();
  14. mapView.onStop();
  15. if (locationEngine != null && locationEngineListener != null) {
  16. locationEngine.removeLocationEngineListener(locationEngineListener);
  17. locationEngine.removeLocationUpdates();
  18. locationEngine.deactivate();
  19. }
  20. }
  21. @Override
  22. protected void onDestroy() {
  23. super.onDestroy();
  24. mapView.onDestroy();
  25. // Ensure no memory leak occurs if we register the location listener but the call hasn't
  26. // been made yet.
  27. if (locationEngineListener != null) {
  28. locationEngine.removeLocationEngineListener(locationEngineListener);
  29. }
  30. }

大意就是在应用重新进入的时候激活定位,设置定位监听

在停止的时候移除监听并取消激活
其实吧,这些吧,写不写都行,不过为了系统性能,可以写上。
设置定位图标的属性

设置定位图标的属性需要获取到一个MyLocationViewSetting的值

[java] view plain copy
  1. MyLocationViewSettings locationSettings = mapboxMap.getMyLocationViewSettings();
  2. locationSettings.setBackgroundDrawable(ContextCompat.getDrawable(LocationActivity.this, R.drawable.ic_my_location_24dp), new int[]{20, 20, 20, 20});
  3. locationSettings.setForegroundTintColor(ContextCompat.getColor(this, R.color.seagreen));
  4. locationSettings.setAccuracyTintColor(ContextCompat.getColor(this,R.color.brown));
  5. locationSettings.setAccuracyAlpha(50);
  6. locationSettings.setTilt(30);

如上,获取到后,可以设置定位图标的各种属性,第一个是图片不再多说

setForegroundTintColor,这个是用于设置定位图标中心圆的颜色

setAccuracyTintColor,这个是用于设置定位图标范围框的颜色

setAccuracyAlpha,设置范围框的透明度

setTilt,设置倾斜角,上面用过这个参数

注意,设置drawable同时还设置了padding

地图跟随

地图跟随,就是tracking,如下

[java] view plain copy
  1. TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
  2. // 让地图始终以定位点为中心,无法滑动
  3. trackingSettings.setDismissAllTrackingOnGesture(false);
  4. // 启用位置和方位跟踪
  5. trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
  6. trackingSettings.setMyBearingTrackingMode(MyBearingTracking.COMPASS);

获取到一个trackingSetting对象,这个对象可用于设置地图跟随的相关属性

首先是setDissmissAllTrackingOnGesture(false),就像我注释说的,是将地图的中心点就固定了,无法移动,只能放大缩小

然后是setMyLocationTrackingMode,这个是设置地图位置模式,TRACKING_FOLLOW就是跟随的意思,就是说如果自身位置移动了,地图中心点也会跟着变化的意思

最后是setMyBearingTrackingMode,这个是设置方位的跟踪模式,有COMPASS,GPS等,值得注意的是,不知道是不是我在室内的原因,这方向箭头只能指向两端两个方位,转动手机到某个位置就直接旋转180度,而不是随着手机转动而慢慢转动角度,我感觉是室内,因为我这gps一向不咋地,毕竟总觉得要是这就是mapbox自带的,也太坑爹了。

可参考该博客:http://blog.csdn.net/stanny_bing/article/details/70230703

Android开发,MapBox地图详细介绍、使用、部分功能实现(初始化、标记、定位、styleurl)相关推荐

  1. qt for android开发百度地图(一步步带图详解)

    qt for android开发百度地图 前言:qt for android开发百度地图,其实找了很多资料,基本上没有,就自己折磨弄了出来,这个过程还是很曲折的,折磨了一两个星期,没有资料,就两个字' ...

  2. 原生Android开发基础项目结构介绍

    原生Android开发基础项目结构介绍 1.软件整体结构 2.具体的页面书写 3.实例分析 4.后续     下面先来总结一下软件的基本目录结构,这一般是开发的关键,只有明白了软件的目录结构,才能更加 ...

  3. Android开发——百度地图定位

    Android开发--百度地图定位 项目需求 项目内容 注册和获取秘钥 获取项目SHA1码 获取项目AK码 AS依赖配置 AS源码 AndroidManifest文件 布局文件 DemoApplica ...

  4. Android旋转视频工具类,Android开发实现的IntentUtil跳转多功能工具类【包含视频、音频、图片、摄像头等操作功能】...

    本文实例讲述了Android开发实现的IntentUtil跳转多功能工具类.分享给大家供大家参考,具体如下: 说明:此工具类是本人开发中总结下来的,还有其它的跳转亲给我留言,希望大家一起把这个工具类打 ...

  5. android实现新闻内容显示功能,Android开发实现自定义新闻加载页面功能实例

    本文实例讲述了Android开发实现自定义新闻加载页面功能.分享给大家供大家参考,具体如下: 一.概述: 1.效果演示: 2.说明:在新闻页面刚加载的时候,一般会出现五种状态 未知状态(STATE_U ...

  6. Android开发:app工程集成银联支付功能(客户端)

    Android开发:app工程集成银联支付功能(客户端) email:chentravelling@163.com 上一篇博文完成了服务器端的集成,可参考: Android开发:app工程集成银联支付 ...

  7. 面向开发者的 Android 8.0 Oreo 详细介绍

    无需原生开发基础,也能完美呈现京东商城.<混合开发京东商城系统,提前布局大前端>课程融合vue.Android.IOS等目前流行的前端和移动端技术,混合开发经典电商APP--京东.课程将各 ...

  8. Android开发环境搭建详细图解

    所谓Android的开发环境,主要是以下两个组件,Android Software Developer Kit(Android软件开发工具包)和Eclipse(编辑器,提供很多方便功能)两大块,下面分 ...

  9. Android开发工具链ppt,介绍Android原生开发工具包r14

    原标题:介绍Android原生开发工具包r14 现在,可以下载最新版本 Android 原生开发工具包 (NDK)--Android NDK r14.也可以通过 Android Studio 在 SD ...

  10. Android开发:最详细的 Toolbar 开发实践总结

    最详细的 Toolbar 开发实践总结 过年前发了一篇介绍 Translucent System Bar 特性的文章 Translucent System Bar 的最佳实践,收到很多开发者的关注和反 ...

最新文章

  1. 面试:你知道 Java 中的回调机制吗?
  2. 《剑指Offer》题一~题十
  3. python decode hex_在python2.7中使用b64decode()将base64转换为hex
  4. c++ vector pop_back() 与pop_back()
  5. php or || 和 and
  6. 快速分类–三向和双枢轴
  7. 经典数值优化算法--专题学习
  8. Hadoop MapReduce(WordCount) Java编程
  9. 手机html文档,手机文档html能删除吗
  10. 【语音评价】基于matlab语音质量客观评价(PESQ)【含Matlab源码 1717期】
  11. zul组件、zhtml组件、native组件的区别
  12. Mac 百度云加速下载,突破限速,大文件无压力(小白使用无压力)
  13. GEE学习笔记3:Landsat8 植被指数计算
  14. photoshop-CMYK色彩模式
  15. as_completed函数用例
  16. m4a怎么转换成mp4?一个简单好用的操作教程分享
  17. mysql 海明距离,golang 实现海明距离 demo
  18. 服务器内存条能点亮显示器吗,上两根内存条显示器就不亮了
  19. cmstop中使用到的js文件
  20. USTC高级软件工程课程学习总结和心得

热门文章

  1. 常见的重要电脑英语及缩写
  2. CTF常见用法小总结
  3. Html静态页面更新,解决浏览器缓存不更新问题
  4. gitlab 邮件服务器配置
  5. 图像处理标准图像——“Lena图”的由来
  6. centos查询 硬盘序列号查询_关于使用java执行shell脚本获取centos的硬盘序列号和mac地址...
  7. 全英文文献翻译 | 遥感技术在绘制中国与东南亚地区岩溶地质的系列地图中的应用
  8. 用iSSH代替Mobile Terminal管理iOS
  9. 【速达软件】速达5000系列、V5、S5批量更改税率
  10. [机器学习实战] 机器学习基础