OpenLayers 3 之 加载百度地图


       虽然百度地图有自己的 JavaScript API,但是有时候,一个项目已经用 OpenLayers 做了很多功能,不可能弃之不用,同时,又想使用百度地图,该怎么办呢?所以很多人想使用 OpenLayers 调用百度地图,本文就讨论一下其可能性和实现原理。

一、 地图调用原理分析

      我们以百度地图为例,分析其地图调用原理,我们都使用过百度地图,在网速不快的情况下,肯定有过感受,地图是一块一块加载的,从这里我们就可以看出,地图是被切成了很多块的小图片,调用时按照一定规则请求需要的“切片”,可视区域以外的“切片”不加载,这样可以减小数据传输数据量,使地图加载更快。

我们 F12 查看浏览器的网络图片请求,可以证实我们看到的现象,每一个图片切片都是 256*256 尺寸的图片:

地图请求

图1 地图请求

仔细看每一个请求:

http://online0.map.bdimg.com/onlinelabel/?qt=tile&x=707&y=217&z=12&styles=pl&udt=20151021&scaler=1&p=1

      其中,http://online0.map.bdimg.com/onlinelabel/?,表示百度地图的图片缓存地址;qt=tile 表示请求类型(Quest Type)为 切片(tile);x=707&y=217,请求的切片位于整张地图中的坐标位置;z=12,是指当前的地图缩放级别是 第 12 级,为什么会分级呢?因为浏览地图时我们注意到地图是可以放大缩小的,放大后我们可以看到地物的更多细节,同时 z 值会越大;styles=pl,可能是返回地图的样式;udt=20151021,应该是上一次切片的更新时间(Update DateTime)是2015年10月21号,为什么需要更新地图呢?因为地图是真实世界的抽象,真实世界就是处在不断的变化中的,所以地图要实时更新;至于后两个参数 scaler=1&p=1 ,本人不是百度的员工,就不太清楚是什么了。

所有的“切片”请求,一共有 21 个,用网格形式表示“切片”布局如下图(其中横坐标和纵坐标是由请求 URL 中的 x 和 y 参数决定的):

切片分布示意图

图2 切片分布示意图

       那么我们清楚了地图请求的原理,下一步就是要验证一下请求百度的地图是否需要一定的权限呢?我们点击每一个请求的 URL ,可以看到其对应的图片,说明不需要特殊的权限便可以访问百度的切片地图,这样我们就可以自己编写程序来调用百度的切片地图。

二、 编写调用程序

       现在,我们要着手编写程序调用百度地图了,最终的结果是在浏览器中显示地图,那么我们首先要根据用户的交互确定两个主要的参数:缩放级别、视图中需要的切片 x y 索引。然后构造相应的请求 URL,再按照相应的索引拼接地图切片,这样我们就能完成调用地图了。

       好了,讲完原理,我们是否要马上就开始着手编写吗?不要这么着急下手,我们在开始一项任务的时候,首先在比如 GitHub 的开源项目网站上寻找一下是否有已经实现你需要功能的开源项目,要尽量避免重复造轮子。OpenLayers 便是我们理想的 JavaScript 工具库,实现了大部分我们需要的操作,所以我们不必再需要自己从头开始构建。

首先贴出实现调用效果图:

OpenLayers调用百度地图

图3 OpenLayers 3 调用百度地图

2.1 关键代码

下面是调用的关键代码:

<script type="text/javascript">
    var projection = ol.proj.get("EPSG:3857");
    var resolutions = [];
    for(var i=0; i<19; i++){
        resolutions[i] = Math.pow(2, 18-i);
    }
    var tilegrid  = new ol.tilegrid.TileGrid({
        origin: [0,0],
        resolutions: resolutions
    });

    var baidu_source = new ol.source.TileImage({
        projection: projection,
        tileGrid: tilegrid,
        tileUrlFunction: function(tileCoord, pixelRatio, proj){
            if(!tileCoord){
                return "";
            }
            var z = tileCoord[0];
            var x = tileCoord[1];
            var y = tileCoord[2];

            if(x<0){
                x = "M"+(-x);
            }
            if(y<0){
                y = "M"+(-y);
            }

            return "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x="+x+"&y="+y+"&z="+z+"&styles=pl&udt=20151021&scaler=1&p=1";
        }
    });

    var baidu_layer = new ol.layer.Tile({
        source: baidu_source
    });

    var map = new ol.Map({
        target: 'map',
        layers: [baidu_layer],
        view: new ol.View({
            center:  [12959773,4853101],
            zoom: 12
        })
    });
</script>

注:
1、页面需要引用 openlayers 3.10.1, js 和 css
2、页面需要有一个 DIV 元素,其 ID 属性为 “map”


       我们分析一下以上的关键代码,首先,初始化一个图片切片地图数据源,var baidu_source = new ol.source.TileImage({})ol.source.TileImage 是 OpenLayers 中专门负责调用地图以切片图片存放的类,其中给定了三个参数,projection 参数指定了地图切片使用的坐标系,一般是 EPSG:3857(球形墨卡托投影坐标系),谷歌地图、必应地图都是使用的这个坐标系,可以说是国际通用的惯例,tileGrid 指定了切片使用的网格的模式,tileUrlFunction 指定一个回调函数,这个回掉函数第一个参数中包含三个变量,主要是 当前缩放级别(z),切片的 x y 索引,每次用户与地图交互,比如 缩放、平移等,就会触发会触发回调函数,该函数根据传入的变量参数构造图片切片的 URL 地址。

       然后,使用图片切片地图数据源初始化一个 切片图层: var baidu_layer = new ol.layer.Tile({source: baidu_source }); 最后将图层加入到地图中(最后一段代码),这样我们就完成了核心代码,刷新页面,你就会看到上图的效果。

三、 总结

       结果表明,使用 OpenLayers 3 可以成功调用百度地图。文章里主要讲了百度地图的切片地图的调用原理,并简要阐释了切片地图的组织结构,以及使用 OpenLayers 3 调用百度地图的关键代码。

       本文并没有对其他的地图做实验,如 谷歌地图、必应地图、腾讯地图、搜狗地图、天地图等地图。如果需要使用相关地图,你可以使用本文的方法检查其可用性,找出其请求规律,然后根据实际情况构造 URL ,替换关键代码中 tileUrlFunction 中 return 的URL。

好的,就写到这里,有什么问题,可以到文章下面评论。

参考文章

1、 http://blog.liuyx.net/?p=240

转载自:https://blog.csdn.net/qingyafan/article/details/49403989

You may also like...