本文主要介绍下如何在国家天地图的底图上面使用ArcGIS JS API 4.16加载2000坐标系的倾斜摄影数据。
1、利用esri/layers/BaseTileLayer
这个JS API模块扩展出来一个天地图的图层类,具体代码如下:
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内置的切片方案,所以我们还需要定义一套切片规则来进行两个切片方案的转换,如下:
//定义瓦片结构
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坐标系的倾斜摄影数据即可,代码和最终效果如下:
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);
4、完整代码如下:
//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);
});
};