动态创建图层关联关系
1.环境说明
ArcGIS 10.4.1
JS API 3.15
2.动态创建图层关联关系说明
在实际业务应用中,通常将图层和业务数据分开存储,即空间位置信息以图层存储,业务数据存储在单独的业务表中,且图层为多个业务表共用。如果要实现图层和业务数据的关联查询,一种做法是在服务端实现,即在发布服务前先在ArcMap中建立图层与业务表的关联关系,适用于中等数据量;第二种做法是在客户端实现,即先查图层,再查业务表,适用于小数据量。这里说的小数据量指的是浏览器能承载的数据量,一般不会超过十万;中等数据量指的是百万以内。如果图层共用的业务表太多,预先建立的地图服务也会很多。如果业务表是变化的,如按月上报的表格数据,这种就不能预先建立关联。对于这样的情况,可使用动态图层来建立动态的关联关系来实现。
这里将图层关联关系的创建分两种情况实现:一是创建动态工作空间中的图层和表的关联关系。二是创建原地图服务中的图层与动态工作空间中的图层或表的关联关系。
3.建立动态图层和动态表间的关联关系,并按表中的字符渲染地图
第一步:建立关联关系
var workspaceId = "FGDBWorkspace1224";
//根据左边数据源类型返回一致的结果数据类型,表即返回表,图层即返回图层。
//1.定义关联关系的数据源(数据源都来自动态图层)
var joinDS = new JoinDataSource({
joinType: "left-inner-join",
leftTableSource: new LayerDataSource({
dataSource:new TableDataSource({
type:"table",
workspaceId: workspaceId,
dataSourceName: "地市级行政中心"
})
}),
rightTableSource: new LayerDataSource({
dataSource:new TableDataSource({
type:"table",
workspaceId: workspaceId,
dataSourceName: "rain"
})
}),
leftTableKey: "OBJECTID",
rightTableKey: "ID"
});
//2.定义Layer数据源
var layerSource = new LayerDataSource();
layerSource.dataSource = joinDS;
//3.更新到现有的dynamicmapservicelayer中
var dynamicLayerInfo = new DynamicLayerInfo();
dynamicLayerInfo.id = dynamicLayerInfos.length;
dynamicLayerInfo.name = "JOIN图层和表";
dynamicLayerInfo.source = layerSource;
dynamicLayerInfos.splice(0,0,dynamicLayerInfo); //将新加的图层添加在数组最前面,在地图中会绘制在最上面。
baseLayer.setDynamicLayerInfos(dynamicLayerInfos);
console.log("join关联后:");
printMsg(dynamicLayerInfos);
第二步:定义渲染方法
注意:测试中发现使用分级渲染方法地图未生效,使用唯一值渲染方法地图生效。
//4.定义渲染方式:分级渲染(未出现渲染效果)
/*var renderer = new ClassBreaksRenderer(createSymbol("esriGeometryPoint"),"rain.STAZT");
renderer.addBreak(0.8, 50.2, createSymbol("esriGeometryPoint"));
renderer.addBreak(50.2, 100.5, createSymbol("esriGeometryPoint"));
renderer.addBreak(100.5, 200.6, createSymbol("esriGeometryPoint"));
renderer.addBreak(200.6, 800.4, createSymbol("esriGeometryPoint"));*/
//4.定义渲染方式:唯一值渲染渲染(测试通过)
/*var renderer = new UniqueValueRenderer(createSymbol("esriGeometryPoint"),"地市级行政中心.ADCLASS");
renderer.addValue("1",createSymbol("esriGeometryPoint"));
renderer.addValue("2",createSymbol("esriGeometryPoint"));
renderer.addValue("3",createSymbol("esriGeometryPoint"));
renderer.addValue("9",createSymbol("esriGeometryPoint"));*/
var renderer = new UniqueValueRenderer(createSymbol("esriGeometryPoint"),"rain.PROVINCE");
renderer.addValue("内蒙古",createSymbol("esriGeometryPoint"));
renderer.addValue("黑龙江",createSymbol("esriGeometryPoint"));
renderer.addValue("吉林",createSymbol("esriGeometryPoint"));
renderer.addValue("北京",createSymbol("esriGeometryPoint"));
renderer.addValue("新疆",createSymbol("esriGeometryPoint"));
//更改渲染
var lblClass = new LabelClass({
labelExpression: "[rain.STAZT]",
labelPlacement: "center-right",
symbol:{
"type": "esriTS",
"color": [255,0,0],
"haloColor":[245,245,245],
"haloSize":1,
"font": {
"family":"Microsoft YaHei",
"size": "14px"
}
}
});
var layerId = dynamicLayerInfos.length-1; //图层ID以加入顺序递增
var lyrDrawingOptions = new LayerDrawingOptions();
lyrDrawingOptions.labelingInfo = [lblClass];
lyrDrawingOptions.showLabels = true;
lyrDrawingOptions.renderer = renderer;
drawingOptions[layerId] = lyrDrawingOptions;
baseLayer.setLayerDrawingOptions(drawingOptions);
4. 建立原地图服务中的图层和动态表间的关联关系,并按表中的字段渲染地图
第一步:建立关联关系
var workspaceId = "FGDBWorkspace1224";
//1.定义关联关系的数据源(左数据源都来自服务中的图层,右数据源来自动态图层)
var joinDS = new JoinDataSource({
type: "joinTable",
joinType: "left-inner-join",
leftTableSource: new LayerMapSource({
type: "mapLayer",
mapLayerId: 0
}),
rightTableSource: new LayerDataSource({
dataSource:new TableDataSource({
type:"table",
workspaceId: workspaceId,
dataSourceName: "rain"
})
}),
leftTableKey: "OBJECTID",
rightTableKey: "ID"
});
//2.定义Layer数据源
var layerSource = new LayerDataSource();
layerSource.dataSource = joinDS;
//3.更新到现有的dynamicmapservicelayer中
var dynamicLayerInfo = new DynamicLayerInfo();
dynamicLayerInfo.id = dynamicLayerInfos.length;
dynamicLayerInfo.name = "JOIN服务图层和表";
dynamicLayerInfo.source = layerSource;
dynamicLayerInfos.splice(0,0,dynamicLayerInfo); //将新加的图层添加在数组最前面,在地图中会绘制在最上面。
baseLayer.setDynamicLayerInfos(dynamicLayerInfos);
console.log("join关联后:");
printMsg(dynamicLayerInfos);
** 第二步:定义渲染方法 **
//4.定义渲染方式:分级渲染(测试通过)
var renderer = new ClassBreaksRenderer(createSymbol("esriGeometryPoint"),"rain.STAZT");
renderer.addBreak(10, 50, createSymbol("esriGeometryPoint"));
renderer.addBreak(50, 100, createSymbol("esriGeometryPoint"));
renderer.addBreak(100, 200, createSymbol("esriGeometryPoint"));
renderer.addBreak(200, Infinity, createSymbol("esriGeometryPoint"));
//5.定义渲染方式:唯一值渲染渲染(测试通过)
/*var renderer = new UniqueValueRenderer(createSymbol("esriGeometryPoint"),"rain.PROVINCE");
renderer.addValue("内蒙古",createSymbol("esriGeometryPoint"));
renderer.addValue("黑龙江",createSymbol("esriGeometryPoint"));
renderer.addValue("吉林",createSymbol("esriGeometryPoint"));
renderer.addValue("北京",createSymbol("esriGeometryPoint"));
renderer.addValue("新疆",createSymbol("esriGeometryPoint"));*/
var lblClass = new LabelClass({
labelExpression: "[rain.STAZT]",
labelPlacement: "center-right",
symbol:{
"type": "esriTS",
"color": [255,0,0],
"haloColor":[245,245,245],
"haloSize":1,
"font": {
"family":"Microsoft YaHei",
"size": "14px"
}
}
});
var layerId = dynamicLayerInfos.length-1; //图层ID以加入顺序递增
var lyrDrawingOptions = new LayerDrawingOptions();
lyrDrawingOptions.labelingInfo = [lblClass];
lyrDrawingOptions.showLabels = true;
lyrDrawingOptions.renderer = renderer;
drawingOptions[layerId] = lyrDrawingOptions;
baseLayer.setLayerDrawingOptions(drawingOptions);
5. 分级渲染问题
在上述测试中,如果是在动态图层和动态表间建立的关联关系,可以定义SimpleRenderer和UniqueValueRenderer两种渲染方法,定义的ClassBreaksRenderer渲染方法未生效。
如果是在原地图服务中的图层和动态表间建立的关联关系,可以定义SimpleRenderer、UniqueValueRenderer和ClassBreaksRenderer三种渲染方法。
对于第一种ClassBreaksRenderer未生效的情况,如果不使用自定义分级间隔,而使用系统自动定义的分级间隔,可使用如下的方式实现:
var colorRamp = new AlgorithmicColorRamp();
colorRamp.fromColor = Color.fromHex("#998ec3");
colorRamp.toColor = Color.fromHex("#f1a340");
colorRamp.algorithm = "hsv";
var classDef = new ClassBreaksDefinition();
classDef.classificationField = "rain.RAIN";
classDef.classificationMethod = "quantile";
classDef.breakCount = 5;
classDef.baseSymbol = createSymbol("esriGeometryPoint");
classDef.colorRamp = colorRamp;
console.log("classBreaksDefinition:"+JSON.stringify(classDef.toJson()));
var params = new GenerateRendererParameters();
params.classificationDefinition = classDef;
params.where = "1=1";
var dynamicLayerUrl = "http://portal140.xinli.local/server/rest/services/worldcities/MapServer/dynamicLayer";
var generateRendererTask = new GenerateRendererTask(dynamicLayerUrl, {"source":layerSource});
var generateRendererDefer = generateRendererTask.execute(params);
var layerId = dynamicLayerInfos.length-1;
generateRendererDefer.then(function(renderer){
var layerDrawingOption = new LayerDrawingOptions();
layerDrawingOption.renderer = renderer;
drawingOptions[layerId] = layerDrawingOption;
baseLayer.setLayerDrawingOptions(drawingOptions);
});
6.源码
xinligis github