赞
踩
接到了一个需求,一个物联网的电力保障系统实时监控。实施用到了Web 3D技术,以前用过一段时间的Three.js,因为太耗资源,没怎么铺开,现在硬件条件好了,就拿出来试试。
环境:blender-2.93.6-windows-x64+Three.js 0.91.0+Echart2.0
我习惯不用最新版本的软件做开发,一方面新版的稳定性不如旧版,主要是基于js的前端开发,新版大部分对IE都不友好,国内的需求现状就是,问就是随便,验收就拿IE说事,所以多一事不如少一事,就用旧的成熟版本对付了。
首先是3D建模,打开blender,一通XJB操作,做出模型长这样:
然后把工业电区和农用电区分开,按照硬件的分布编好号(部分检测设备在一层并且比较近,就编在一起,报警时候单独处置)。
然后建一个html,按照监控屏的分辨率1920*1080设置一个画布、背景 什么的,建一个对象叫做three,作为我们绘制模型的容器。
#three{width:1920px;height:1080px;position:absolute;z-index:1}
<div id="three"></div>
建一个js文件,加载模型,按照不同的供电方式设置材质:
function init() {
var container = document.getElementById("three");
camera = new THREE.PerspectiveCamera( 45, sceneWidth / sceneHeight, 1, 4000 );
//camera.position.set(900, 400, 900);
camera.position.set(300, 600, -1400);
scene = new THREE.Scene();
//scene.rotation.set(0,Math.PI,0);
scene.rotation.y = 0.5;
scene.background = new THREE.Color('#394855');
scene.fog = new THREE.Fog('#394855', 2000, 2500 );
var hemiLight = new THREE.HemisphereLight( 0xFFFFFF, 0x444444);
hemiLight.position.set( 0, 500, -300 );
scene.add( hemiLight );
var dirLight = new THREE.DirectionalLight('#FFFFFF');
dirLight.position.set( 100, 300, 200 );
dirLight.castShadow = true;
dirLight.shadow.camera.top = 1000;
dirLight.shadow.camera.bottom = - 1000;
dirLight.shadow.camera.left = - 1000;
dirLight.shadow.camera.right = 1000;
dirLight.shadow.camera.far=1000;
dirLight.shadow.mapSize.width = 1024;
dirLight.shadow.mapSize.height = 1024;
scene.add( dirLight );
//scene.add(new THREE.CameraHelper( dirLight.shadow.camera ) );
//地板
//var textureLoader=new THREE.TextureLoader();
//var texture = textureLoader.load("../images/ground.png");
//var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( {map:texture,color: '#2B3745', depthWrite: false } ) );
var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 8000, 8000 ), new THREE.MeshBasicMaterial( {color: '#394855', depthWrite:false } ) );
mesh.rotation.set(- Math.PI / 2,0,0);
mesh.receiveShadow = true;
scene.add( mesh );
var grid = new THREE.GridHelper(8000, 200, '#556B80','#556B80');
grid.material.opacity = 0.2;
grid.material.transparent = true;
//grid.rotation.set(0,100,0);
scene.add(grid);
var loader = new THREE.FBXLoader();
loader.load('/object/factory.fbx', function ( object ) {
object.traverse( function ( child ) {
if ( child.isMesh ) {
var material =new THREE.MeshPhongMaterial( {color: '#2F3C46' ,opacity:1,transparent:true})
var material2 =new THREE.MeshStandardMaterial({color: '#394855' ,opacity:0.8,transparent:true})
var material1=new THREE.LineBasicMaterial( {
color: 0xffffff,
linewidth: 1,
linecap: 'round',
linejoin: 'round'
} );
child.material =material;
child.castShadow = true;
child.receiveShadow = true;
if(child.name=="ground") //地板
{
child.material=material2;
}
else if(child.name=="wall") //外墙
{
var textureLoader = new THREE.TextureLoader();
var alphaMap = textureLoader.load( 'images/alphaMap.png' );
var wallMaterial=new THREE.MeshBasicMaterial({
color: 0x005E9B,
side:THREE.DoubleSide,
transparent: true,
depthWrite: false,
alphaMap: alphaMap,
});
child.material=wallMaterial;
child.receiveShadow = false;
child.castShadow = false;
}
else if(child.name.indexOf("HF")==0) //民用电
{
child.material.color.set('#00538A');
if(child.name.indexOf("HF18")==0 )
{
var fined=false;
for(var i=0;i<selectNodes.length;i++)
{
if(selectNodes[i].name==child.name)
{
fined=true;
break;
}
}
//if(!fined) selectNodes.push(child);
}
}
else if(child.name.indexOf("TF")==0) //工业电
{
child.material.color.set('#917000');
//var text=createTitle(child.name);
//text.position.set(child.position.x,child.position.y+35,child.position.z);
//scene.add(text);
}
else if(child.name.indexOf("F")==0) //冷凝罐
{
child.material.color.set('#0099FF');
//var text=createTitle(child.name);
//text.position.set(child.position.x,child.position.y+25,child.position.z);
//scene.add(text);
}
else if(child.name.indexOf("NO")==0) //氮气
{
child.material.color.set('#FF0000');
//var text=createTitle(child.name);
//text.position.set(child.position.x,child.position.y+25,child.position.z);
//scene.add(text);
}
else if(child.name.indexOf("NH")==0) //氨气
{
child.material.color.set('#0000FF');
//var text=createTitle(child.name);
//text.position.set(child.position.x,child.position.y+25,child.position.z);
//scene.add(text);
}
else if(child.name.indexOf("YH")==0) //液化气
{
child.material.color.set('#00FF00');
//var text=createTitle(child.name);
//text.position.set(child.position.x,child.position.y+25,child.position.z);
//scene.add(text);
}
//console.log(child.name);
}
} );
scene.add( object );
} );
renderer = new THREE.WebGLRenderer( { antialias: true,alpha:true } );
//renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( sceneWidth, sceneHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
container.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set( 0, 0, 0 );
controls.update();
window.addEventListener( 'resize', onWindowResize );
}
一通操作以后,模型加载进来,页面长这样:
然后上面再加一个效果层,就是一个摄像机一样的东东,禁止它的鼠标响应。把要显示的东西都加上,页面长这样:
数据的刷新分两部分,常规的数据库信息(人员,统计指标什么的)就JQuery加载进来。监控的实时信息,引入MQTT.js和代理服务做个长连接,实时读取显示就行了,数据异常,就弹出个报警框然后发声音什么的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。