隨著(zhù)社會(huì )的發(fā)展,城市中的汽車(chē)越來(lái)越多。車(chē)輛集中存放管理的場(chǎng)所被人類(lèi)提出車(chē)輛進(jìn)出的秩序、車(chē)輛存放的安全性、車(chē)輛存放管理的有償性等要求。停車(chē)場(chǎng)系統應用現代機械電子及通訊科學(xué)技術(shù),集控制硬件、軟件于一體。隨著(zhù)科技的發(fā)展,停車(chē)場(chǎng)管理系統也日新月異,目前最為專(zhuān)業(yè)化的停車(chē)場(chǎng)系統為免取卡停車(chē)場(chǎng)。下面我們就用ThingJs平臺來(lái)搭建一個(gè)3d可視化的停車(chē)場(chǎng)管理系統。




下面我們就用ThingJs平臺來(lái)搭建一個(gè)3d可視化的停車(chē)場(chǎng)管理系統。
使用CampusBuilder來(lái)搭建一個(gè)模擬停車(chē)場(chǎng)。CampusBuider很好用在以往的文章中也多次提及過(guò),豐富的模型庫任你選擇快速搭建3D場(chǎng)景。

初始化攝像機的位置并添加鼠標滑過(guò),左鍵單擊,右鍵單擊,左鍵雙擊等事件。鼠標滑過(guò),車(chē)勾邊變紅色,車(chē)位勾邊邊藍色。左鍵單擊,車(chē)或車(chē)位彈出信息牌。右鍵單擊,關(guān)閉當前信息牌,鏡頭初始化。getCarData() 與 getParkData() 為模擬數據,沒(méi)有幾個(gè)售出的車(chē)位和車(chē)就用了switch。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | app.on('load', function (evt) { //初始化攝像機 init_camera(); //滑過(guò)勾邊 var campus = evt.campus; var objs = app.query('.Building').add(campus.things); objs.on('mouseon', function (ev) { if (ev.object.name.search("car") == 0) { this.style.outlineColor = '#ff0000'; } if (ev.object.name.search("park") == 0) { this.style.outlineColor = '#0000ff'; } }); objs.on('mouseoff', function () { this.style.outlineColor = null; }); //單擊事件 app.on('click', function (ev) { if (ev.button == 2) { destroy_ui(); init_camera(); } if (ev.object.name.search("car") == 0) { destroy_ui(); getCarData(ev.object); create_ui_car(); } if (ev.object.name.search("park") == 0) { destroy_ui(); getParkData(ev.object); create_ui_park(); } }); //雙擊事件 app.on('dblclick', function (ev) { if (ev.object.name.search("car") == 0) { app.camera.flyTo({ 'time': 1500, 'object': ev.object, 'position': [0, 0, 0], 'complete': function () { } }); } if (ev.object.name.search("park") == 0) { app.camera.flyTo({ 'time': 1500, 'object': ev.object, 'position': [0, 5, 0], 'complete': function () { } }); } });});//初始化攝像機function init_camera() { // 攝像機飛行到某位置 app.camera.flyTo({ 'position': [-67.95670997548082, 49.69517426520041, -42.88366089402964], 'target': [-7.188588318222256, 14.094194791658271, -12.724756207211417], 'time': 800, 'complete': function () { console.log("Camera ready"); } });}//創(chuàng )建面板var panel;var dataObj;var carInfo;var parkInfo;function create_ui_car() { panel = new THING.widget.Panel({ titleText: "車(chē)輛信息", closeIcon: true, // 是否有關(guān)閉按鈕 dragable: true, retractable: true, opacity: 0.9, hasTitle: true, titleImage: 'https://www.thingjs.com/static/images/example/icon.png' }); panel.position = [0, 326]; // 創(chuàng )建任意對象 dataObj = { name: carInfo[0], info: carInfo[1], park: carInfo[2], plateNum: carInfo[3], state: carInfo[4], contactNum: carInfo[5] }; // 動(dòng)態(tài)綁定物體 var name = panel.addString(dataObj, 'name').caption('車(chē)主姓名'); var info = panel.addString(dataObj, 'info').caption('車(chē)主信息'); var park = panel.addString(dataObj, 'park').caption('車(chē)位編號'); var plateNum = panel.addString(dataObj, 'plateNum').caption('車(chē)牌號碼'); var contactNum = panel.addString(dataObj, 'contactNum').caption('聯(lián)系電話(huà)'); var state = panel.addString(dataObj, 'state').caption('車(chē)位狀態(tài)');}function create_ui_park() { panel = new THING.widget.Panel({ titleText: "車(chē)位信息", closeIcon: true, // 是否有關(guān)閉按鈕 dragable: true, retractable: true, opacity: 0.9, hasTitle: true, titleImage: 'https://www.thingjs.com/static/images/example/icon.png' }); panel.position = [0, 326]; dataObj = { park: parkInfo[0], name: parkInfo[1], state: parkInfo[2], date: parkInfo[3] }; var park = panel.addString(dataObj, 'park').caption('車(chē)位編號'); var name = panel.addString(dataObj, 'name').caption('車(chē)主姓名'); var state = panel.addString(dataObj, 'state').caption('車(chē)位狀態(tài)'); var date = panel.addString(dataObj, 'date').caption('車(chē)位期限');}function destroy_ui() { if (panel) { panel.destroy(); panel = null; }}function getCarData(obj) { switch (obj.name) { case "car_0": carInfo = ['張三', '28#1-302', 'A-06', '吉K49278', '未交費', '13159828222']; break; case "car_1": carInfo = ['李四', '18#2-1202', 'B-04', '吉A46154', '已交費', '13159828222']; break; case "car_2": carInfo = ['王五', '13#2-702', 'B-05', '吉D95868', '已交費', '13159828222']; break; case "car_3": carInfo = ['郭富貴', '3#3-802', 'B-09', '吉B46278', '已交費', '13159828222']; break; case "car_4": carInfo = ['薛展暢', '8#3-1302', 'C-03', '吉A44278', '未交費', '13159828222']; break; case "car_5": carInfo = ['李文忠', '6#2-302', 'C-05', '黑B77865', '已交費', '13159828222']; break; case "car_6": carInfo = ['李洪春', '8#2-402', 'D-08', '吉CJ87821', '未交費', '13159828222']; break; case "car_7": carInfo = ['孟旭浩', '9#2-801', 'D-16', '吉A4U278', '已交費', '13159828222']; break; case "car_8": carInfo = ['劉星辰', '4#2-502', 'D-20', '吉A98378', '已交費', '13159828222']; break; case "car_9": carInfo = ['張星辰', '4#1-302', 'E-04', '吉A98378', '已交費', '13159828222']; break; case "car_10": carInfo = ['張星辰', '8#2-302', 'D-01', '京A44378', '已交費', '13159228222']; break; }}function getParkData(obj) { switch (obj.name) { case "park_5": parkInfo = ['A-06', '張三', '已交', '2018.5.10-2020.5.11']; break; case "park_11": parkInfo = ['B-09', '郭富貴', '已交', '2018.5.10-2020.5.11']; break; case "park_16": parkInfo = ['B-05', '王五', '欠費', '2018.5.10-2020.5.11']; break; case "park_17": parkInfo = ['B-04', '李四', '已交', '2018.5.10-2020.5.11']; break; case "park_40": parkInfo = ['C-03', '薛展暢', '已交', '2018.5.10-2020.5.11']; break; case "park_44": parkInfo = ['C-05', '李文忠', '已交', '2018.5.10-2020.5.11']; break; case "park_68": parkInfo = ['D-08', '李洪春', '已交', '2018.5.10-2020.5.11']; break; case "park_78": parkInfo = ['E-04', '張星辰', '已交', '2018.5.10-2020.5.11']; break; case "park_59": parkInfo = ['D-16', '孟旭浩', '已交', '2018.5.10-2020.5.11']; break; case "park_67": parkInfo = ['D-20', '劉星辰', '已交', '2018.5.10-2020.5.11']; break; case "park_3": parkInfo = ['A-04', '劉地辰', '已交', '2018.5.10-2020.5.11']; break; case "park_54": parkInfo = ['D-1', '龍的辰', '未交', '2018.5.10-2020.5.11']; break; default: parkInfo = ['X-xx', 'XXX', '未售出', '2000.1.1-2020.1.1']; }} |
創(chuàng )建主面板添加空間統計,閘門(mén)管理,播放動(dòng)畫(huà),出入登記等功能按鈕,同時(shí)創(chuàng )建閘門(mén)管理子面板。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | //主面板var toolbar = new THING.widget.Panel({ width: '163px' });var mainDataObj = { spaceStatistics: false, gateManagement: false, video: false, registrationForm: false}//閘門(mén)管理面板var gateToolbar = new THING.widget.Panel({ width: '163px' });gateToolbar.position = [450, 0];gateToolbar.visible = false;var gateDataObj = { entrance: false, exit: false,}//面板按鈕組件及事件Loader.sync(['lib/iconfont.js'], function () { //主面板 var button0 = toolbar.addImageBoolean(mainDataObj, 'spaceStatistics').caption('空間統計').url('#momoda_lc-icontubiao'); var button1 = toolbar.addImageBoolean(mainDataObj, 'gateManagement').caption('閘門(mén)管理').url('#momoda_lc-icontubiao21'); var button2 = toolbar.addImageBoolean(mainDataObj, 'video').caption('播放動(dòng)畫(huà)').url('#momoda_lc-icontubiao9'); var button3 = toolbar.addImageBoolean(mainDataObj, 'registrationForm').caption('出入登記').url('#momoda_lc-icontubiao10'); //閘門(mén)面板 var button4 = gateToolbar.addImageBoolean(gateDataObj, 'entrance').caption('入口管理').url('#momoda_lc-icontubiao21'); var button5 = gateToolbar.addImageBoolean(gateDataObj, 'exit').caption('出口管理').url('#momoda_lc-icontubiao21'); //第四步中的功能實(shí)現}); |
為上面創(chuàng )建的功能按鈕實(shí)現功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | //空間統計 var opacityFlag = true; button0.on('change', function () { if (opacityFlag) { opacityFlag = false; app.query(/park/).forEach( function (obj) { var str = obj.name; switch (str) { case "park_5": break; case "park_11": break; case "park_16": break; case "park_17": break; case "park_40": break; case "park_44": break; case "park_68": break; case "park_78": break; case "park_59": break; case "park_67": break; case "park_33": break; case "park_54": break; case "park_3": break; default: obj.style.opacity = 0.3; } } ); } else { opacityFlag = true; app.query(/park/).forEach( function (obj) { obj.style.opacity = 1; } ) } }); //閘門(mén)管理,入口管理,出口管理 var gateToolbarFlag = true; var entranceFlag = false; var exitFlag = false; button1.on('change', function () { if (gateToolbarFlag) { app.camera.flyTo({ 'position': [-69.15232764795844, 12.556743445078443, -4.722896106654333], 'target': [-6.75806618043438, 11.584727439263146, -5.077821719000649], 'time': 1000 }); gateToolbarFlag = false; gateToolbar.visible = true; } else { init_camera(); gateToolbarFlag = true; gateToolbar.visible = false; } }); button4.on('change', function () { var entry = app.query('入口')[0]; if (!entranceFlag) { entranceFlag = true; entry.rotateX(45.0); entry.moveY(2); entry.moveZ(-1); } else { entranceFlag = false; entry.rotateX(-45.0); entry.position = [0, 0, 0]; } }); button5.on('change', function () { var exit = app.query('出口')[0]; if (!exitFlag) { exitFlag = true; exit.rotateX(-45.0); exit.moveY(9.2); exit.moveZ(4.3); } else { exitFlag = false; exit.rotateX(-315.0); exit.position = [0, 0, 0]; } }); //播放動(dòng)畫(huà) button2.on('change', function () { //飛向每一個(gè)攝像機的位置 console.log("監控設備!"); playCar(); }); //出入登記 registrationFlag = true; button3.on('change', function () { //顯示兩塊信息板,鏡頭飛向門(mén)禁 // 攝像機飛行到某位置 if (registrationFlag) { app.camera.flyTo({ 'position': [-13.229586070519874, 13.062016938601909, -14.789241424512456], 'target': [-21.25078065116403, 11.949594230222267, -11.972835509196605], 'time': 1000, }); registrationFlag = false; create_ui_gate_exit(); create_ui_gate_entry(); } else { registrationFlag = true; entryUi.destroy(); entryUi = null; exitUi.destroy(); exitUi = null; } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | var car = app.create({ type: 'Thing', name: 'car_10', url: 'http://model.3dmomoda.cn/models/c6ed424627234a298c1921950eb8534c/0/gltf/', // 模型地址 position: [-45.89714816093272, 0.043936770289323, 0.312388718621647], // 位置 angle: 90,});var points = [];points.push([-45.89714816093272, 0.043936770289323, 0.312388718621647]);points.push([-38.89714816093272, 0.043936770289323, 0.312388718621647]);var radius = 2for (var degree = 0, y = 0; degree <= 90; degree += 20) { var x = Math.sin(degree * 2 * Math.PI / 360) * radius - 35.89714816093272; var z = -Math.cos(degree * 2 * Math.PI / 360) * radius + 2.312388718621647; points.push([x, y, z]); console.log([x, y, z]);}points.push([-33.927532654908305, 0, 4.9650923632877861]);points.push([-33.927532654908305, 0, 7.9650923632877861]);points.push([-33.927532654908305, 0, 10.9650923632877861]);points.push([-33.927532654908305, 0, 13.9650923632877861]);var line = app.create({ type: 'Line', color: 0xFFFF00, // 軌跡線(xiàn)顏色 dotSize: 2, // 軌跡點(diǎn)的大小 points: points,});line.visible = false;function playCar() { var car = app.query('car_10')[0]; var entry = app.query('入口')[0]; entry.rotateX(45.0); entry.moveY(2); entry.moveZ(-1); car.movePath({ 'path': line.points, // 軌跡路線(xiàn) 'time': 5000, // 移動(dòng)時(shí)間 'orientToPath': true, // 物體移動(dòng)時(shí)沿向路徑方向 }); setTimeout(function () { entry.rotateX(-45.0); entry.position = [0, 0, 0]; }, 2000)} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | //出入登記function create_html_entry() { var sign1 = `<div class="sign1" id="board1" style="font-size: 12px;width: 230px;text-align: center;background-color: rgba(0, 0, 0, .6);border: 3px solid #eeeeee;border-radius: 8px;color: #eee;position: absolute;top: 0;left: 0;z-index: 10;display: none;"> <div class="s1" style="margin: 5px 0px 5px 0px;line-height: 32px;overflow: hidden;"> <span class="span-l icon" style="float: left;width: 30px;height: 30px;"></span> <span class="span-l font" style="float: left;margin: 0px 0px 0px 3px;">車(chē)輛進(jìn)入</span> <span class="span-r point" style="float: right;width: 12px;height: 12px;background-color: #18EB20;border-radius: 50%;margin: 10px 5px 10px 0px;"></span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;width:70px;margin: 0px 10px 0px 10px;">進(jìn)車(chē)時(shí)間</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">車(chē)牌號</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">9:15</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉K49278</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">10:15</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉A46154</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">10:17</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉D95868</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">10:25</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉B46278</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">10:39</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">黑B77865</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">11:19</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉CJ87821</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">11:21</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉A4U278</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">11:35</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉A98378</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">12:50</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉A98778</span> </div> <div class="point-top" style="position: absolute;top: -7px;right: -7px;background-color: #3F6781;width: 10px;height: 10px;border: 3px solid #eee;border-radius: 50%;"></div> </div>` $('#div3d').append($(sign1));}function create_html_exit() { var sign2 = `<div class="sign2" id="board2" style="font-size: 12px;width: 230px;text-align: center;background-color: rgba(0, 0, 0, .6);border: 3px solid #eeeeee;border-radius: 8px;color: #eee;position: absolute;top: 0;left: 0;z-index: 10;display: none;"> <div class="s1" style="margin: 5px 0px 5px 0px;line-height: 32px;overflow: hidden;"> <span class="span-l icon" style="float: left;width: 30px;height: 30px;"></span> <span class="span-l font" style="float: left;margin: 0px 0px 0px 3px;">車(chē)輛進(jìn)入</span> <span class="span-r point" style="float: right;width: 12px;height: 12px;background-color: #18EB20;border-radius: 50%;margin: 10px 5px 10px 0px;"></span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;width:70px;margin: 0px 10px 0px 10px;">出車(chē)時(shí)間</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">車(chē)牌號</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">7:15</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">黑B77865</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">8:45</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉A4U278</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">8:57</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉A98378</span> </div> <div class="s2" style="margin: 5px 0px 10px 0px;line-height: 18px;font-size: 10px;overflow: hidden;"> <span class="span-l font1" style="float: left;margin: 0px 10px 0px 10px;">10:01</span> <span class="span-l font2" style="float: left;width: 140px;background-color: #2480E3;">吉A98778</span> </div> <div class="point-top" style="position: absolute;top: -7px;right: -7px;background-color: #3F6781;width: 10px;height: 10px;border: 3px solid #eee;border-radius: 50%;"></div> </div>` $('#div3d').append($(sign2));}function create_element(str) { var srcElem = document.getElementById(str); var newElem = srcElem.cloneNode(true); newElem.style.display = "block"; app.domElement.insertBefore(newElem, srcElem); return newElem;}var entryUi = null;function create_ui_gate_entry() { create_html_entry(); entryUi = app.create({ type: 'UIAnchor', position: [-39.89714816093272, 3.043936770289323, 2.312388718621647], element: create_element("board1"), offset: [0, 2, 0], pivot: [0.5, 1] // 界面的重心 });}var exitUi = null;function create_ui_gate_exit() { create_html_exit(); exitUi = app.create({ type: 'UIAnchor', position: [-34.89714816093272, 6.059100472147456, -14.950719696627075], element: create_element("board2"), offset: [0, 2, 0], pivot: [0.5, 1] // 界面的重心 });} |
聯(lián)系客服