一、vue使用three.js实现开关门
1、实现效果
使用button按钮来控制开关门。
默认是关门状态,当点击“向左/向右/向上/向下开门”按钮时实现某个方向的开门效果,点击“关门按钮”实现关门的效果。开门后必须先进行上门操作,才能进行其他方向的开门操作,否则将提示:请先点击“关门按钮”。
当在http://localhost:8080/#/onoffnew?a=80&b=80 中修改参数a和参数b的大小可以改变模型宽高,此时不影响开关门效果。
2、实现思路
2.1、建立一个盒子模型。
(1)定义一个Scene、PerspectiveCamera、WebGLRenderer以及包含AmbientLight和DirectionalLight的混合光。
(2)设置六个不同的面,给每个面的外层贴上不同的纹理材质,里层贴上相同的纹理材质。
(3)外层中六个不同的mesh通过position和rotation属性组合成一个盒子模型,设置好后先不添加到scene中。
(4)内层中六个cube主要旋转Math.PI,使其翻转(cube中Material.side默认是THREE.FrontSide),然后将其添加到mesh里,最后将mesh添加到scene中。
(5) 最后将六个面通过group.add()方法组合成一个盒子,并将其添加到scene中。
2.2、开关门的实现
(1)为了更好地适应页面的风格,我们通过5个button按钮的v-on:click = ' '
方法来实现关门和向左、向右、向上、向下开门。
<el-row>
<el-button type="primary" v-on:click = 'closeDoor'>关门按钮</el-button>
<el-button type="success" v-on:click = 'openLeft'>向左开门</el-button>
<el-button type="success" v-on:click = 'openRight'>向右开门</el-button>
<el-button type="success" v-on:click = 'openUp'>向上开门</el-button>
<el-button type="success" v-on:click = 'openDown'>向下开门</el-button>
</el-row>
(2)开门效果的实现:
door_state和direction的初始设置为true。当door_state为true时,可进行开门操作。
将要旋转的一个面绕着其某一边缘进行一定角度的旋转,如同打开门一样。然后根据旋转角度计算得到旋转后该面中心位置的x、y、z的位置坐标,并将其设置为该面的位置坐标即可实现开门效果。
最后设置door_state和direction的布尔类型。
其中旋转后位置核心计算方法如下:
假设旋转的是模型加载那一刻看到的面,该面在左右开门的情况下,其在y轴上的坐标位置是未发生变化,所以只需要计算在x轴和z轴的坐标位置。下图是在不考虑y轴下,转化为二维坐标计算。(上下开门时同理,只是此时未发生变化的是x轴上位置坐标。)
假设在开门时面的中心位置从A移动到B点,旋转过程中面的大小是不变的,只是位置发生了改变,所以我们可以把旋转的过程轨迹看成是一小段扇形区域。
设扇形半径为r,旋转角度为θ。建立如下坐标轴。那么问题就转化为如何计算B点坐标即可,下图中B点坐标为*(-(r-rcosθ),-rsinθ)。
当然,计算的思路提供了。但最终的位置坐标需要根据开门方向以及在坐标系中位置灵活应用。
openLeft() {
if(this.door_state){
let angle = -Math.PI/4;
this.mesh1.rotation.y = angle;
let a = 0 - (this.width * 0.5 *(1-Math.cos(angle)));
let b = 0;
let c = this.depth/2 + this.width *0.5 *Math.sin(Math.abs(angle));
this.mesh1.position.set(a, b,c);
this.door_state = false;
this.direction = true;
}
else{
alert('请先点击“关门按钮”!')
}
},
openRight(){
if(this.door_state){
this.mesh1.position.set(0,0,this.depth/2);
this.mesh1.rotation.y =0 ;
let angle = Math.PI/4;
this.mesh1.rotation.y = angle;
let a = 0 + (this.width * 0.5 *(1-Math.cos(angle)));
let b = 0;