zoukankan      html  css  js  c++  java
  • 百度地图基本操作

    基础地图

    简介

    开发者可利用SDK提供的接口,使用百度为您提供的基础地图数据。目前百度地图SDK所提供的地图等级为3-21级,所包含的信息有建筑物、道路、河流、学校、公园等内容。

    V3.7.0起,地图支持缩放至21级显示;卫星图、热力图和交通路况图最高支持20级缩放显示。

    所有叠加或覆盖到地图的内容,我们统称为地图覆盖物。如标注、矢量图形元素(包括:折线、多边形和圆等)、定位图标等。覆盖物拥有自己的地理坐标,当您拖动或缩放地图时,它们会相应的移动。

    百度地图SDK为广大开发者提供的基础地图和上面的各种覆盖物元素,具有一定的层级压盖关系,具体如下(从下至上的顺序):

    1、基础底图(包括底图、底图道路、卫星图、室内图等);

    2、瓦片图层(TileOverlay);

    3、地形图图层(GroundOverlay);

    4、热力图图层(HeatMap);

    5、实时路况图图层(BaiduMap.setTrafficEnabled(true););

    6、百度城市热力图(BaiduMap.setBaiduHeatMapEnabled(true););

    7、底图标注(指的是底图上面自带的那些POI元素);

    8、几何图形图层(点、折线、弧线、圆、多边形);

    9、标注图层(Marker),文字绘制图层(Text);

    10、指南针图层(当地图发生旋转和视角变化时,默认出现在左上角的指南针);

    11、定位图层(BaiduMap.setMyLocationEnabled(true););

    12、弹出窗图层(InfoWindow);

    13、自定义View(MapView.addView(View););

    地图类型

    百度地图Android SDK为您提供了3种类型的地图资源(普通矢量地图、卫星图和空白地图),开发者可以利用BaiduMap中的mapType()方法来设置地图类型。核心代码如下:

    mMapView = (MapView) findViewById(R.id.bmapView);  
    mBaiduMap = mMapView.getMap();  
     
    //普通地图  
    mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);  
     
    //卫星地图  
    mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);  
     
    //空白地图, 基础地图瓦片将不会被渲染。在地图类型中设置为NONE,将不会使用流量下载基础地图瓦片图层。使用场景:与瓦片图层一起使用,节省流量,提升自定义瓦片图下载速度。
    mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);

    V3.7.0起,地图支持缩放至21级缩放显示;卫星图、热力图和交通路况图最高支持20级缩放显示。 在打开21级地图切换卫星图、热力图和交通路况图,地图层级会自动缩放到20级。

    实时交通图

    当前,全国范围内已支持多个城市实时路况查询,且会陆续开通其他城市。

    在地图上打开实时路况的核心代码如下:

    mMapView = (MapView) findViewById(R.id.bmapView);  
    mBaiduMap = mMapView.getMap();  
    //开启交通图   
    mBaiduMap.setTrafficEnabled(true);

    百度城市热力图

    百度地图SDK继为广大开发者开放热力图本地绘制能力之后,再次进一步开放百度自有数据的城市热力图层,帮助开发者构建形式更加多样的移动端应用。

    百度城市热力图的性质及使用与实时交通图类似,只需要简单的接口调用,即可在地图上展现样式丰富的百度城市热力图。

    在地图上开启百度城市热力图的核心代码如下:

    地图控

    mMapView = (MapView) findViewById(R.id.bmapView);  
    mBaiduMap = mMapView.getMap();  
    //开启交通图   
    mBaiduMap.setBaiduHeatMapEnabled(true);

    制和手势

    地图控制

    地图Logo

    • 默认在左下角显示,不可以移除。

    通过mMapView.setLogoPosition(LogoPosition.logoPostionleftBottom);方法,使用枚举类型控制显示的位置,共支持6个显示位置(左下,中下,右下,左上,中上,右上)。

    • 地图Logo不允许遮挡,可通过mBaiduMap.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);方法可以设置地图边界区域,来避免UI遮挡。

    其中参数paddingLeft、paddingTop、paddingRight、paddingBottom参数表示距离屏幕边框的左、上、右、下边距的距离,单位为屏幕坐标的像素密度。

    指南针

    指南针默认为开启状态,可以关闭显示 。

    比例尺

    比例尺默认为开启状态,可以关闭显示。同时支持设置MaxZoomLevel和minZoomLevel,可通过mMapView.getMapLevel获取当前地图级别下比例尺所表示的距离大小。

    地图手势

    地图平移

    控制是否启用或禁用平移的功能,默认开启。如果启用,则用户可以平移地图

    地图缩放

    控制是否启用或禁用缩放手势,默认开启。如果启用,用户可以双指点击或缩放地图视图。

    地图俯视(3D)

    控制是否启用或禁用俯视(3D)功能,默认开启。如果启用,则用户可使用双指 向下或向上滑动到俯视图。

    地图旋转

    控制是否启用或禁用地图旋转功能,默认开启。如果启用,则用户可使用双指 旋转来旋转地图。

    禁止所有手势

    控制是否一并禁止所有手势,默认关闭。如果启用,所有手势都将被禁用。

    标注覆盖物

    在百度地图上展示覆盖物,需使用百度BD09坐标,如使用其他坐标( WGS84、GCJ02)进行展示,需先将其他坐标转换为BD09,详细说明请参考坐标转换页面,请勿使用非官方的转换方法

    地图标注

    开发者可根据自己实际的业务需求,利用标注覆盖物,在地图指定的位置上添加标注信息。

    具体实现方法如下:

    //定义Maker坐标点  
    LatLng point = new LatLng(39.963175, 116.400244);  
    //构建Marker图标  
    BitmapDescriptor bitmap = BitmapDescriptorFactory  
        .fromResource(R.drawable.icon_marka);  
    //构建MarkerOption,用于在地图上添加Marker  
    OverlayOptions option = new MarkerOptions()  
        .position(point)  
        .icon(bitmap);  
    //在地图上添加Marker,并显示  
    mBaiduMap.addOverlay(option);

    basicmap1.png

    针对已经添加在地图上的标注,可采用如下方式进行手势拖拽:

    第一步,设置可拖拽:

    OverlayOptions options = new MarkerOptions()
        .position(llA)  //设置marker的位置
        .icon(bdA)  //设置marker图标
        .zIndex(9)  //设置marker所在层级
        .draggable(true);  //设置手势拖拽
    //将marker添加到地图上
    marker = (Marker) (mBaiduMap.addOverlay(options));

    第二步,设置监听方法:

    //调用BaiduMap对象的setOnMarkerDragListener方法设置marker拖拽的监听
    mBaiduMap.setOnMarkerDragListener(new OnMarkerDragListener() {
        public void onMarkerDrag(Marker marker) {
            //拖拽中
        }
        public void onMarkerDragEnd(Marker marker) {
            //拖拽结束
        }
        public void onMarkerDragStart(Marker marker) {
            //开始拖拽
        }
    });

    自v3.3.0版本起,SDK提供了给Marker增加动画的能力,具体实现方法如下:

    // 通过marker的icons设置一组图片,再通过period设置多少帧刷新一次图片资源
    ArrayList<BitmapDescriptor> giflist = new ArrayList<BitmapDescriptor>();
    giflist.add(bdA);
    giflist.add(bdB);
    giflist.add(bdC);
    OverlayOptions ooD = new MarkerOptions().position(pt).icons(giflist)
                    .zIndex(0).period(10);  
    mMarkerD = (Marker) (mBaiduMap.addOverlay(ooD));

    针对已添加在地图上的标注覆盖物,可利用如下方法进行修改和删除操作:

    marker.remove();   //调用Marker对象的remove方法实现指定marker的删除

    自v3.6.0版本起,SDK提供了给加载Marker增加动画的能力,加载maker时包含两种加载动画方式:从地上生长和从天上落下。

    以生长动画为例,具体实现方法如下:

    MarkerOptions ooD = new MarkerOptions().position(llD).icons(giflist)
                    .zIndex(0).period(10);
     if (animationBox.isChecked()) {
         // 生长动画
         ooD.animateType(MarkerAnimateType.grow);
     }
     Marker  mMarkerD = (Marker) (mBaiduMap.addOverlay(ooD));

    自v3.6.0版本起,SDK提供了给Marker设置透明度的方法,具体实现方法如下:

    MarkerOptions ooA = new MarkerOptions().position(llD).icons(giflist)
                    .zIndex(0).period(10).alpha(0.5);
    mBaiduMap.addOverlay(ooA);

    具体源码请在OverlayDemo中查看。

    点聚合功能

    自v3.6.0版本起,新增点聚合功能,可通过缩小地图层级,将定义范围内的多个标注点,聚合显示成一个标注点,并在MarkerClusterDemo中开放源码,方便开发者自行修改。

    // 初始化点聚合管理类
    ClusterManager mClusterManager = new ClusterManager<>(this, mBaiduMap);
    // 向点聚合管理类中添加Marker实例
    LatLng llA = new LatLng(39.963175, 116.400244);
    List<MyItem> items = new ArrayList<>();
    items.add(new MyItem(llA));
    mClusterManager.addItems(items);

    具体源码请在MarkerClusterDemo中查看。

    底图标注

    自v3.6.0版本起,SDK在BaiduMap提供了控制底图标注的showMapPoi方法,默认显示底图标注。利用此属性可得到仅显示道路信息的地图,方法如下:

    // 将底图标注设置为隐藏,方法如下:
    mBaiduMap.showMapPoi(false)

    运行后,底图标注被隐藏,效果如图:

    nopoi.png

    几何图形覆盖物

    地图SDK提供多种结合图形覆盖物,利用这些图形,可帮助您构建更加丰富多彩的地图应用。目前提供的几何图形有:点(Dot)、折线(Polyline)、弧线(Arc)、圆(Circle)、多边形(Polygon)。

    在百度地图上展示覆盖物,需使用百度BD09坐标,如使用其他坐标( WGS84、GCJ02)进行展示,需先将其他坐标转换为BD09,详细说明请参考坐标转换页面,请勿使用非官方的转换方法

    下面以多边形为例,向大家介绍如何使用几何图形覆盖物:

    //定义多边形的五个顶点  
    LatLng pt1 = new LatLng(39.93923, 116.357428);  
    LatLng pt2 = new LatLng(39.91923, 116.327428);  
    LatLng pt3 = new LatLng(39.89923, 116.347428);  
    LatLng pt4 = new LatLng(39.89923, 116.367428);  
    LatLng pt5 = new LatLng(39.91923, 116.387428);  
    List<LatLng> pts = new ArrayList<LatLng>();  
    pts.add(pt1);  
    pts.add(pt2);  
    pts.add(pt3);  
    pts.add(pt4);  
    pts.add(pt5);  
    //构建用户绘制多边形的Option对象  
    OverlayOptions polygonOption = new PolygonOptions()  
        .points(pts)  
        .stroke(new Stroke(5, 0xAA00FF00))  
        .fillColor(0xAAFFFF00);  
    //在地图上添加多边形Option,用于显示  
    mBaiduMap.addOverlay(polygonOption);

    运行结果如下:

    basicmap2.png

    Android地图SDK自v3.5.0版本起,新增了折线多段颜色绘制能力,实现的核心代码如下:

    //构造纹理资源
    BitmapDescriptor custom1 = BitmapDescriptorFactory
                    .fromResource(R.drawable.icon_road_red_arrow);
    BitmapDescriptor custom2 = BitmapDescriptorFactory
                    .fromResource(R.drawable.icon_road_green_arrow);
    BitmapDescriptor custom3 = BitmapDescriptorFactory
                    .fromResource(R.drawable.icon_road_blue_arrow);
    // 定义点
    LatLng pt1 = newLatLng(39.93923, 116.357428);
    LatLng pt2 = newLatLng(39.91923, 116.327428);
    LatLng pt3 = newLatLng(39.89923, 116.347428);
    LatLng pt4 = newLatLng(39.89923, 116.367428);
    LatLng pt5 = newLatLng(39.91923, 116.387428);
     
    //构造纹理队列
    List<BitmapDescriptor>customList = newArrayList<BitmapDescriptor>();
    customList.add(custom1);
    customList.add(custom2);
    customList.add(custom3);
     
    List<LatLng> points = newArrayList<LatLng>();
    List<Integer> index = newArrayList<Integer>();
    points.add(pt1);//点元素
    index.add(0);//设置该点的纹理索引
    points.add(pt2);//点元素
    index.add(0);//设置该点的纹理索引
    points.add(pt3);//点元素
    index.add(1);//设置该点的纹理索引
    points.add(pt4);//点元素
    index.add(2);//设置该点的纹理索引
    points.add(pt5);//点元素
    //构造对象
    OverlayOptionsooPolyline = newPolylineOptions().width(15).color(0xAAFF0000).points(points).customTextureList(customList).textureIndex(index);
    //添加到地图
    mBaiduMap.addOverlay(ooPolyline);

    效果图如下:

    3_%E5%89%AF%E6%9C%AC.png

    自v3.6.0版本起,扩展了折线多段颜色绘制能力:增加支持分段纹理绘制、分段颜色绘制,实现的核心代码如下:

    构造PolylineOptions对象,添加折线分段颜色绘制覆盖物,核心代码如下:

    // 构造折线点坐标
    List<LatLng> points = new ArrayList<LatLng>();
    points.add(new LatLng(39.965,116.404));
    points.add(new LatLng(39.925,116.454));
    points.add(new LatLng(39.955,116.494));
    points.add(new LatLng(39.905,116.554));
    points.add(new LatLng(39.965,116.604));
     
    //构建分段颜色索引数组
    List<Integer> colors = new ArrayList<>();
    colors.add(Integer.valueOf(Color.BLUE));
    colors.add(Integer.valueOf(Color.RED));
    colors.add(Integer.valueOf(Color.YELLOW));
    colors.add(Integer.valueOf(Color.GREEN));
     
    OverlayOptions ooPolyline = new PolylineOptions().width(10)
            .colorsValues(colors).points(points);
    添加在地图中
    Polyline  mPolyline = (Polyline) mBaiduMap.addOverlay(ooPolyline);

    运行结果:

    文字覆盖物

    文字,在地图中也是一种覆盖物,开发者可利用相关的接口,快速实现在地图上书写文字的需求。实现方式如下:

    //定义文字所显示的坐标点  
    LatLng llText = new LatLng(39.86923, 116.397428);  
    //构建文字Option对象,用于在地图上添加文字  
    OverlayOptions textOption = new TextOptions()  
        .bgColor(0xAAFFFF00)  
        .fontSize(24)  
        .fontColor(0xFFFF00FF)  
        .text("百度地图SDK")  
        .rotate(-30)  
        .position(llText);  
    //在地图上添加该文字对象并显示  
    mBaiduMap.addOverlay(textOption);

    运行结果如下:

    basicmap3.png

    弹出窗覆盖物

    弹出窗覆盖物的实现方式如下,开发者可利用此接口,构建具有更强交互性的地图页面。

    //创建InfoWindow展示的view  
    Button button = new Button(getApplicationContext());  
    button.setBackgroundResource(R.drawable.popup);  
    //定义用于显示该InfoWindow的坐标点  
    LatLng pt = new LatLng(39.86923, 116.397428);  
    //创建InfoWindow , 传入 view, 地理坐标, y 轴偏移量 
    InfoWindow mInfoWindow = new InfoWindow(button, pt, -47);  
    //显示InfoWindow  
    mBaiduMap.showInfoWindow(mInfoWindow);

    下图为点击Marker弹出InfoWindow的示例图,开发者只需将InfoWindow的显示方法写在Maker的点击事件处理中即可实现该效果。

    运行结果如下:

    basicmap4.png

    地形图图层

    地形图图层(GroundOverlay),又可叫做图片图层,即开发者可在地图的指定位置上添加图片。该图片可随地图的平移、缩放、旋转等操作做相应的变换。该图层是一种特殊的Overlay, 它位于底图和底图标注层之间(即该图层不会遮挡地图标注信息)。

    在百度地图上设置图层位置,需使用百度BD09坐标,如使用其他坐标( WGS84、GCJ02)进行展示,需先将其他坐标转换为BD09,详细说明请参考坐标转换页面,请勿使用非官方的转换方法

    在地图中添加使用地形图覆盖物的方式如下:

    //定义Ground的显示地理范围  
    LatLng southwest = new LatLng(39.92235, 116.380338);  
    LatLng northeast = new LatLng(39.947246, 116.414977);  
    LatLngBounds bounds = new LatLngBounds.Builder()  
        .include(northeast)  
        .include(southwest)  
        .build();  
    //定义Ground显示的图片  
    BitmapDescriptor bdGround = BitmapDescriptorFactory  
        .fromResource(R.drawable.ground_overlay);  
    //定义Ground覆盖物选项  
    OverlayOptions ooGround = new GroundOverlayOptions()  
        .positionFromBounds(bounds)  
        .image(bdGround)  
        .transparency(0.8f);  
    //在地图中添加Ground覆盖物  
    mBaiduMap.addOverlay(ooGround);

    运行结果如下:

    basicmap5.png

    热力图功能

    热力图是用不同颜色的区块叠加在地图上描述人群分布、密度和变化趋势的一个产品,百度地图SDK将绘制热力图的能力为广大开发者开放,帮助开发者利用自有数据,构建属于自己的热力图,提供丰富的展示效果。

    利用热力图功能构建自有数据热力图的方式如下:

    第一步,设置颜色变化:

    //设置渐变颜色值
    int[] DEFAULT_GRADIENT_COLORS = {Color.rgb(102, 225,  0), Color.rgb(255, 0, 0) };
    //设置渐变颜色起始值
    float[] DEFAULT_GRADIENT_START_POINTS = { 0.2f, 1f };
    //构造颜色渐变对象
    Gradient gradient = new Gradient(DEFAULT_GRADIENT_COLORS, DEFAULT_GRADIENT_START_POINTS);

    第二步,准备数据:

    //以下数据为随机生成地理位置点,开发者根据自己的实际业务,传入自有位置数据即可
    List<LatLng> randomList = new ArrayList<LatLng>();
    Random r = new Random();
    for (int i = 0; i < 500; i++) {
        // 116.220000,39.780000 116.570000,40.150000
        int rlat = r.nextInt(370000);
        int rlng = r.nextInt(370000);
        int lat = 39780000 + rlat;
        int lng = 116220000 + rlng;
        LatLng ll = new LatLng(lat / 1E6, lng / 1E6);
        randomList.add(ll);
    }

    第三步,添加、显示热力图:

    //在大量热力图数据情况下,build过程相对较慢,建议放在新建线程实现
    HeatMap heatmap = new HeatMap.Builder()
        .data(randomList)
        .gradient(gradient)
        .build();
    //在地图上添加热力图
    mBaiduMap.addHeatMap(heatmap);
    第四步,删除热力图:
    
    heatmap.removeHeatMap();

    检索结果覆盖物

    针对检索功能模块(POI检索、线路规划等),地图SDK还对外提供相应的覆盖物来快速展示结果信息。这些方法都是开源的,开发者可根据自己的实际去求来做个性化的定制。

    利用检索结果覆盖物展示POI搜索结果的方式如下:

    第一步,构造自定义 PoiOverlay 类;

    private class MyPoiOverlay extends PoiOverlay {  
        public MyPoiOverlay(BaiduMap baiduMap) {  
            super(baiduMap);  
        }  
        @Override  
        public boolean onPoiClick(int index) {  
            super.onPoiClick(index);  
            return true;  
        }  
    }

    第二步,在POI检索回调接口中添加自定义的PoiOverlay;

    public void onGetPoiResult(PoiResult result) {  
        if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {  
            return;  
        }  
        if (result.error == SearchResult.ERRORNO.NO_ERROR) {  
            mBaiduMap.clear();  
            //创建PoiOverlay  
            PoiOverlay overlay = new MyPoiOverlay(mBaiduMap);  
            //设置overlay可以处理标注点击事件  
            mBaiduMap.setOnMarkerClickListener(overlay);  
            //设置PoiOverlay数据  
            overlay.setData(result);  
            //添加PoiOverlay到地图中  
            overlay.addToMap();  
            overlay.zoomToSpan();  
            return;  
        }  
    }

    运行结果如下:

    basicmap6.png

    利用TransitRouteOverlay展示公交换乘结果:

    //在公交线路规划回调方法中添加TransitRouteOverlay用于展示换乘信息  
    public void onGetTransitRouteResult(TransitRouteResult result) {  
        if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {  
            //未找到结果  
            return;  
        }  
        if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {  
            //起终点或途经点地址有岐义,通过以下接口获取建议查询信息  
            //result.getSuggestAddrInfo()  
            return;  
        }  
        if (result.error == SearchResult.ERRORNO.NO_ERROR) {  
            route = result.getRouteLines().get(0);  
            //创建公交路线规划线路覆盖物   
            TransitRouteOverlay overlay = new MyTransitRouteOverlay(mBaidumap);  
            //设置公交路线规划数据     
            overlay.setData(route);  
            //将公交路线规划覆盖物添加到地图中  
            overlay.addToMap();  
            overlay.zoomToSpan();  
       }  
    }

    运行结果如下:

    basicmap7.png

    OpenGL绘制功能

    百度地图SDK为广大开发者开放了OpenGL绘制接口,帮助开发者在地图上实现更灵活的样式绘制,丰富地图使用效果体验。

    在百度地图上绘制各种覆盖物,需使用百度BD09坐标,如使用其他坐标( WGS84、GCJ02)进行展示,需先将其他坐标转换为BD09,详细说明请参考坐标转换页面,请勿使用非官方的转换方法


    下面将以在地图上绘制折线为例,向大家介绍如何使用OpenGL绘制接口:

    自4.2.0起, 地图SDK支持 OpenGLES 2.0, onMapDrawFrame(GL10 gl, MapStatus drawingMapStatus)废弃;请使用onMapDrawFrame(MapStatus drawingMapStatus)

    // 定义地图绘制每一帧时 OpenGL 绘制的回调接口
    OnMapDrawFrameCallback callback = new OnMapDrawFrameCallback() {
        public void onMapDrawFrame(MapStatus drawingMapStatus)     {
            if (mBaiduMap.getProjection() != null) {
                 drawFrame(drawingMapStatus);
     
            }
        }
    }
     
    // 设置地图绘制每一帧时的回调接口
    mMapView = (MapView) findViewById(R.id.bmapView);
    mBaiduMap = mMapView.getMap();
    mBaiduMap.setOnMapDrawFrameCallback(this);
     
    // 采用屏幕坐标, 有抖动,有累计误差
        private void drawFrame(MapStatus drawingMapStatus) {
     
            PointF p1f = mBaiduMap.getProjection().toOpenGLNormalization(latlng2 , drawingMapStatus);
            PointF p2f = mBaiduMap.getProjection().toOpenGLNormalization(latlng3 , drawingMapStatus);
     
            float mVerticesData[] = new float[] { p1f.x, p1f.y, 0.0f, p2f.x, p1f.y, 0.0f, p1f.x,
                    p2f.y, 0.0f, p2f.x, p2f.y, 0.0f };
            mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
            mVertices.put(mVerticesData).position(0);
     
            mTexCoords = ByteBuffer.allocateDirect(mTexCoordsData.length * 2)
                    .order(ByteOrder.nativeOrder()).asShortBuffer();
            mTexCoords.put(mTexCoordsData).position(0);
            if(!mBfirst) {
                comipleShaderAndLinkProgram();
                loadTexture();
                mBfirst = true;
            }
     
            GLES20.glUseProgram(mProgramObject);
     
            GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices);
            GLES20.glEnableVertexAttribArray(0);
     
            GLES20.glVertexAttribPointer(1, 2, GLES20.GL_SHORT, false, 0, mTexCoords);
            GLES20.glEnableVertexAttribArray(1);
     
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID);
     
            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        }
     
     
        private void comipleShaderAndLinkProgram() {
            final String vShaderStr = "attribute vec4 a_position;    
    "
                    +"attribute vec2 a_texCoords; 
    "
                    +"varying vec2 v_texCoords; 
    "
                    + "void main()                  
    "
                    + "{                            
    "
                    + "   gl_Position = a_position;  
    "
                    +"    v_texCoords = a_texCoords; 
    "
                    + "}                            
    ";
            final String fShaderStr = "precision mediump float;                     
    "
                    +"uniform sampler2D u_Texture; 
    "
                    +"varying vec2 v_texCoords; 
    "
                    + "void main()                                  
    "
                    + "{                                            
    "
                    + "  gl_FragColor = texture2D(u_Texture, v_texCoords) ;
    "
                    + "}                                            
    ";
            int vertexShader;
            int fragmentShader;
            int programObject;
            int[] linked = new int[1];
            // Load the vertex/fragment shaders
            vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vShaderStr);
            fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fShaderStr);
            // Create the program object
            programObject = GLES20.glCreateProgram();
            if (programObject == 0) {
                return ;
     
            }
     
            GLES20.glAttachShader(programObject, vertexShader);
            GLES20.glAttachShader(programObject, fragmentShader);
            // Bind vPosition to attribute 0
            GLES20.glBindAttribLocation(programObject, 0, "a_position");
            GLES20.glBindAttribLocation(programObject, 1, "a_texCoords");
            // Link the program
            GLES20.glLinkProgram(programObject);
            // Check the link status
            GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0);
            if (linked[0] == 0) {
                Log.e(LTAG, "Error linking program:");
                Log.e(LTAG, GLES20.glGetProgramInfoLog(programObject));
                GLES20.glDeleteProgram(programObject);
                return  ;
            }
            mProgramObject = programObject;
        }
        private int loadShader(int shaderType, String shaderSource) {
            int shader;
            int[] compiled = new int[1];
            // Create the shader object
            shader = GLES20.glCreateShader(shaderType);
            if (shader == 0) {
                return 0;
     
            }
            // Load the shader source
            GLES20.glShaderSource(shader, shaderSource);
            // Compile the shader
            GLES20.glCompileShader(shader);
            // Check the compile status
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
            if (compiled[0] == 0) {
                Log.e(LTAG, GLES20.glGetShaderInfoLog(shader));
                GLES20.glDeleteShader(shader);
                return 0;
            }
            return shader;
        }
        private void loadTexture() {
            bitmap = BitmapFactory.decodeResource(this.getResources(),
                    R.drawable.ground_overlay);
            if (bitmap != null) {
                int []texID = new int[1];
                GLES20.glGenTextures(1, texID, 0);
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texID[0]);
                mTexID = texID[0];
                GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
                        GLES20.GL_LINEAR);
                GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                        GLES20.GL_LINEAR);
     
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
                        GLES20.GL_REPEAT);
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                        GLES20.GL_REPEAT);
     
                GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
                bitmap.recycle();
            }
        }
     
    // 计算折线 OpenGL 坐标
    public void calPolylinePoint(MapStatus mspStatus) {
        PointF[] polyPoints = new PointF[latLngPolygon.size()];
        vertexs = new float[3 * latLngPolygon.size()];
        int i = 0;
        for (LatLng xy : latLngPolygon) {
            // 将地理坐标转换成 openGL 坐标
            polyPoints[i] = mBaiduMap.getProjection().toOpenGLLocation(xy, mspStatus);
            vertexs[i * 3] = polyPoints[i].x;
            vertexs[i * 3 + 1] = polyPoints[i].y;
            vertexs[i * 3 + 2] = 0.0f;
            i++;
        }
        for (int j = 0; j < vertexs.length; j++) {
            Log.d(LTAG, "vertexs[" + j + "]: " + vertexs[j]);
        }
        vertexBuffer = makeFloatBuffer(vertexs);
    }
     
    //创建OpenGL绘制时的顶点Buffer
    private FloatBuffer makeFloatBuffer(float[] fs) {
        ByteBuffer bb = ByteBuffer.allocateDirect(fs.length * 4);
        bb.order(ByteOrder.nativeOrder());
        FloatBuffer fb = bb.asFloatBuffer();
        fb.put(fs);
        fb.position(0);
        return fb;
    }

    结果如下图所示:

    opengl.png

    TextureMapView渲染

    地图SDK为广大开发者新增了TextureMapView类,实现地图由TextureView渲染(使用前提:Android 4.0以上系统,并开启强制GPU渲染),解决原MapView基于系统GLSurfaceView导致在TabHost和scrollView中等闪黑屏、白边、压盖等问题,使用方法与原MapView类似。

    代码如下:

    private TextureMapView mMapView;
    private BaiduMap mBaiduMap;
    mMapView = (TextureMapView) findViewById(R.id.mTexturemap);
    mBaiduMap = mMapView.getMap();

    瓦片图层

    地图SDK自v3.6.0起,新增瓦片图层(tileOverlay), 该图层支持开发者添加自有瓦片数据,包括本地加载和在线下载两种方式。该图层可随地图的平移、缩放、旋转等操作做相应的变换,它仅位于底图之上(即瓦片图层将会遮挡底图,不遮挡其他图层),瓦片图层的添加顺序不会影响其他图层(例如:POI搜索图层、我的位置图层等)的叠加关系,适用于开发者拥有某一区域的地图,并希望使用此区域地图覆盖相应位置的百度地图。


    一、瓦片划分规则:

    百度地图SDK会根据不同的比例尺将地图划分成若干个瓦片,并且以中心点经纬度(0,0)开始计算瓦片,当地图显示缩放级别增大时,每一个瓦片被划分成4 个瓦片。如:

    地图级别为0时,只有1张瓦片

    地图级别为1时,会分成 1 * 4 = 4 张瓦片

    依次类推,

    地图级别为n时,总共划分的瓦片为:4的n次方

    为了保证瓦片的显示效果,第n级的瓦片显示的地图level范围为[n - 0.5, n + 0.5)


    二、瓦片图层分为本地加载和在线下载两种绘制方式。

    1、本地加载方式,将图片打包于应用内,适用于图片较小且不需要频繁变更,通过TileLayer可实现,下面举例分步说明添加本地瓦片图层的步骤:

     // 瓦片图对象
    TileOverlay tileOverlay;
    /**
             * 定义瓦片图的离线Provider,并实现相关接口
             * MAX_LEVEL、MIN_LEVEL 表示地图显示瓦片图的最大、最小级别
             * Tile 对象表示地图每个x、y、z状态下的瓦片对象
             */
            FileTileProvider  tileProvider = new FileTileProvider() {
                @Override
                public Tile getTile(int x, int y, int z) {
                    // 根据地图某一状态下x、y、z加载指定的瓦片图
                    String filedir = "LocalTileImage/" + z + "/" + z + "_" + x + "_" + y + ".jpg";
                    Bitmap bm = getFromAssets(filedir);
                    if (bm == null) {
                        return null;
                    }
                    // 瓦片图尺寸必须满足256 * 256
                    offlineTile = new Tile(bm.getWidth(), bm.getHeight(), toRawData(bm));
                    bm.recycle();
                    return offlineTile;
                }
                @Override
                public int getMaxDisLevel() {
                    return MAX_LEVEL;
                }
                @Override
                public int getMinDisLevel() {
                    return MIN_LEVEL;
                }
            };
       TileOverlayOptions options = new TileOverlayOptions();
       // 构造显示瓦片图范围,当前为世界范围
       LatLng northeast = new LatLng(80, 180);
       LatLng southwest = new LatLng(-80, -180);
       // 设置离线瓦片图属性option
       options.tileProvider(tileProvider)
       .setPositionFromBounds(new LatLngBounds.Builder().include(northeast).include(southwest).build());
       // 通过option指定相关属性,向地图添加离线瓦片图对象
       tileOverlay = mBaiduMap.addTileLayer(options);

    效果如图:

    android-tileioverlay-offline.PNG

    2、 在线下载,将图片存放于开发者提供的服务中,提供给SDK一个URL模板,通过URLTileLayer调用在线瓦片图层的URL,下面举例分步说明添加在线瓦片图层的步骤:

    // 瓦片图对象
    TileOverlay tileOverlay;
    final String urlString = mEditText.getText().toString();
    /**
             * 定义瓦片图的在线Provider,并实现相关接口
             * MAX_LEVEL、MIN_LEVEL 表示地图显示瓦片图的最大、最小级别
             * urlString 表示在线瓦片图的URL地址
             */
            TileProvider tileProvider = new UrlTileProvider() {
                @Override
                public int getMaxDisLevel() {
                    return MAX_LEVEL;
                }
                @Override
                public int getMinDisLevel() {
                    return MIN_LEVEL;
                }
                @Override
                public String getTileUrl() {
                    return urlString;
                }
            };
    TileOverlayOptions options = new TileOverlayOptions();
    // 构造显示瓦片图范围,当前为世界范围
    LatLng northeast = new LatLng(80, 180);
    LatLng southwest = new LatLng(-80, -180);
    // 通过option指定相关属性,向地图添加在线瓦片图对象
    tileOverlay = mBaiduMap.addTileLayer(options.tileProvider(tileProvider).setMaxTileTmp(TILE_TMP).setPositionFromBounds(new LatLngBounds.Builder().include(northeast).include(southwest).build()));

    效果如下:

    xianshangtupian.png

    设置地图区域边界

    v3.7.0起,新增setPadding方法,支持设置地图区域边界,在被定义边距范围内,对显示和操作地图,做了如下两方面的定义。

    (1)百度logo、比例尺、指南针、缩放控件等,可被控制在自定义的地图区域边界内。

    (3)自适应MapStatus中心点坐标,由原屏幕中心点调整至设置的区域中心点。

    当设计的UI与地图部分重叠时,可以设置地图的操作和显示范围,以防止UI遮挡和重叠。

    给地图设置边界,需在OnMapLoadedCallback.onMapLoaded() 回调内设置才生效,设置方法如下:

    // paddingLeft、 paddingTop、 paddingRight、 paddingBottom 
    // 表示距离屏幕左、上、右、下边距离,单位为屏幕坐标下的像素密度
     
    mBaiduMap.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);

    设置地图显示范围

    v3.7.0起新增了设置地图显示范围,手机屏幕仅显示设定的地图范围,当前不支持旋转地图的情况,请与"禁用旋转手势"配合使用。

    使用场景:针对需要展示部分固定范围的地图,如希望设置仅显示北京市区地图,可使用此功能。

    设置地图显示范围,需在OnMapLoadedCallback.onMapLoaded()回调内设置才能生效。

    设置方法如下:

    mBaiduMap.setMapStatusLimits(new LatLngBounds.Builder().include(northeast).include(southwest).build());
  • 相关阅读:
    APP测试--功能测试
    笨方法学python--读文件
    笨方法学python--参数,解包,变量
    Jmeter工具学习(四)——插件安装及使用(转载)
    JMeter工具学习(三)——获取全局变量 token
    FROM_UNIXTIME()时间戳转换函数
    软件测试用例编写规范总结(转载)
    Jmeter之Bean shell使用(二)(转载)
    JMeter工具学习(一)工具使用详细介绍
    JMeter工具学习(二)——获取登录 token
  • 原文地址:https://www.cnblogs.com/kuoAT/p/7380037.html
Copyright © 2011-2022 走看看