基于ArcGIS API for JavaScript加载百度各种类型切片地图
原创giao00000 最后发布于2019-03-24 23:01:13 阅读数 923 收藏
展开
文章目录
应用场景
需求分析
效果图
实现代码
原理解读
应用场景
部分项目基于ArcGIS平台,但是甲方只提供部分矢量数据,用作底图的地形图数据没有,表示可以使用百度地图作为底图。所以才会有使用ArcGIS JS API加载百度地图的这种特殊需求。
需求分析
上面描述的需求场景有两种解决方案:
下载指定区域的百度地图(.tif格式),将下载好的地图在ArcMap中处理之后,通过ArcGIS Server发布成切片地图服务,之后就可以直接用API加载了。问题在于需要借助地图下载工具下载数据,数据量可能会比较大。
基于ArcGIS API for JavaScript中的TiledMapServiceLayer类进行扩展,直接使用百度地图在线切片。优势:数据无需单独下载,可以使用百度各种类型切片地图,如道路、午夜黑等。
这里通过方案二入手。
效果图
实现代码
封装模块:BaiduLayer.js
define(["dojo/_base/declare", "esri/layers/TiledMapServiceLayer", "esri/geometry/Extent", "esri/SpatialReference", "esri/layers/TileInfo"],
function (declare, TiledMapServiceLayer, Extent, SpatialReference, TileInfo) {
return declare(TiledMapServiceLayer, {
layertype: "midNightStyle", //图层类型
baiduAK: "1H8Dhi2pGmOMYbN4EcaAGr1rv8f7Gmjz", //百度开发密钥
// 构造函数
constructor: function (properties) {
this.spatialReference = new SpatialReference({
wkid: 102100 //webMercator投影
});
declare.safeMixin(this, properties);
// 图层提供的起始显示范围以及整个图层的地理范围
// this.fullExtent = new Extent(-16777360, -16797630, 16777360, 16797630, this.spatialReference);
this.fullExtent = new Extent(-20037508.342787, -20037508.342787, 20037508.342787, 20037508.342787, this.spatialReference);
this.initialExtent = new Extent(5916776.8, 1877209.3, 19242502.6, 7620381.8, this.spatialReference);
// 图层提供的切片信息
this.tileInfo = new TileInfo({
"rows": 256,
"cols": 256,
"compressionQuality": 0,
"origin": {
"x": -16777360, //济南适用
"y": 16802960
},
"spatialReference": {
"wkid": 102100
},
"lods": [{
"level": 0,
"resolution": 131072,
"scale": 131072 * 256
},
{
"level": 1,
"resolution": 65536,
"scale": 65536 * 256
},
{
"level": 2,
"resolution": 32768,
"scale": 32768 * 256
},
{
"level": 3,
"resolution": 16384,
"scale": 16384 * 256
},
{
"level": 4,
"resolution": 8192,
"scale": 8192 * 256
},
{
"level": 5,
"resolution": 4096,
"scale": 4096 * 256
},
{
"level": 6,
"resolution": 2048,
"scale": 2048 * 256
},
{
"level": 7,
"resolution": 1024,
"scale": 1024 * 256
},
{
"level": 8,
"resolution": 512,
"scale": 512 * 256
},
{
"level": 9,
"resolution": 256,
"scale": 256 * 256
},
{
"level": 10,
"resolution": 128,
"scale": 128 * 256
},
{
"level": 11,
"resolution": 64,
"scale": 64 * 256
},
{
"level": 12,
"resolution": 32,
"scale": 32 * 256
},
{
"level": 13,
"resolution": 16,
"scale": 16 * 256
},
{
"level": 14,
"resolution": 8,
"scale": 8 * 256
},
{
"level": 15,
"resolution": 4,
"scale": 4 * 256
},
{
"level": 16,
"resolution": 2,
"scale": 2 * 256
},
{
"level": 17,
"resolution": 1,
"scale": 1 * 256
},
{
"level": 18,
"resolution": 0.5,
"scale": 0.5 * 256
},
{
"level": 19,
"resolution": 0.25,
"scale": 0.25 * 256
}
]
});
// 设置图层的loaded属性,并触发onLoad事件
this.loaded = true;
this.onLoad(this);
},
getTileUrl: function (level, row, col) {
var url = "";
var zoom = level - 1;
var offsetX = Math.pow(2, zoom);
var offsetY = offsetX - 1;
var numX = col - offsetX;
var numY = (-row) + offsetY;
zoom = level + 1;
var num = (col + row) % 8 + 1;
switch (this.layertype) {
case "road":
url = "http://online1.map.bdimg.com/tile/?qt=tile&x=" + numX + "&y=" + numY + "&z=" + zoom + "&styles=pl";
break;
case "st":
//url = "http://q"+num+".baidu.com/it/u=x="+numX+";y="+numY+";z="+zoom+";v=009;type=sate&fm=46";
url = "http://shangetu" + num + ".map.bdimg.com/it/u=x=" + numX + ";y=" + numY + ";z=" + zoom + ";v=009;type=sate&fm=46";
break;
case "label":
url = "http://online1.map.bdimg.com/tile/?qt=tile&x=" + numX + "&y=" + numY + "&z=" + zoom + "&styles=sl&v=020";
break;
case "simpleStyle":
url = "http://api1.map.bdimg.com/customimage/tile?&x=" + numX + "&y=" + numY + "&z=" + zoom + "&ak=" + this.baiduAK + "&styles=t%3Aroad%7Ce%3Aall%7Cl%3A20%2Ct%3Ahighway%7Ce%3Ag%7Cc%3A%23f49935%2Ct%3Arailway%7Ce%3Aall%7Cv%3Aoff%2Ct%3Alocal%7Ce%3Al%7Cv%3Aoff%2Ct%3Awater%7Ce%3Aall%7Cc%3A%23d1e5ff%2Ct%3Apoi%7Ce%3Al%7Cv%3Aoff";
break;
case "grassGreenStyle":
url = "http://api0.map.bdimg.com/customimage/tile?&x=" + numX + "&y=" + numY + "&z=" + zoom + "&ak=" + this.baiduAK + "&styles=t%3Awater%7Ce%3Aall%7Cc%3A%2372b8fe%2Ct%3Aroad%7Ce%3Ag.f%7Cc%3A%23ffffff%2Ct%3Aroad%7Ce%3Ag.s%7Cc%3A%23bababa%2Ct%3Aroad%7Ce%3Al.t.f%7Cc%3A%23767676%2Ct%3Aroad%7Ce%3Al.t.s%7Cc%3A%23ffffff%2Ct%3Aland%7Ce%3Aall%7Cc%3A%23b8cb93";
break;
case "midNightStyle":
url = "http://api1.map.bdimg.com/customimage/tile?&x=" + numX + "&y=" + numY + "&z=" + zoom + "&ak=" + this.baiduAK + "&styles=t%3Awater%7Ce%3Aall%7Cc%3A%23021019%2Ct%3Ahighway%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Ahighway%7Ce%3Ag.s%7Cc%3A%23147a92%2Ct%3Aarterial%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Aarterial%7Ce%3Ag.s%7Cc%3A%230b3d51%2Ct%3Alocal%7Ce%3Ag%7Cc%3A%23000000%2Ct%3Aland%7Ce%3Aall%7Cc%3A%2308304b%2Ct%3Arailway%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Arailway%7Ce%3Ag.s%7Cc%3A%2308304b%2Ct%3Asubway%7Ce%3Ag%7Cl%3A-70%2Ct%3Abuilding%7Ce%3Ag.f%7Cc%3A%23000000%2Ct%3Aall%7Ce%3Al.t.f%7Cc%3A%23857f7f%2Ct%3Aall%7Ce%3Al.t.s%7Cc%3A%23000000%2Ct%3Abuilding%7Ce%3Ag%7Cc%3A%23022338%2Ct%3Agreen%7Ce%3Ag%7Cc%3A%23062032%2Ct%3Aboundary%7Ce%3Aall%7Cc%3A%231e1c1c%2Ct%3Amanmade%7Ce%3Ag%7Cc%3A%23022338%2Ct%3Apoi%7Ce%3Aall%7Cv%3Aoff%2Ct%3Aall%7Ce%3Al.i%7Cv%3Aoff%2Ct%3Aall%7Ce%3Al.t.f%7Cv%3Aon%7Cc%3A%232da0c6";
break;
case "darkStyle":
url = "http://api2.map.bdimg.com/customimage/tile?&x=" + numX + "&y=" + numY + "&z=" + zoom + "&ak=" + this.baiduAK + "&styles=t%3Aland%7Ce%3Ag%7Cc%3A%23212121%2Ct%3Abuilding%7Ce%3Ag%7Cc%3A%232b2b2b%2Ct%3Ahighway%7Ce%3Aall%7Cl%3A-42%7Cs%3A-91%2Ct%3Aarterial%7Ce%3Ag%7Cl%3A-77%7Cs%3A-94%2Ct%3Agreen%7Ce%3Ag%7Cc%3A%231b1b1b%2Ct%3Awater%7Ce%3Ag%7Cc%3A%23181818%2Ct%3Asubway%7Ce%3Ag.s%7Cc%3A%23181818%2Ct%3Arailway%7Ce%3Ag%7Cl%3A-52%2Ct%3Aall%7Ce%3Al.t.s%7Cc%3A%23313131%2Ct%3Aall%7Ce%3Al.t.f%7Cc%3A%238b8787%2Ct%3Amanmade%7Ce%3Ag%7Cc%3A%231b1b1b%2Ct%3Alocal%7Ce%3Ag%7Cl%3A-75%7Cs%3A-91%2Ct%3Asubway%7Ce%3Ag%7Cl%3A-65%2Ct%3Arailway%7Ce%3Aall%7Cl%3A-40%2Ct%3Aboundary%7Ce%3Ag%7Cc%3A%238b8787%7Cl%3A-29%7Cw%3A1";
break;
default:
url = "http://online1.map.bdimg.com/tile/?qt=tile&x=" + numX + "&y=" + numY + "&z=" + zoom + "&styles=pl";
break;
}
return url;
}
});
}
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ArcGIS调用百度在线切片</title>
</head>
<link rel="stylesheet" href="https://js.arcgis.com/3.27/esri/css/esri.css">
<style>
html, body, #map {
height: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
var package_path = window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/'));
var dojoConfig = {
// The locationPath logic below may look confusing but all its doing is
// enabling us to load the api from a CDN and load local modules from the correct location.
packages: [{
name: "modules",
location: package_path + '/modules'
}]
};
</script>
<script src="https://js.arcgis.com/3.27/"></script>
<script>
require([
"esri/map",
"modules/BaiduLayer",
"dojo/domReady!"], function(Map,BaiduLayer) {
var map = new Map("map");
var options = {
layertype: "darkStyle"
}
var layer = new BaiduLayer(options);
map.addLayer(layer);
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
原理解读
以下为个人见解,如有不当敬请指出,核心代码主要在getTile这块:
getTileUrl: function (level, row, col) {
var url = "";
var zoom = level - 1;
var offsetX = Math.pow(2, zoom);
var offsetY = offsetX - 1;
var numX = col - offsetX;
var numY = (-row) + offsetY;
zoom = level + 1;
var num = (col + row) % 8 + 1;
url = "http://api2.map.bdimg.com/customimage/tile?&x=" + numX + "&y=" + numY + "&z=" + zoom + "&ak=" + this.baiduAK + '太长了省略';
return url;
}
1
2
3
4
5
6
7
8
9
10
11
12
关键在于切片坐标的转换,通过下图可以看到ArcGIS切片坐标定义方式:
ArcGIS的切片坐标定义方式是从左上角开始,按照行列号划分。高德地图、Open Street Map、Google地图同样采用此种切片方式。
百度地图切片坐标定义方式如下图:
两者的切片坐标系不太一样,要想将切片放到正确的位置就要进行坐标转换了,公式已经在代码里面里了,就是简单的数学转换。关于国内主要地图瓦片坐标系定义及计算原理
源代码下载地址:https://download.csdn.net/download/wml00000/11055976
————————————————
版权声明:本文为CSDN博主「giao00000」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wml00000/article/details/88784277
网友评论