我们在做可视化开发的时候常常需要下载某些地方的适量地图数据,利用echarts等去渲染相关数据,当然我们完全可以利用GIS技术去实现,但是GIS相对我们比较简单的需求成本有点过大,因为你需要制图、配准、发布,再到前段开发,这样有点得不偿失。
所以我们有时候仅仅需要一个县区的边界,比如我们需要展现“凤翔县”的行政边界我们现在可以这样做
Step 1
打开链接:百度地图API > 覆盖物示例 > 添加行政区划 lbsyun.baidu.com/jsdemo.htm#… 看到如下界面:
注意上图的右边显示了一个北京市的边界。 再看左边的代码里有这么一段话:function getBoundary(){
var bdary = new BMap.Boundary();
bdary.get("北京市海淀区", function(rs){ //获取行政区域
map.clearOverlays(); //清除地图覆盖物
var count = rs.boundaries.length; //行政区域的点有多少个
if (count === 0) {
alert('未能获取当前输入行政区域');
return ;
}
……
复制代码
通过一个GET
请求去获取北京市海淀区
的边界,我们打印出来看看,可以这样做:
function getBoundary(){
var bdary = new BMap.Boundary();
bdary.get("北京市海淀区", function(rs){ //获取行政区域
//--------------------
console.log(rs)
//--------------------
map.clearOverlays(); //清除地图覆盖物
var count = rs.boundaries.length; //行政区域的点有多少个
if (count === 0) {
alert('未能获取当前输入行政区域');
return ;
}
……
复制代码
在控制台看到的结果:
你会发现一个问题:控制台会输出一个数组,内部存储一个字符串,但是太长了没法复制,这里我们可以选择两个办法:- 把这个结果存储到本地
Local Storage
里面,然后去那个里面复制。 - 请看
Step 2
Step 2
改造上面的代码中getBoundary()
函数如下:
function getBoundary(){
var bdary = new BMap.Boundary();
bdary.get("凤翔县", function(rs){ //获取行政区域
map.clearOverlays(); //清除地图覆盖物
var count = rs.boundaries.length; //行政区域的点有多少个
console.log(rs.boundaries);
var content = rs.boundaries
var fileName = '凤翔县.txt'
var aLink = document.createElement('a');
var blob = new Blob([content]);
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, false);
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
aLink.dispatchEvent(evt);
aLink.click();
if (count === 0) {
alert('未能获取当前输入行政区域');
return ;
}
var pointArray = [];
for (var i = 0; i < count; i++) {
var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多边形覆盖物
map.addOverlay(ply); //添加覆盖物
pointArray = pointArray.concat(ply.getPath());
}
map.setViewport(pointArray); //调整视野
addlabel();
});
}
复制代码
点击运行
按钮等待2s会自动下载一个凤翔县.txt
文件,打开后里面的内容如下
107.653733, 34.657435;107.648513, 34.661217;107.625176, 34.705117;107.609942, 34.707262;107.594553, 34.736579;107.584968, 34.730437;107.579062, 34.745847;107.573426, 34.745894;……
复制代码
我们可以使用js的字符串切割方法对其进行以';'
切割,之后再转换成二维数组,然后利用convas、svg
技术描点绘制出来,其中类似107.653733
就是x坐标利用js的经纬度转墨卡托算法
(当然你也可以直接渲染,但保证地图上的点也是经纬度)在将其转换成墨卡托平面直角坐标系坐标,就可以了,当然会得出一个很大的值,我们可以除与共同系数来改变整体渲染结果的大小,我么还可以利用此去绑定鼠标事件。
经纬度转墨卡托算法
没接触过GIS的同学可能不知道这是什么意思,大致是这样的:
大家都知道,地球是个球体,那么经纬度明显表达的是一个度数,直接用其绘制出来的图形不是个平面的会有一定的变形,所以科学家
墨卡托
假想一个与地轴方向一致的圆柱切或割于地球,按等角条件,将经纬网投影到圆柱面上,将圆柱面展为平面后,即得投影。墨卡托投影在切圆柱投影与割圆柱投影中,最早也是最常用的是切圆柱投影。 算法公式在下面:
function _getMercator(poi) {//[114.32894, 30.585748]
var mercator = {};
var earthRad = 6378137.0;//赤道周长
mercator.x = poi.lng * Math.PI / 180 * earthRad;
var a = poi.lat * Math.PI / 180;
mercator.y = earthRad / 2 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
return mercator; //[12727039.383734727, 3579066.6894065146]
}
复制代码