夜已深,天很冷,简单写点,以慰藉这几天的成果。
由于项目需要,也源于程序员的强迫,总是想基于webappbuilder+arcgis for js4.系列,做一个不依赖portal的源码。
经过测试,已经试验成功,并成功添加天地图。
环境:webappbuilder2.6+arcgis for js 4.5。
还是基于webstorm开发,在vs2017下弄过,虽然可以调试js,但感觉很慢,反正就是结合vs、记事本、webstorm等,你懂的。
一、前期准备
很简单,有portal,官网上下载web appbuilder,经过一路下来,生成一个3D的应用程序。
注意:一定要生成一个3D的应用程序,因为,webappbuilder的3D程序是基于arcgis js 4系列,因此,生成一个3D应用程序,在该代码基础上进行修改。
准备完成后,就需要改造代码了。
二、代码改造
其实代码改造很简单,就改几个地方就可以了。
1、拷贝jimu.js文件夹下的WebSceneLoader.js文件,重命名为WebMapLoader.js,对其进行改造,使其能够加载二维地图数据,代码如下:
/ Copyright © 2014 - 2017 Esri. All Rights Reserved. Licensed under the Apache License Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.///define([
'dojo/Deferred',
'dojo/_base/lang',
'dojo/_base/array',
'dojo/_base/html',
'dojo/promise/all',
'esri/kernel',
'esri/Map',
'esri/WebMap',
'esri/views/MapView',
"esri/layers/GraphicsLayer",
'esri/portal/Portal',
'esri/portal/PortalItem',
'esri/core/sniff',
'./utils',
'./portalUtils',
'./portalUrlUtils'], function(Deferred, lang, array, html, all, esriNS, Map,WebMap, MapView,GraphicsLayer,Portal, PortalItem,has,
jimuUtils, portalUtils, portalUrlUtils) {
var mo = {
createMap: function(mapDivId, portalUrl, itemId,mapOptions) {
var def = new Deferred();
def = this._createMap(mapDivId, portalUrl, itemId,mapOptions);
return def;
},
_createMapNoPortal: function(mapDivId,mapOptions) {
var def = new Deferred();
var map = new Map();
map.id = mapDivId;
if(!mapOptions)
{
mapOptions = {};
}
mapOptions.map = map;
mapOptions.container = mapDivId;
var mapView = new MapView(mapOptions);
//, //extent:new Extent({ // xmin:-180, // ymin:-90, // xmax:180, // yamx:90, // sptialReference:new SpatialReference({ // wkid:4326 // }) //必须加上这个图层,否则,球不显示 var graphicsLayer = new GraphicsLayer();
mapView.map.add(graphicsLayer); //addLayer //this._handleLocalScene(mapView); def.resolve(mapView);
return def;
},
_createMap: function (mapDivId, portalUrl, itemId,mapOptions) {
if (!portalUrl)
{
return this._createMapNoPortal(mapDivId,mapOptions);
}
var esriConfig = jimuUtils.getEsriConfig();
esriConfig.portalUrl = portalUrlUtils.getStandardPortalUrl(portalUrl);
var def = new Deferred();
var defs = [];
/************************************************************ * Creates a new WebScene instance. A WebScene must reference * a PortalItem ID that represents a WebScene saved to * arcgis.com or an on premise portal. * * To load a WebScene from an onpremise portal, set the portal * url in esriConfig.portalUrl. ************************************************************/ Portal._default = null;
var map = new WebMap({
portalItem: new PortalItem({
id: itemId
})
});
/************************************************************ * Set the WebScene instance to the map property in a SceneView. ************************************************************/ //we add extra attribute 'view' for scene // View can emit 'resize' event var mapView = new MapView({
map: map,
container: mapDivId
});
defs.push(map);
defs.push(mapView);
var portal = portalUtils.getPortal(portalUrl);
defs.push(portal.getItemById(itemId));
defs.push(portal.getItemData(itemId));
all(defs).then(lang.hitch(this, function(results) {
if(mapView.popup){
mapView.popup.closeOnViewChangeEnabled = true;
}
map.id = mapDivId;
map.itemId = itemId;
map.itemInfo = {
item: results[2],
itemData: results[3]
};
this._handleLocalScene(mapView);
def.resolve(mapView);
//this._handleAttribution(sceneView); }), lang.hitch(this, function(err) {
console.error(err);
def.reject(err);
}));
return def;
},
_handleLocalScene: function (sceneView) {
try {
if (sceneView.viewingMode && sceneView.viewingMode.toLowerCase() === 'local') {
lang.setObject("constraints.collision.enabled", false, sceneView);
lang.setObject("constraints.tilt.max", 179.99, sceneView);
}
} catch (e) {
console.error(e);
}
}
};
return mo;
});
WebSceneLoader.js文件也做相应改造,其实和map的差不多,不贴代码了。
2、MapManager.js文件改造
(1)添加webmaploader.js文件的支持
define([
'dojo/_base/declare',
'dojo/_base/lang',
'dojo/_base/array',
'dojo/_base/html',
'dojo/topic',
'dojo/on',
// 'dojo/aspect', 'dojo/keys',
// 'dojo/Deferred', // 'esri/dijit/InfoWindow', // "esri/dijit/PopupMobile", // 'esri/InfoTemplate', 'esri/geometry/Extent',
'esri/geometry/Point',
'./utils',
'./dijit/LoadingShelter',
// 'jimu/LayerInfos/LayerInfos', // './MapUrlParamsHandler', './AppStateManager',
'./WebSceneLoader',
'./WebMapLoader',
'esri/Viewpoint','esri/geometry/SpatialReference'], function(declare, lang, array, html, topic, on,/* aspect,*/ keys,/* Deferred, InfoWindow, PopupMobile, InfoTemplate,*/ Extent, Point, jimuUtils, LoadingShelter, /*LayerInfos, MapUrlParamsHandler,*/ AppStateManager, WebSceneLoader, WebMapLoader, Viewpoint,SpatialReference) {
(2)
_showMap函数改造
_showMap: function(appConfig) {
// console.timeEnd('before map'); console.time('Load Map');
this.loading = new LoadingShelter();
this.loading.placeAt(this.mapDivId);
this.loading.startup();
//for now, we can't create both 2d and 3d map if (appConfig.map['3D']) {
this._show3DWebScene(appConfig,true);
} else {
this._show3DWebScene(appConfig,false);
}
},
(3)_show3DWebScene函数改造
_show3DWebScene: function(appConfig,is3D) {
var portalUrl = appConfig.map.portalUrl;
var itemId = appConfig.map.itemId;
this._destroySceneView();
var def;
if(is3D)
{
def = WebSceneLoader.createMap(this.mapDivId, portalUrl, itemId,appConfig.map.mapOptions);
}
else {
def = WebMapLoader.createMap(this.mapDivId, portalUrl, itemId,appConfig.map.mapOptions);
}
def.then(lang.hitch(this, function(sceneView){
this._publishSceneViewEvent(sceneView);
if(appConfig.map.mapOptions){
var initialState = appConfig.map.mapOptions.initialState;
if(initialState && initialState.viewpoint){
try{
var vp = Viewpoint.fromJSON(initialState.viewpoint);
if(vp){
this.sceneView.map.initialViewProperties.viewpoint = vp;
this.sceneView.viewpoint = vp.clone();
}
}catch(e){
console.error(e);
}
}
}
}), lang.hitch(this, function(){
if (this.loading) {
this.loading.destroy();
}
topic.publish('mapCreatedFailed');
}));
},
(4)添加根据配置文件添加函数
主要代码如下:
_publishSceneViewEvent: function(sceneView){
window._sceneView = sceneView;
console.timeEnd('Load Map');
if(this.loading){
this.loading.destroy();
}
if(this.sceneView){
this.sceneView = sceneView;
//this.resetInfoWindow(true); console.log("sceneView changed");
topic.publish('sceneViewChanged', this.sceneView);
}else{
this.sceneView = sceneView;
//this.resetInfoWindow(true); console.log("sceneView loaded");
topic.publish('sceneViewLoaded', this.sceneView);
}
//添加图层 this._visitConfigMapLayers(this.appConfig, lang.hitch(this, function(layerConfig,i) {
this.createLayer(sceneView.map, layerConfig,i);
}));
},_visitConfigMapLayers: function(appConfig, cb) {
array.forEach(appConfig.map.basemaps, function(layerConfig, i) {
cb(layerConfig, i);
}, this);
},createLayer: function(map, layerConfig,index) {
if(!map || !layerConfig || !layerConfig.type)
{
return;
}
var layMap = {
'mapserver': 'esri/layers/MapImageLayer',
'imageserver': 'esri/layers/ImageryLayer',
'feature': 'esri/layers/FeatureLayer',
"elevation":'esri/layers/ElevationLayer',
'tile': 'esri/layers/TileLayer',
'kml': 'esri/layers/KMLLayer',
'webtile': 'esri/layers/WebTileLayer',
'wms': 'esri/layers/WMSLayer',
'wmts': 'esri/layers/WMTSLayer',
'google':'jimu/layers/GoogleLayer',
'tianditu':'jimu/layers/TianDiTuLayer' };
require([layMap[layerConfig.type.toLowerCase()]], lang.hitch(this, function(layerClass) {
var layer;
layer = new layerClass(layerConfig.options);
var lyrIndex = layerConfig.index;
if(layer.customLayer)
{
map.add(layer.customLayer,undefined == lyrIndex ? index : lyrIndex);
}
else {
map.add(layer,undefined == lyrIndex ? index : lyrIndex);
}
}));
},
3、ConfigLoader.js文件改造
(1)loadConfig函数
直接上图
loadConfig: function () {
console.time('Load Config');
return this._tryLoadConfig().then(lang.hitch(this, function(appConfig) {
var err = this.checkConfig(appConfig);
if (err) {
throw err;
}
this.rawAppConfig = lang.clone(appConfig);
AppStateManager.getInstance().setRawAppConfig(this.rawAppConfig);
appConfig = this._upgradeAppConfig(appConfig);
this._processAfterTryLoad(appConfig);
this.appConfig = appConfig;
if (!appConfig.portalUrl) {
return this._processNotInPortalAppProtocol(appConfig).then(lang.hitch(this, function () {
this._processAfterTryLoad(appConfig);
this.appConfig = appConfig;
})).then(lang.hitch(this, function () {
return this.loadWidgetsManifest(appConfig);
})).then(lang.hitch(this, function () {
return this._upgradeAllWidgetsConfig(appConfig)
})).then(lang.hitch(this, function () {
this.appConfig = appConfig;
this._configLoaded = true;
if (appConfig.title) {
document.title = jimuUtils.stripHTML(appConfig.title);
}
this._readAndSetSharedTheme(appConfig);
return this.getAppConfig();
}), lang.hitch(this, function (err) {
this.showError(err);
}));
}
else if(this.urlParams.id){
(2)_processAfterTryLoad函数
直接上图
_processAfterTryLoad: function(appConfig){
if (appConfig.portalUrl) {
this._setPortalUrl(appConfig);
this._tryUpdateAppConfigByLocationUrl(appConfig);
this._processUrlParams(appConfig);
}
this.addNeedValues(appConfig);
this.processProxy(appConfig);
IdentityManager.tokenValidity = 60 * 24 * 7;//token is valid in 7 days return appConfig;
},
4、添加天地图
经过上面改造,已经能够脱离portal运行了,为了添加天地图,制作了一个添加天地图的类,命名为TiantiTuLayer.js文件,代码如下
define([ "dojo/_base/declare", "dijit/_TemplatedMixin", "esri/layers/WebTileLayer" ,"esri/geometry/SpatialReference","esri/geometry/Extent","esri/layers/support/TileInfo"],
function(declare, _TemplatedMixin, TiledMapServiceLayer,SpatialReference,Extent,TileInfo) {
return declare("tianditu",[], { // create WMTSLayer by extending esri.layers.TiledMapServiceLayer _hosts: new Array("t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"),
constructor: function(options){
if(!options){
options = {};
}
options.spatialReference = new SpatialReference({
wkid: 4326 });
options.initialExtent = new Extent({
xmin:-180,
ymin:-90,
xmax:180,
ymax:90,
sptialReference:options.spatialReference });
options.fullExtent = new Extent({
xmin:-180,
ymin:-90,
xmax:180,
ymax:90,
sptialReference:options.spatialReference });
// options.tileInfo = new TileInfo({
"dpi": "90.71428571427429",
"format": "image/png",
"compressionQuality": 0,
"spatialReference": {
"wkid": 4326 },
"rows": 256,
"cols": 256,
"origin": {
"x": -180,
"y": 90 },
// Scales in DPI 96 "lods": [
{"level": 1,"scale": 2.95498e+008,"resolution": 0.703125 }, {"level": 2,"scale": 1.47749e+008,"resolution": 0.351563 }, {"level": 3,"scale": 7.38744e+007,"resolution": 0.175781 }, {"level": 4,"scale": 3.69372e+007,"resolution": 0.0878906 }, {"level": 5,"scale": 1.84686e+007,"resolution": 0.0439453 }, {"level": 6,"scale": 9.2343e+006,"resolution": 0.0219727 }, {"level": 7,"scale": 4.61715e+006,"resolution": 0.0109863 }, {"level": 8,"scale": 2.30857e+006,"resolution": 0.00549316 }, {"level": 9,"scale": 1.15429e+006,"resolution": 0.00274658 }, {"level": 10,"scale": 577144,"resolution": 0.00137329 }, {"level": 11,"scale": 288572,"resolution": 0.000686646 }, {"level": 12,"scale": 144286,"resolution": 0.000343323 }, {"level": 13,"scale": 72143,"resolution": 0.000171661 }, {"level": 14,"scale": 36071.5,"resolution": 8.58307e-005 }, {"level": 15,"scale": 18035.7,"resolution": 4.29153e-005 }, {"level": 16,"scale": 9017.87,"resolution": 2.14577e-005 }, {"level": 17,"scale": 4508.9,"resolution": 1.07289e-005 }, {"level": 18,"scale": 2254.47,"resolution": 5.36445e-006 }]
});
var ty = options.whichlayer ? options.whichlayer.toLowerCase() : "map";
var typeT;
var crt;
if(ty == "map")
{
typeT = "vec_c";
crt = "地图";
}
else if(ty == "mapi")
{
typeT = "cva_c";
crt = "地图注记";
}
else if(ty == "trrain")
{
typeT = "ter_c";
crt = "地形";
}
else if(ty == "image")
{
typeT = "img_c";
crt = "影像";
}
else if(ty == "imagei")
{
typeT = "cia_c";
crt = "影像注记";
}
options.urlTemplate="http://{subDomain}.tianditu.com/DataServer?T=" + typeT + "&X={col}&Y={row}&L={level}";
//options.urlTemplate="http://{subDomain}.tianditu.cn/cva_w/wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={level}&TileRow={rows}&TileCol={cols}&style=default&format=tiles"; options.id = "tianditu";
options.copyright = "天地图" + crt;
options.subDomains = this._hosts;
this.customLayer = new TiledMapServiceLayer(options);
}
});
});
5、成果
经过以上改造,并配置config.json文件,加载天地图效果如下:
也可以切换到三维显示,只是没有数据,显示为一个白球:
需要源代码的到我的资源里面下载。