cesium三维开发全过程记录
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