以下是我以前學習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>
發布
再重新部署一套iServer就可以了。把寫好的html文件。Data.Json, fly飛行路線文件按原文件存放就可以了。
http://localhost:8090/WebGL/examples/test1.html
QQ 276605216
2019.12.18