cesium三维开发过程记录

以下是我以前学习cesium三维开发全过程记录

环境准备

1.Supermap iServer9.1.2a win64 

2.基于supermap SuperMap_iClient3D_10i_for_WebGL_CN.zip

3.Supermap 10i 的iDesktop  supermap-idesktop-10.0.0-39781-win32-bin-zip-chs

官网下载好了。

注意许可问题,可以在线申请试用许可(下载两个文件),三个月。iServer和iDesktop都需要,在bin的同级文件下有许可的文件夹,可以打开可执行文件进行许可导入(注意选择许可文件类型)、更新。

 

iServer启动停止在startup.bat  shutup.bat

idesktop三维场景不支持微软的远程桌面,远程时会直接崩掉。问了客服,可以使用如anyDesk, TV这种互联网远程工作。

 

基于webgl三维展示主要考虑客户端浏览器端的显卡能力、显存配置。客户有一台老机器,显示效果卡顿得惨不忍睹。 

iClient for WebGL的配置

iServer和desktop正常运行之后,解压SuperMap_iClient3D_10i_for_WebGL_CN.zip所有文件到iServer的webapps目录下,如

 

 

 

 

 

 

然后在浏览器中测试这个地址,正常显示就可以了。

http://localhost:8090/WebGL/examples/examples.html#layer

这是自带的示例。

http://localhost:8090/WebGL/Build/Documentation/index.html

这是自带的api帮助

 

由于iclient for webgl 是基于cesium的封装,所以这里很多API和cesium超级像,而且就是一致的,里面的使用方法也一样。

所以本质上就是学习cesium开发。

Cesium开发的资源

Cesium官网,https://cesium.com/cesiumjs/,这里可以下载cesiumJs 1.64

由于超图已经封装好了,不必下载(不用iserver, 改用node.js就需要下载了)

Cesium中文网 http://cesium.xin/

跃焱邵隼 的个人示例:

https://www.wellyyss.cn/ysCesium/views/main.html

 

数据准备

1。地图

二维:行政区,地籍区,子区、道路,河流,

三维:楼幢按高度拉伸

 

由于客户希望实现科技感的效果,最终采用了夜景深色的方案

如阿里的

 

 

 

先是在desktop里拉抻幢数据,高度是采用层数*3的数值

桌面里新建工作空间,新建数据源,超图支持建议我们使用udb文件类型的,而不是udbx,不明原因。

 

加载数据源,把准备好的shp文件全部导入进去。

转换坐标。由于三维场景发布之后是经纬度坐标,而客户提供的是2000投影坐标,生成二维的图切片之后也是2000的,不能动态投影上去,所以制作二维底图的时候要先做坐标转换。没有椭球体的变换,直接转就可以

 

 

 

一个一个层转换,转存到另一个数据源里。

然后开始制图。

 

建二维地图,把区、路、河的数据拖进去,配色,制作成深色效果,如:

 

 

 

 

 切片。

地图上右键就可以:

 

 

 

同样,可以将切好的图加载到地图里。

数据源右键à加载文件型à找到切片目录,加载.sci文件就可以

然后再添加到地图中。

 

 

 

建三维球面场景(要用球面,不然二维的图叠不上去)

先使用楼幢数据拉伸白模。

将zrz楼幢的数据拖到三维场景中,然后在三维地理设计菜单里规则建模里,拉伸

 

 

 

 

 

 

 生成白模之后可以在场景图层中,菜单风格设置里调整颜色、透明度:

 

 

 

把二维的图也叠加进来看看是不是重合

 

 

 

最后发布三维切片。

 

 

  

要选择s3m的,其他可以默认。

 

发布地图服务:

二维要选择ugcv5瓦片,再选择切片目录的sci文件

 

 

 

 

 

  

使用这个层级的路径就好:

  

三维

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2。图片

如天空盒子

代码

 

 

 

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="utf-8">
  5     <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  6     <meta name="viewport"
  7           content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  8     <title>沿线飞行</title>
  9     <link href="../Build/Cesium/Widgets/widgets.css" rel="stylesheet">
 10     <link href="./css/bootstrap.min.css" rel="stylesheet">
 11     <link href="./css/pretty.css" rel="stylesheet">
 12     <script src="./js/jquery.min.js"></script>
 13     <script src="./js/bootstrap.min.js"></script>
 14     <script src="./js/bootstrap-select.min.js"></script>
 15     <script src="./js/config.js"></script>
 16     <script type="text/javascript" src="./js/require.min.js" data-main="js/main"></script>
 17     <style>
 18         #play {
 19             content: url(./images/play.png);
 20             height: 30px;
 21             padding: 5px;
 22         }
 23 
 24         #pause {
 25             content: url(./images/pause.png);
 26             height: 30px;
 27             padding: 5px;
 28         }
 29 
 30         #stop {
 31             content: url(./images/stop.png);
 32             height: 30px;
 33             padding: 5px;
 34         }
 35 
 36         .bootstrap-select {
 37             width: 150px;
 38         }
 39     </style>
 40 </head>
 41 <body>
 42 <div id="cesiumContainer"></div>
 43 
 44 <script>
 45 
 46     var flyManager;
 47     var regCenterArr = [[118.872007133102,32.5654461621505],[118.8721859694,32.5681986643736]];
 48     var currentSkyBox, defaultSkyBox, qingtianSkyBox, wanxiaSkyBox, lantianSkyBox;
 49 
 50     function onload(Cesium) {
 51         
 52         var viewer = new Cesium.Viewer(\'cesiumContainer\');
 53         // var terrainProvider= new Cesium.CesiumTerrainProvider({
 54         //     url : \'http://localhost:8090/WebGL/terrain_tiles\' 
 55         // });
 56         // var viewer = new Cesium.Viewer(\'cesiumContainer\', {
 57         //     terrainProvider: terrainProvider
 58         // });
 59         // var viewer = new Cesium.Viewer(\'cesiumContainer\');
 60 
 61         viewer.imageryLayers.addImageryProvider(new Cesium.SuperMapImageryProvider({
 62                 url:\'http://localhost:8090/iserver/services/map-ugcv5-D21C/rest/maps/D21C\'                
 63         }));
 64 
 65         var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
 66         handler.setInputAction(function (movement) {
 67             var pick = viewer.scene.pick(movement.position);
 68             if (Cesium.defined(pick)) {
 69                 console.log(pick);
 70             }
 71         }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
 72 
 73         var scene = viewer.scene;
 74         scene.globe.depthTestAgainstTerrain = false;
 75 
 76         var camera = scene.camera;
 77         //添加S3M图层服务
 78         //var promise = scene.open(\'http://localhost:8090/iserver/services/3D-test2/rest/realspace\');
 79         var promise = scene.open(\'http://localhost:8090/iserver/services/3D-LinearExtrudeResult_2-test1/rest/realspace\');
 80         promise.then(function (layers) {
 81             camera.setView({
 82                 destination: Cesium.Cartesian3.fromDegrees(118.873391561571 ,32.5519730104681 , 800.0),
 83                 orientation: {
 84                     heading : Cesium.Math.toRadians(0.0),
 85                         pitch : Cesium.Math.toRadians(-23),
 86                         roll : 0
 87                 }
 88             });
 89 
 90 
 91             console.log(layers);
 92             //layers[1].setObjsColor(885, Cesium.Color.YELLOW);
 93 
 94 //设置不同颜色的,没有作用。
 95             promise.style = new Cesium.Cesium3DTileStyle({
 96                 color: {
 97                     conditions: [
 98                         [\'${zcs} >= 8\', \'rgba(45, 0, 75, 0.5)\'],
 99                         [\'${zcs} >= 7\', \'rgb(102, 71, 151)\'],
100                         [\'${zcs} >= 6\', \'rgb(170, 162, 204)\'],
101                         [\'${zcs} >= 5\', \'rgb(224, 226, 238)\'],
102                         [\'${zcs} >= 4\', \'rgb(252, 230, 200)\'],
103                         [\'${zcs} >= 3\', \'rgb(248, 176, 87)\'],
104                         [\'${zcs} >= 2\', \'rgb(198, 106, 11)\'],
105                         [\'true\', \'rgb(127, 59, 8)\']
106                     ]
107                 }
108             });
109 
110             //天空盒子
111             qingtianSkyBox = new Cesium.SkyBox({
112                 nearGround: true,
113                 sources: {
114                     positiveX : \'./images/天空盒素材/晴天/Right.jpg\',
115                     negativeX : \'./images/天空盒素材/晴天/Left.jpg\',
116                     positiveY : \'./images/天空盒素材/晴天/Front.jpg\',
117                     negativeY : \'./images/天空盒素材/晴天/Back.jpg\',
118                     positiveZ : \'./images/天空盒素材/晴天/Up.jpg\',
119                     negativeZ : \'./images/天空盒素材/晴天/Down.jpg\'
120                 }
121             });
122             wanxiaSkyBox = new Cesium.SkyBox({
123                 nearGround: true,
124                 sources: {
125                     positiveX : \'./images/天空盒素材/晚霞/Right.jpg\',
126                     negativeX : \'./images/天空盒素材/晚霞/Left.jpg\',
127                     positiveY : \'./images/天空盒素材/晚霞/Front.jpg\',
128                     negativeY : \'./images/天空盒素材/晚霞/Back.jpg\',
129                     positiveZ : \'./images/天空盒素材/晚霞/Up.jpg\',
130                     negativeZ : \'./images/天空盒素材/晚霞/Down.jpg\'
131                 }
132             });
133             lantianSkyBox = new Cesium.SkyBox({
134                 nearGround: true,
135                 sources: {
136                     positiveX : \'./images/天空盒素材/蓝天/Right.jpg\',
137                     negativeX : \'./images/天空盒素材/蓝天/Left.jpg\',
138                     positiveY : \'./images/天空盒素材/蓝天/Front.jpg\',
139                     negativeY : \'./images/天空盒素材/蓝天/Back.jpg\',
140                     positiveZ : \'./images/天空盒素材/蓝天/Up.jpg\',
141                     negativeZ : \'./images/天空盒素材/蓝天/Down.jpg\'
142                 }
143             });
144 
145             // defaultSkyBox = viewer.scene.skyBox;
146             // //天空盒效果切换
147             // currentSkyBox = wanxiaSkyBox;
148             // scene.skyBox = currentSkyBox;
149             // scene.postRender.addEventListener(function() {
150             //     var cameraHeight = scene.camera.positionCartographic.height;
151             //     var toggleHeight = 23e4;
152             //     if(cameraHeight < toggleHeight && Cesium.defined(currentSkyBox)) {
153             //         scene.skyBox = currentSkyBox;
154             //         scene.skyAtmosphere.show = false;
155             //     } else {
156             //         scene.skyBox = defaultSkyBox;
157             //         scene.skyAtmosphere.show = true;
158             //     }
159             // });
160 
161    
162 
163             //加载飞行路线管理
164             var routes = new Cesium.RouteCollection(viewer.entities);
165             var fpfUrl = \'fly333.fpf\';
166             routes.fromFile(fpfUrl);
167             var flyManager = new Cesium.FlyManager({
168                 scene: scene,
169                 routes: routes
170             });
171             //注册站点到达事件
172             flyManager.stopArrived.addEventListener(function (routeStop) {
173                 routeStop.waitTime = 0; // 在每个站点处停留1s
174                 var route = flyManager.currentRoute;
175                 // var stop = route.get(index);  // flyManager.currentStopIndex = index;  // flyManager.viewToStop(stop);
176                 //console.log(routeStop._index);
177                 switch(routeStop._index){
178                     case 1:
179                         load_certs_bubbles();
180                         break;
181                     case 2:
182                         // var entity2 = viewer.entities.getById(885);
183                         // console.log(entity2);                        
184                         //entity2.model.color = Cesium.Color.YELLOW;//修改模型颜色
185 
186                         load_big_reg_bullitin({id:\'pos1\',lon:118.872007133102,lat:32.5654461621505,height:50,name:\'南京市大光路不动产登记中心\'});
187 
188                         viewer.entities.removeById(\'111\');
189                         addCircleRipple(viewer,{ //默认只绘制两个圆圈叠加 如遇绘制多个,请自行源码内添加。
190                             id:"111",
191                             lon:118.872007133102,
192                             lat:32.5654461621505,
193                             height:0,
194                             maxR:150,
195                             minR:0,//最好为0
196                             deviationR:1,//差值 差值也大 速度越快
197                             eachInterval:1000,//两个圈的时间间隔
198                             imageUrl:\'./images/环状扫描纹理2.png\'
199                         });
200                         break;
201                     case 9:
202                         load_big_reg_bullitin({id:\'pos1\',lon:118.8721859694,lat:32.5681986643736,height:50,name:\'华侨路不动产登记中心\'});
203                         viewer.entities.removeById(\'211\');
204                         addCircleRipple(viewer,{ 
205                             id:"211",
206                             lon:118.8721859694,
207                             lat:32.5681986643736,
208                             height:0,
209                             maxR:150,
210                             minR:0,
211                             deviationR:1,
212                             eachInterval:1000,
213                             imageUrl:\'./images/环状扫描纹理2.png\'
214                         });
215                     break;
216                 }
217                 
218             });
219 
220             flyManager.readyPromise.then(function () { // 飞行路线就绪
221                 var currentRoute = flyManager.currentRoute;
222                 currentRoute.isLineVisible = false;
223                 currentRoute.isStopVisible = false;
224                 //播放飞行
225                 flyManager && flyManager.play();
226             });
227         });
228 
229 
230         var load_big_reg_bullitin  =function(data){
231             var entity_big = viewer.entities.add({
232                 position: Cesium.Cartesian3.fromDegrees(data.lon, data.lat, data.height),//118.872007133102 ,32.5654461621505,40),
233                 // billboard: {
234                 //     image: \'images/loading.gif\',
235                 //     width: 12,
236                 //     height: 40,
237                 // },
238                 label : {
239                     text : data.name,//\'南京市大光路不动产登记中心\',
240                     font : \'18pt 宋体\',    //字体样式
241                     fillColor:Cesium.Color.BLUE,        //字体颜色
242                     backgroundColor:Cesium.Color.WHITE,    //背景颜色
243                     showBackground:true,                //是否显示背景颜色
244                     style: Cesium.LabelStyle.OUTLINE,        //label样式
245                     outlineWidth : 2,                    
246                     verticalOrigin : Cesium.VerticalOrigin.CENTER,//垂直位置
247                     horizontalOrigin :Cesium.HorizontalOrigin.LEFT,//水平位置
248                     pixelOffset:new Cesium.Cartesian2(10,0)            //偏移
249                 }
250             });
251 
252             viewer.entities.add({
253                 name:"",
254                 polyline: {
255                     positions: Cesium.Cartesian3.fromDegreesArrayHeights([
256                         data.lon,data.lat,40,
257                         data.lon,data.lat, 50,]
258                     ),
259                     width: 4,
260                     material : new Cesium.PolylineGlowMaterialProperty({ //发光线
261                         glowPower : 0.1,
262                         color : Cesium.Color.WHITE
263                     })
264                 }
265             });
266             viewer.entities.add({
267                 position : Cesium.Cartesian3.fromDegrees(data.lon,data.lat,50),
268                 point : {
269                     pixelSize : 10,
270                     color : Cesium.Color.WHITE
271                 }
272             });
273 
274         };
275 
276         //随机加载气泡效果
277         var load_certs_bubbles = function(){
278             $.get(\'data2.json\', function(Json){
279                 // console.log(Json.data);
280                 var arr = [];
281                 for(var i in Json.data){
282                     arr.push(Json.data[i]);
283                 }
284                 // console.log(arr.length);
285                 var j = 0;
286                 var interval =setInterval(function () {
287                     var id=(j+"x").toString();
288                     entity_label(arr[j].lon, arr[j].lat, 20,arr[j].JZWMC,id );
289                     j++
290                     if (j >= arr.length) {
291                         clearInterval(interval);
292                     }
293                 }, GetRandomNum(500, 1500));
294                 //remove
295                 var i=0;
296                 var interval2 =setInterval(function () {
297                     //console.log(i+"out");
298                     const labelEntity = viewer.entities.getById((i+"x").toString() );
299                     viewer.entities.remove(labelEntity);
300                     i++
301                     if (i >= arr.length) {
302                         clearInterval(interval2);
303                     }
304                 }, GetRandomNum(500, 4000));
305 
306             });
307 
308             var entity_label= function(lon,lat,height,jzwmc,value){
309                 var entity_label = viewer.entities.add({
310                     id: value,
311                     position: Cesium.Cartesian3.fromDegrees(lon, lat, height),
312                     // point: {
313                     //     color: Cesium.Color.RED,    //点位颜色
314                     //     pixelSize: 0                //像素点大小
315                     // },
316                     billboard: {
317                         image: \'images/location4.png\',
318                         width: 12,
319                         height: 14,
320                     },
321                     label: {
322                         text: jzwmc,
323                         font: \'9pt Source Han Sans CN\',    //字体样式
324                         fillColor: Cesium.Color.BLACK ,        //字体颜色
325                         backgroundColor: Cesium.Color.ALICEBLUE,    //背景颜色
326                         showBackground: true,                //是否显示背景颜色
327                         style: Cesium.LabelStyle.FILL,        //label样式
328                         outlineWidth: 2,
329                         verticalOrigin: Cesium.VerticalOrigin.CENTER,//垂直位置
330                         horizontalOrigin: Cesium.HorizontalOrigin.LEFT,//水平位置
331                         pixelOffset: new Cesium.Cartesian2(10, 0)            //偏移
332                     }
333                 });
334 //                 //添加尾迹线
335 //                 var pos= regCenterArr[Math.round(Math.random()*(regCenterArr.length-1))];
336 //                 viewer.entities.add({
337 //                     description: \'trail-line\',
338 //                     name: \'test\',
339 //                     polyline: {
340 //                         width: 1, //positions: Cesium.Cartesian3.fromDegreesArray([118.872007133102 ,32.5654461621505, lon, lat]),
341 //                         positions: Cesium.Cartesian3.fromDegreesArray([pos[0] ,pos[1], lon, lat]),
342 //                         material: new Cesium.PolylineTrailMaterialProperty({ // 尾迹线材质
343 //                             color: Cesium.Color.fromCssColorString("rgba(118, 233, 241, 1.0)"),
344 //                             trailLength : 0.2,
345 //                             period : 5.0
346 //                         })
347 //                     }
348 //                 });
349             };
350             var GetRandomNum = function(Min,Max){  
351                 var Range = Max - Min;  
352                 var Rand = Math.random();  
353                 return(Min + Math.round(Rand * Range));  
354             }  
355         }
356 
357         /**
358         *两个圆扩散纹理
359         * */
360         function addCircleRipple(viewer,data){
361             var r1=data.minR,r2=data.minR;
362 
363             function changeR1() { //这是callback,参数不能内传
364                 r1=r1+data.deviationR;
365                 if(r1>=data.maxR){
366                     r1=data.minR;
367                 }
368                 return r1;
369             }
370             function changeR2() {
371                 r2=r2+data.deviationR;
372                 if(r2>=data.maxR){
373                     r2=data.minR;
374                 }
375                 return r2;
376             }
377             viewer.entities.add({
378                 id:data.id,
379                 name:"",
380                 position:Cesium.Cartesian3.fromDegrees(data.lon,data.lat,data.height),
381                 ellipse : {
382                     semiMinorAxis :new Cesium.CallbackProperty(changeR1,false),
383                     semiMajorAxis :new Cesium.CallbackProperty(changeR2,false),
384                     height:data.height,
385                     material:new Cesium.ImageMaterialProperty({
386                         image:data.imageUrl,
387                         repeat:new Cesium.Cartesian2(1.0, 1.0),
388                         transparent:true,
389                         color:new Cesium.CallbackProperty(function () {
390                         var alp=1-r1/data.maxR;
391                             return Cesium.Color.WHITE.withAlpha(alp)  //entity的颜色透明 并不影响材质,并且 entity也会透明哦
392                         },false)
393                     })
394                 }
395             });
396             setTimeout(function () {
397                 viewer.entities.add({
398                     name:"",
399                     position:Cesium.Cartesian3.fromDegrees(data.lon,data.lat,data.height),
400                     ellipse : {
401                         semiMinorAxis :new Cesium.CallbackProperty(changeR1,false),
402                         semiMajorAxis :new Cesium.CallbackProperty(changeR2,false),
403                         height:data.height,
404                         material:new Cesium.ImageMaterialProperty({
405                             image:data.imageUrl,
406                             repeat:new Cesium.Cartesian2(1.0, 1.0),
407                             transparent:true,
408                             color:new Cesium.CallbackProperty(function () {
409                                 var alp=1;
410                                 alp=1-r2/data.maxR;
411                                 return Cesium.Color.WHITE.withAlpha(alp)
412                             },false)
413                         })
414                     }
415                 });
416             },data.eachInterval)
417         }
418 
419     }
420 </script>
421 </body>
422 </html>

View Code

发布

再重新部署一套iServer就可以了。把写好的html文件。Data.Json, fly飞行路线文件按原文件存放就可以了。

 http://localhost:8090/WebGL/examples/test1.html

 

 

 QQ 276605216

2019.12.18

 

 

 

 

版权声明:本文为yansc原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/yansc/p/12294186.html