基于WebGL架构的3D可视化平台—平面图导航(二)

35次阅读

共计 6979 个字符,预计需要花费 18 分钟才能阅读完成。

前言
基于 WebGL 架构的 3D 可视化平台—平面图导航(一)中已经完成了 iframe 面板与我们的 3D 场景的简单交互,下面我们继续完善并给 iframe 页加上鼠标悬停事件让 iframe 页的 img 标签和我们场景中的 obj 一起动起来。
实现
第一步,还是使用之前的场景接着上次的继续,先编写 iframe 页。给每一个 img 标签都加上 onmouseover、onmouseout 事件。
<!DOCTYPE html><html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<meta http-equiv=”X-UA-Compatible” content=”ie=edge”>
<title>Document</title>
<style>
.total_image {
margin : 20px;
}
.total_image img{
cursor: pointer;
transition: all 0.6s;
width: 50px;
}
.total_image img:hover{
transform: scale(1.5);
position:relative;
z-index:100;
}
</style>
</head>
<body><div class=”total_image” style=”width: 500px;height: 280px;background-size: 100% auto”>
<img class=”model_imag” src=” 发电室 1.jpg” style=”float: left;display: block;width: 85px;height: 84px”
onclick=”onClick(‘PowerGenerationGroup_01′,’viewPoint_1’)” onmouseover=”onMouseOver(‘PowerGenerationGroup_01′,’viewPoint_1’)” onmouseout=”onMouseOut(‘PowerGenerationGroup_01’)”>

<img class=”model_imag” src=” 发电室 2.jpg” style=”float: left;display: block;width: 78px;height: 84px”
onclick=”onClick(‘PowerGenerationGroup_02′,’viewPoint_2’)” onmouseover=”onMouseOver(‘PowerGenerationGroup_02′,’viewPoint_2’)” onmouseout=”onMouseOut(‘PowerGenerationGroup_02’)”>

<img class=”model_imag” src=” 发电室 3.jpg” style=”float: left;display: block;width:170px;height: 84px”
onclick=”onClick(‘PowerGenerationGroup_03′,’viewPoint_3’)” onmouseover=”onMouseOver(‘PowerGenerationGroup_03′,’viewPoint_3’)” onmouseout=”onMouseOut(‘PowerGenerationGroup_03’)”>

<img class=”model_imag” src=” 发电室 4.jpg” style=”float: left;display: block;width:167px;height: 84px”
onclick=”onClick(‘PowerGenerationGroup_04′,’viewPoint_4’)” onmouseover=”onMouseOver(‘PowerGenerationGroup_04′,’viewPoint_4’)” onmouseout=”onMouseOut(‘PowerGenerationGroup_04’)”>

<div style=”display: block;float: left;width: 100px;height: 145px;background-color:white”>
<img class=”model_imag” src=” 办公室 1.jpg” style=”float: left;display: block;width:100px;height: 60px”
onclick=”onClick(‘Office’,’viewPoint_5′)” onmouseover=”onMouseOver(‘Office’,’viewPoint_5′)” onmouseout=”onMouseOut(‘Office’)”>
<img class=”model_imag” src=” 返回.png” style=”float: left;display: block;width:100px;height: 80px” onclick=”initViewPoint()”>
</div>

<img class=”model_imag” src=” 发电室 5.jpg” style=”float: right;display: block;width:123px”
onclick=”onClick(‘PowerGenerationGroup_05′,’viewPoint_8’)” onmouseover=”onMouseOver(‘PowerGenerationGroup_05′,’viewPoint_8’)” onmouseout=”onMouseOut(‘PowerGenerationGroup_05’)”>

<img class=”model_imag” src=” 会议室 1.jpg” style=”float: left;display: block;width: 138px;height: 145px” alt=””
onclick=”onClick(‘BoardRoom_01′,’viewPoint_6’)” onmouseover=”onMouseOver(‘BoardRoom_01′,’viewPoint_6’)” onmouseout=”onMouseOut(‘BoardRoom_01’)”>

<img class=”model_imag” src=” 会议室 2.jpg” style=”float: left;display: block;width: 138px;height: 145px” alt=””
onclick=”onClick(‘BoardRoom_02′,’viewPoint_7’)” onmouseover=”onMouseOver(‘BoardRoom_02′,’viewPoint_7’)” onmouseout=”onMouseOut(‘BoardRoom_02’)”>
</div>
<script>
function onClick(viewPoint,target){
window.parent.onClick(viewPoint,target);
}

function onMouseOver(targetObj,viewPoint){
window.parent.onMouseOver(targetObj,viewPoint);
}
function onMouseOut(targetObj){
window.parent.onMouseOut(targetObj);
}
function initViewPoint(){
window.parent.initViewPoint();
}
</script>
</body></html>

第二步,房间里的物体不要要让他“飞起来”,还要给他加一个“底座”。这里叫他 SurveillanceCamera 类,在自己编写类的时候一定要注意,想要当前类生效一定要继承 THING.Thing,并且 THING.factory.registerClass(‘ClassName’, ClassName);
class SurveillanceCamera extends THING.Thing {
constructor(app) {
super(app);
this.app = app;
this.isFrustum = true;
this.opacity = 1;
this.color = 0xff00ff;
this.vertices = [];
this.near = 0.1;
this.camera = null;
this.node = new THREE.Object3D();
this._frustum = new THREE.Frustum();
this._projScreenMatrix = new THREE.Matrix4();

}

setup(param) {
super.setup(param);
this.fov = param[‘fov’];
this.aspect = param[‘aspect’];
this.far = param[‘far’];
this.alpha = param[‘alpha’];
this.lineAlpha = param[‘lineAlpha’];
this.setupComplete(param);
}

setupComplete(param) {
super.setupComplete(param);
this.build();
}

build() {
if (this.node.children.length > 0) {
this.node.children = [];
}

if (this.camera != null) {
this.camera = null;
}

var h = this.far * Math.tan(this.fov * 0.5 * 0.017453293);
var w = this.aspect * h;

var geometry = new THREE.Geometry();
this.vertices = [new THREE.Vector3(0, 0, 0), new THREE.Vector3(w, -h, -this.far), new THREE.Vector3(w, h, -this.far), new THREE.Vector3(-w, h, -this.far), new THREE.Vector3(-w, -h, -this.far)];
var faces = [new THREE.Face3(0, 1, 2), new THREE.Face3(0, 2, 3), new THREE.Face3(0, 3, 4), new THREE.Face3(0, 4, 1), new THREE.Face3(3, 4, 1), new THREE.Face3(3, 1, 2)];
geometry.vertices = this.vertices;

var line_mat = new THREE.LineBasicMaterial({
color: “#b4f5f8”,
opacity: this.lineAlpha || 0.5,
})

var texture = THREE.ImageUtils.loadTexture(“images/light2.png”);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
var frustum_mat = new THREE.MeshBasicMaterial({
color: “#0aa5ff”,
opacity: this.alpha || 0.5,
transparent: true,
side: THREE.DoubleSide,
});
var line_mesh = new THREE.Line(geometry, line_mat);

var frustum_mesh = new THREE.Mesh(geometry, frustum_mat);
geometry.faces = faces;
this.node.add(frustum_mesh, line_mesh);

this.camera = new THREE.PerspectiveCamera(this.fov, this.aspect, this.near, this.far);
this.camera.position.set(this.position[0], this.position[1], this.position[2]);
this.camera.rotation.copy(this.node.rotation);

this.camera.updateMatrixWorld(true);
this._updateFrustum();
}

setPosition() {
this.camera.position.set(this.position[0], this.position[1], this.position[2]);
this.camera.updateMatrixWorld(true);
this._updateFrustum();
}

_updateFrustum() {
if (this.camera) {
this._projScreenMatrix.multiplyMatrices(this.camera.projectionMatrix, this.camera.matrixWorldInverse);
this._frustum.setFromMatrix(this._projScreenMatrix);
}
}

intersectsObject(object) {
this._updateFrustum();
return this._frustum.intersectsObject(object);
}

intersectsBox(box) {
this._updateFrustum();
return this._frustum.intersectsBox(box);
}

intersectsSphere(sphere) {
this._updateFrustum();
return this._frustum.intersectsSphere(sphere);
}

intersectsSprite(sprite) {
this._updateFrustum();
return this._frustum.intersectsSprite(sprite);
}
}
THING.factory.registerClass(‘SurveillanceCamera’, SurveillanceCamera);
第三步,鼠标悬浮事件和鼠标离开事件,这里我们使用了之前创建的 SurveillanceCamera 类为 obj 加上了一个“底座”。
// 鼠标悬浮事件 function onMouseOver(targetObj,viewPoint) {
if (currentModule != null)
return;
overModule = app.query(targetObj)[0];
overModule.style.boundingBox = true;
overModule.moveTo({
“offset”: [0, 6, 0],
“time”: 80,
});
sCamera = app.create({
type: ‘SurveillanceCamera’,
name: ‘SurveillanceCamera_’,
position:app.query(viewPoint)[0].position,
fov: 65,
aspect: 1.3,
far: 6,
});
sCamera.angleX = 90;
sCamera.style.opacity = 0.1;
}// 鼠标离开事件 function onMouseOut(targetObj) {
if (currentModule != null)
return;
if (sCamera) {
sCamera.destroy();
sCamera = null;
}
outModule = overModule;
outModule.style.boundingBox = false;
outModule.stopMoving();
outModule.position = [0, 0, 0];
outModule = null;
}
演示地址:EXAMPLE
总结
利用 iframe 与 ThingJS 进行交互完成了平面图导航功能,通过自制的 HTML 界面,嵌入 ThingJS 的面板中,形成一个可自定义的导航界面,通过偏移实现相应的视觉效果。
制作一个视锥,达到投放影像的效果,这里运用面向对象的方式是为了,能够更快捷的创建视锥,起到复用的作用。
在制作过程中,将物体悬浮的过程时出现了问题,发现如果快速的操作鼠标,物体不会达到预期的视觉效果,例如,鼠标快速的在两个导航图之间切换时,对应的两个物体会不断的上升,尽管将上升与还原的速度加快,也依然无法解决问题。最后解决的办法是:新添加一个变量,将上一次悬浮的物体记录下来,就是文中的 outModule,通过对 outModule 单独操作来解决影响问题。

正文完
 0