客户端数据动态渲染
更新:这个例子比之前的更贴切:http://resources.arcgis.com/en/help/flex-api/samples/index.html#/DynamicLayerInfo_JoinDataSource/01nq00000088000000/
ArcGIS Server 10.1+Flex API 3.0(至少Server10.1和3.0的API才行)客户端执行GP服务,对得到的数据进行渲染,并生成图例(颜色可自定义)。
1.客户端设置好相应参数,并绘图确定分析范围,调用GP服务。
2.对GP服务返回的结果进行渲染(用到了DetailsTask和GenerateRendererTask)。
参考在线Samples:http://resources.arcgis.com/en/help/flex-api/samples/index.html#/Generate_renderers/01nq0000006z000000/
3.若觉得颜色不好看,改变图例颜色。
另:有些细节还模糊,写的有点乱,敬请指正。
效果图:
具体:
1.在客户端选择好相应参数,确定分析范围,此处设置为绘图结束后立即调用GP服务。
在名为“inputsLayer”的GraphicsLayer上绘制,并将结果转为FeatureSet,因为FeatureSet是GP输入参数的格式要求,而且包含更多属性信息等。
然后异步提交这些确定好的GP参数,调用GP服务,并对GP事件的状态进行监听,为后续流程进行做准备。
protected function drawTool_drawEndHandler(event:DrawEvent):void { // reset after finished drawing a feature map.addLayer(inputsLayer); graphic=event.graphic; inputsLayer.add(graphic); var featureSet:FeatureSet=new FeatureSet([graphic]); var params:Object= { //"SQL":"1=1", "Selecting_Features":featureSet, "Cellsize_":cellsize.value.toString(),//"0.008", "ValueField_":roadCoverField.selectedItem['label'].toString() }; GP.submitJob(params); //提交参数,调用GP服务 //map.addLayer(refreshAddLayer); GP.addEventListener(GeoprocessorEvent.STATUS_UPDATE,AddLayer); GP.addEventListener(FaultEvent.FAULT,FaultInfo); myDrawTool.deactivate(); tbb.selectedIndex = -1; }
2.对GP服务结果进行渲染。
之前对GP事件状态进行监听,若成功则执行AddLayer,即将结果图层添加上来。flag是做什么的呢?等会解释,它的作用是为了避免犯错。
并执行已经声明好的DetailsTask,来获取该结果图层的相关属性信息,为渲染做准备。
当然还要对detailsTask事件进行监听,如果已经得到结果图层的相关信息,则执行detailsTask_getAllDetailsCompleteHandler(其实detailsTask执行完毕后它会自动派发)。
这时,渲染参数都搞定了,就可以执行渲染了, 即“generateRenderer()”,然后就可以将已经渲染成功的结果图层添加上来了,即“refreshAddLayer”。
//GP状态改变后派发事件,即添加更新后的GP结果地图 protected function AddLayer(event:GeoprocessorEvent):void { if (event.jobInfo.jobStatus == JobInfo.STATUS_SUCCEEDED) { flag_generateRenderer=true; dynamicLayerInfosArr = refreshAddLayer.createDynamicLayerInfosFromLayerInfos(); detailsTask.getAllDetails(); detailsTask.addEventListener(DetailsEvent.GET_ALL_DETAILS_COMPLETE,detailsTask_getAllDetailsCompleteHandler); generateRenderer(); map.addLayer(refreshAddLayer); //map.addEventListener(MapEvent.LAYER_ADD,Refresh); } else { Alert.show(event.jobInfo.jobStatus); //Alert.show("GP服务似乎遇到一点问题,赶快检查一下吧!"); } }
之前声明好的两个Task:"DetailsTask"和"GenerateRendererTask"
另:第一次用DetailsTask和GenerateRendererTask这两个东西,不是很了解,大致过程是这样的,detailsTask.getAllDetails()获取到动态图层的相应属性信息,就派发detailsTask_getAllDetailsCompleteHandler,根据目标图层获取分类方法及渲染参数,然后开始渲染。
<esri:DetailsTask id="detailsTask" fault="esriService_faultHandler(event)" getAllDetailsComplete="detailsTask_getAllDetailsCompleteHandler(event)" url="http://192.168.210.114:6080/arcgis/rest/services/gptest/MapServer"/> <esri:GenerateRendererTask id="generateRendererTask" executeComplete="generateRendererTask_executeCompleteHandler(event)" fault="esriService_faultHandler(event)" url="http://192.168.210.114:6080/arcgis/rest/services/gptest/MapServer/0"/>
detailsTask执行完毕即获取了结果图层的信息后,派发detailsTask_getAllDetailsCompleteHandler,通过它可以提交渲染参数,怎么这里也generateRendererTask.execute?有点疑惑。。。————之前由于直接复制在线sample代码留下来的,确实是重复了。
protected function detailsTask_getAllDetailsCompleteHandler(event:DetailsEvent):void { var details:AllDetails = event.allDetails; layerDetailsArr = details.layersDetails; var layerDetails:LayerDetails; for (var i:int = 0; i < layerDetailsArr.length; i++) { layerDetails = layerDetailsArr[i]; if (layerDetails.name == "Zoncover" ) //目标图层的图层名 { layerMapSource = DynamicLayerInfo(dynamicLayerInfosArr[i]).source as LayerMapSource; generateRendererTask.source = layerMapSource; classBreaksDefinition.breakCount = _breakCount; //分类级数,之前已设置,其实分类级数和方法也可以弄成客户端来选择 classBreaksDefinition.classificationField = _classificationField; //目标图层的目标属性字段,用以分类,这里已经预设好了。 classBreaksDefinition.classificationMethod = ClassBreaksDefinition.CLASSIFY_QUANTILE; //分类方法这里已经写死 classBreaksDefinition.colorRamp =colorRamp1; //colorRamp1为预先设置好的色带参数。 generateRendererParams.classificationDefinition = classBreaksDefinition; generateRendererTask.execute(generateRendererParams); } }
执行渲染的函数generateRenderer(),colorRamp1是预先设好的色带参数。
[Bindable] private var fromColorValue:uint=uint("0xF9F900"); //private var fromColorValue:uint=uint(c1.colorField); [Bindable] private var toColorValue:uint=uint("0xFF0000");
<esri:AlgorithmicColorRamp id="colorRamp1" algorithm="esriHSVAlgorithm" fromColor="{fromColorValue}" toColor="{toColorValue}"/>
//符号渲染 protected function generateRenderer():void { classBreaksDefinition.breakCount = 9; classBreaksDefinition.classificationMethod = _classificationMethod; classBreaksDefinition.classificationField = _classificationField; //在此也添加字段,看是否能解决第一次渲染找不到字段的问题 generateRendererParams.classificationDefinition = classBreaksDefinition; classBreaksDefinition.colorRamp = colorRamp1; generateRendererTask.execute(generateRendererParams); }
渲染完毕后把图例加上来。
protected function generateRendererTask_executeCompleteHandler(event:GenerateRendererEvent):void { var renderer:ClassBreaksRenderer = event.renderer as ClassBreaksRenderer; var layerDrawingOptions:LayerDrawingOptions = new LayerDrawingOptions(); layerDrawingOptions.layerId = layerMapSource.mapLayerId; layerDrawingOptions.renderer = renderer; refreshAddLayer.alpha = 0.7; var layerDrawingOptionsArr:Array = [layerDrawingOptions]; refreshAddLayer.layerDrawingOptions = layerDrawingOptionsArr; legend.map=map; refreshAddLayer.name="图例"; legend.layers = [refreshAddLayer]; }
3.改变图例颜色,颜色选择用来Flex自带的ColorPicker控件
<!--色带选择横行--> <s:HGroup> <s:Label fontSize="12" paddingTop="5" paddingBottom="5" fontWeight="bold" height="20" width="60" text="选择色带:" fontFamily="中易宋体"/> <!-- <s:ComboBox id="roadpic" selectedIndex="0" width="183" dataProvider="{roadpicchoice}" change="color_changeHandler(event)" />--> <mx:ColorPicker id="c1" showTextField="true" selectedColor="0xF9F900" width="88.5" change="c1_changeHandler(event)"/> <mx:ColorPicker id="c2" showTextField="true" selectedColor="0xFF0000" width="85.5" change="c2_changeHandler(event)"/> </s:HGroup>
不改变则按预设的色带进行渲染,改变颜色则重新渲染一次。
该说明一下flag的作用了,试想如果在设置GP执行需要的相应参数时(最后一步是绘图确定分析范围),如果改变了颜色,则会触发执行渲染的函数generateRenderer(),而之前设置的是绘图结束自动调用GP服务,并执行一系列流程,其中就有获取GP结果图层和渲染参数等,而这时GP服务没有执行,渲染参数更是没有得到,执行渲染函数是会出错的,于是之前设置了一个flag,若GP执行,且执行成功,则为flag赋值为true(默认flag是false),这样改变色带颜色时,如果还没有成功调用GP任务,是不会去进行渲染的,避免出错。
//颜色选择 protected function c1_changeHandler(event:ColorPickerEvent):void { fromColorValue=c1.selectedColor; if(flag_generateRenderer==true) //在GP成功完成后为true值 { generateRenderer(); } } protected function c2_changeHandler(event:ColorPickerEvent):void { //toColorValue=uint(c2.colorField); toColorValue=c2.selectedColor; if(flag_generateRenderer==true) //在GP成功完成后为true值 { generateRenderer(); } }