0%

ArcGIS JS API 4.16实现三维场景中在天地图底图上加载2000坐标系的倾斜摄影数据

本文主要介绍下如何在国家天地图的底图上面使用ArcGIS JS API 4.16加载2000坐标系的倾斜摄影数据。

所需数据

  • 国家天地图官网数据服务作为底图
  • 自己发布的GCS 2000地理坐标系的倾斜摄影数据服务,对应wkid为4490
  • ArcGIS JS API 4.16 最新版

操作步骤

1、利用esri/layers/BaseTileLayer这个JS API模块扩展出来一个天地图的图层类,具体代码如下:

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
let TdtLayer = BaseTileLayer.createSubclass({
properties: {
urlTemplate: null,
tint: {
value: null,
type: Color,
},
subDomains: null,
},
getTileUrl: function (level, row, col) {
return this.urlTemplate
.replace('{level}', level)
.replace('{col}', col)
.replace('{row}', row)
.replace(
'{subDomain}',
this.subDomains[Math.round(Math.random() * (this.subDomains.length - 1))],
);
},
fetchTile: function (level, row, col, options) {
let url = this.getTileUrl(level + 1, row, col);
return esriRequest(url, {
responseType: 'image',
//新增下面两句,解决乱片问题
allowImageDataAccess: true,
signal: options.signal,
}).then(
function (response) {
let image = response.data;
let width = this.tileInfo.size[0];
let height = this.tileInfo.size[0];
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
if (this.tint) {
context.fillStyle = this.tint.toCss();
context.fillRect(0, 0, width, height);
context.globalCompositeOperation = 'difference';
}
context.drawImage(image, 0, 0, width, height);
return canvas;
}.bind(this),
);
},
});

2、因为国家天地图官网的切片服务用的切片方案是国家天地图切片方案,ArcGIS JS API虽然从4.12版本开始支持三维场景中加载2000坐标系服务,但是2000坐标系的切片服务目前仅支持ArcGIS Pro内置的切片方案,所以我们还需要定义一套切片规则来进行两个切片方案的转换,如下:

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
//定义瓦片结构
let tileInfo = new TileInfo({
//"dpi": 90.71428571428571,
dpi: 96,
rows: 256,
cols: 256,
compressionQuality: 0,
origin: {
x: -180,
y: 90,
},
spatialReference: {
wkid: 4490,
},
lods: [
{ level: 0, resolution: 0.703125, scale: 295829355.454566 },
{ level: 1, resolution: 0.3515625, scale: 147914677.727283 },
{ level: 2, resolution: 0.17578125, scale: 73957338.863641 },
{ level: 3, resolution: 0.087890625, scale: 36978669.431821 },
{ level: 4, resolution: 0.0439453125, scale: 18489334.71591 },
{ level: 5, resolution: 0.02197265625, scale: 9244667.357955 },
{ level: 6, resolution: 0.010986328125, scale: 4622333.678978 },
{ level: 7, resolution: 0.0054931640625, scale: 2311166.839489 },
{ level: 8, resolution: 0.00274658203125, scale: 1155583.419744 },
{ level: 9, resolution: 0.001373291015625, scale: 577791.709872 },
{ level: 10, resolution: 0.0006866455078125, scale: 288895.854936 },
{ level: 11, resolution: 0.00034332275390625, scale: 144447.927468 },
{ level: 12, resolution: 0.000171661376953125, scale: 72223.963734 },
{ level: 13, resolution: 8.58306884765625e-5, scale: 36111.981867 },
{ level: 14, resolution: 4.291534423828125e-5, scale: 18055.990934 },
{ level: 15, resolution: 2.1457672119140625e-5, scale: 9027.995467 },
{ level: 16, resolution: 1.0728836059570313e-5, scale: 4513.997733 },
{ level: 17, resolution: 5.3644180297851563e-6, scale: 2256.998867 },
{ level: 18, resolution: 0.000002682209014892578, scale: 1128.499433 },
],
});

3、接下来,实例化天地图服务图层作为三维场景的底图,然后添加我们2000坐标系的倾斜摄影数据即可,代码和最终效果如下:

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
let tiledLayer = new TdtLayer({
urlTemplate:
'http://{subDomain}.tianditu.com/vec_c/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=vec&STYLE=default&FORMAT=tiles&TILEMATRIXSET=c&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=申请的密钥',
subDomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
tileInfo: tileInfo,
});
let tdtzjLayer = new TdtLayer({
urlTemplate:
'http://{subDomain}.tianditu.com/cva_c/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=cva&STYLE=default&FORMAT=tiles&TILEMATRIXSET=c&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=申请的密钥',
subDomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
tileInfo: tileInfo,
});
let map = new Map({
spatialReference: {
wkid: 4490,
},
basemap: {
baseLayers: [tiledLayer],
referenceLayers: [tdtzjLayer],
},
});
let mapView = new SceneView({
container: 'mainView',
spatialReference: {
wkid: 4490,
},
map: map,
center: {
x: 117,
y: 39,
spatialReference: {
wkid: 4490,
},
},
});
let layer01 = new IntegratedMeshLayer({
url: 'http://www.arcgisonline.cn/server/rest/services/Hosted/Production_4/SceneServer',
//copyright: "VRICON"
});
mapView.map.add(layer01);

img

img

4、完整代码如下:

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
//4.16 加载天地图并添加倾斜摄影数据
_initSceneView416 = () => {
const _self = this;
const options = {
url: 'https://js.arcgis.com/4.16/init.js',
css: 'https://js.arcgis.com/4.16/esri/themes/light/main.css',
};
loadModules(
[
'esri/Color',
'esri/request',
'esri/layers/BaseTileLayer',
'esri/Map',
'esri/views/SceneView',
'esri/layers/support/TileInfo',
'esri/layers/IntegratedMeshLayer',
],
options,
)
.then(([Color, esriRequest, BaseTileLayer, Map, SceneView, TileInfo, IntegratedMeshLayer]) => {
let TdtLayer = BaseTileLayer.createSubclass({
properties: {
urlTemplate: null,
tint: {
value: null,
type: Color,
},
subDomains: null,
},
getTileUrl: function (level, row, col) {
return this.urlTemplate
.replace('{level}', level)
.replace('{col}', col)
.replace('{row}', row)
.replace(
'{subDomain}',
this.subDomains[Math.round(Math.random() * (this.subDomains.length - 1))],
);
},
fetchTile: function (level, row, col, options) {
let url = this.getTileUrl(level + 1, row, col);
return esriRequest(url, {
responseType: 'image',
//新增下面两句,解决乱片问题
allowImageDataAccess: true,
signal: options.signal,
}).then(
function (response) {
let image = response.data;
let width = this.tileInfo.size[0];
let height = this.tileInfo.size[0];
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
if (this.tint) {
context.fillStyle = this.tint.toCss();
context.fillRect(0, 0, width, height);
context.globalCompositeOperation = 'difference';
}
context.drawImage(image, 0, 0, width, height);
return canvas;
}.bind(this),
);
},
});
//定义瓦片结构
let tileInfo = new TileInfo({
//"dpi": 90.71428571428571,
dpi: 96,
rows: 256,
cols: 256,
compressionQuality: 0,
origin: {
x: -180,
y: 90,
},
spatialReference: {
wkid: 4490,
},
lods: [
{ level: 0, resolution: 0.703125, scale: 295829355.454566 },
{ level: 1, resolution: 0.3515625, scale: 147914677.727283 },
{ level: 2, resolution: 0.17578125, scale: 73957338.863641 },
{ level: 3, resolution: 0.087890625, scale: 36978669.431821 },
{ level: 4, resolution: 0.0439453125, scale: 18489334.71591 },
{ level: 5, resolution: 0.02197265625, scale: 9244667.357955 },
{ level: 6, resolution: 0.010986328125, scale: 4622333.678978 },
{ level: 7, resolution: 0.0054931640625, scale: 2311166.839489 },
{ level: 8, resolution: 0.00274658203125, scale: 1155583.419744 },
{ level: 9, resolution: 0.001373291015625, scale: 577791.709872 },
{ level: 10, resolution: 0.0006866455078125, scale: 288895.854936 },
{ level: 11, resolution: 0.00034332275390625, scale: 144447.927468 },
{ level: 12, resolution: 0.000171661376953125, scale: 72223.963734 },
{ level: 13, resolution: 8.58306884765625e-5, scale: 36111.981867 },
{ level: 14, resolution: 4.291534423828125e-5, scale: 18055.990934 },
{ level: 15, resolution: 2.1457672119140625e-5, scale: 9027.995467 },
{ level: 16, resolution: 1.0728836059570313e-5, scale: 4513.997733 },
{ level: 17, resolution: 5.3644180297851563e-6, scale: 2256.998867 },
{ level: 18, resolution: 0.000002682209014892578, scale: 1128.499433 },
],
});
let tiledLayer = new TdtLayer({
urlTemplate:
'http://{subDomain}.tianditu.com/vec_c/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=vec&STYLE=default&FORMAT=tiles&TILEMATRIXSET=c&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=ac0daf56728bbb77d9514ba3df69bcd3',
subDomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
tileInfo: tileInfo,
});
let tdtzjLayer = new TdtLayer({
urlTemplate:
'http://{subDomain}.tianditu.com/cva_c/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=cva&STYLE=default&FORMAT=tiles&TILEMATRIXSET=c&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=ac0daf56728bbb77d9514ba3df69bcd3',
subDomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
tileInfo: tileInfo,
});
let map = new Map({
spatialReference: {
wkid: 4490,
},
basemap: {
baseLayers: [tiledLayer],
referenceLayers: [tdtzjLayer],
},
});
let mapView = new SceneView({
container: 'mainView',
spatialReference: {
wkid: 4490,
},
map: map,
center: {
x: 117,
y: 39,
spatialReference: {
wkid: 4490,
},
},
});
let layer01 = new IntegratedMeshLayer({
url: 'http://www.arcgisonline.cn/server/rest/services/Hosted/Production_4/SceneServer',
//copyright: "VRICON"
});
mapView.map.add(layer01);
})
.catch((err) => {
console.log('三维场景实例化失败:', err);
});
};