要完全从0开始实现3D环境下的Map Control当然也可以,不过既然已经有了ArcGIS Server Flex API的Map Control,并且还有一整套现成的功能,那么将ArcGIS Server Flex API的Map Control加到PV3D的环境中是一个不错的选择。
但是要实现也不是非常容易的事情,在测试的过程中发现了一些问题。
①3D环境下显示Map Control必须保证同样添加到2D环境下,但是无法隐藏2D环境下的Map Control,或者是隐藏了2D环境下的Map Control,3D环境下显示的Map Control默认事件(双击、滚轮、移动)就无效;
②在Map Control上绘制图形对象会发生偏移,和鼠标点击的位置不一致。
最终的解决方法:将Map Control作为Plane的MovieMaterial,Map Control并不是直接加到MovieMaterial中,而是通过MovieClip,并且用一个ParentMovie Clip处理2D环境下的Map Control的隐藏,这样既能在2D环境下隐藏Map Control,还会保证Map Control在3D环境下保留原先的功能。
//add esri map control to pv3d environment movie.addChild(map); mat = new MovieMaterial(movie, true, true, false, new Rectangle(0, 0, m_pv3dwidth, m_pv3dheight)); mat.smooth=true; m_baseMapPlane = new Plane(mat, m_pv3dwidth, m_pv3dheight, 20, 20); //make esri map control invisible in flex 2d environment movieParent.addChild(movie); movieParent.alpha = 0; pv3d.rawChildren.addChild(movieParent);
图形的绘制要在Map Control没有变形的时候进行,能够保证所绘即所得。
柱状图(createBarChartHeatMap)、饼状图(createPieChartHeatMap)的实现原理:通过QueryTask查询出需要做专题的对象,通过PV3D绘制出3D的柱状(Cube 3D object)、饼状(Cylinder 3D object)。考虑到柱状图和饼状图的三维效果,要对Cube、Cylinder不同面以不同的方式渲染。
柱状专题图
//create chart map materia list matList.addMaterial(red, "front"); matList.addMaterial(red, "back"); matList.addMaterial(blue, "left"); matList.addMaterial(blue, "right"); matList.addMaterial(green, "top"); matList.addMaterial(green, "bottom"); var pvCube:Cube = new Cube(matList, 20, 2 * pv3dz, 20);
var pvCylinder:Cylinder = new Cylinder(null, pv3dz / 1.5, 15, 20, 1, pv3dz / 1.5, true, true); var bottomMaterial:ColorMaterial = new ColorMaterial(0xff0000); var middleMaterial:ColorMaterial = new ColorMaterial(0x0000ff); var topMaterial:ColorMaterial = new ColorMaterial(0xff0000); var i:int; //this is the bottom face for (i = 0; i < 18; i++) { pvCylinder.geometry.faces[i].material = bottomMaterial; } //the middle of the cylinder for (i = 18; i < pvCylinder.geometry.faces.length - 18; i++) { pvCylinder.geometry.faces[i].material = middleMaterial; } //the top for (i = pvCylinder.geometry.faces.length - 18; i < pvCylinder.geometry.faces.length; i++) { pvCylinder.geometry.faces[i].material = topMaterial; }