使用ThreeJs从零开始构建3D智能仓库——第四章(添加动画及库区)

写在前面

本章我们来探索下如何添加补间动画以及添加库区。效果如下图所示:
2019.11.26 更新:我最近建立了个人网站,大家可以访问下面的链接查看演示
3D仓库演示
2019.11.28 更新:代码和图片资源等已上传至GitHub
https://github.com/xiao149/ThreeJsDemo
在这里插入图片描述
因为上传GIF的大小限制为5M,所以只能截个开门的动画,关门的动画类似大家可以自行脑补。
添加库区后效果如下,库区的位置、长宽、字体的大小位置颜色都是可以根据自己的配置调整的,为了演示方便,我在这里就只添加一个库区:
在这里插入图片描述

使用TweenJS创建补间动画

TweenJS简介

  • TweenJS是使用 JavaScript 中的一个简单的补间动画库,支持数字、对象的属性和 CSS 样式属性的赋值。
  • TweenJS以平滑的方式修改元素的属性值,需要传递给 tween 要修改的值、动画结束时的最终值和动画花费时间(duration),之后 tween 引擎就可以计算从开始动画点到结束动画点之间值,从而产生平滑的动画效果。

大家可以从TweenJS的官网:点击跳转 下载到最新的JS文件。
下载下来后我们把Tween.js这个文件放到自己项目的目录下,然后在HTML中引入:

<script src="./ThreeJs/js/Tween.js"></script>

我用自己的话来简单介绍下这个库,我觉得英文单词between非常形象地描述了这个库的功能(毕竟这个库也叫Tween),这个库主要的作用就是创建补间动画,比如一扇门初始状态是关闭的,结束状态是打开的,TweenJS的作用就是在开始点和结束点之间做过度动画,从而实现开门或者关门的效果。

开关门动画的实现

因为我们是要点击一扇门之后,才会发生开门或者关门的动画,所以我们再次使用到了上一章自定义创建的ThreeJs_Composer.js,然后在这个文件中新增我们需要的代码:
首先我们定义四个全局变量(原谅我比较傻,四扇门只有创建四个变量了,true为关闭,false为打开):

var door_state_left1 = true; //默认是门是关闭的
var door_state_right1 = true; //默认是门是关闭的
var door_state_left2 = true; //默认是门是关闭的
var door_state_right2 = true; //默认是门是关闭的

然后在onMouseClick这个方法的最后添加:

if(intersects[0].object.name == "左门1"){
    if(door_state_left1){
        new TWEEN.Tween(intersects[0].object.rotation).to({
            y: -0.5*Math.PI
        }, 5000).easing(TWEEN.Easing.Elastic.Out).onComplete(function(){
        }).start();
        door_state_left1 = false;
    }else{
        new TWEEN.Tween(intersects[0].object.rotation).to({
            y: 0
        }, 5000).easing(TWEEN.Easing.Elastic.Out).onComplete(function(){
        }).start();
        door_state_left1 = true;
    }
}

其他三扇门依葫芦画瓢一样的我就不发了,当我们的鼠标点击“左门1”这个物体时,就会进入这个IF条件。

new TWEEN.Tween(intersects[0].object.rotation).to({
   y: -0.5*Math.PI
}, 5000).easing(TWEEN.Easing.Elastic.Out).onComplete(function(){
}).start();

上面这段关键代码的意思很简单,就是将点击到的物体的rotation属性,绕着Y轴旋转90度,5000是动画持续的时间,easing(TWEEN.Easing.Elastic.Out) 这段话的意思是动画会有个缓慢过渡的效果,大家可以看下面的两张GIF,前者是添加了easing效果的,关门后还会有一种来回晃动的效果(比较符合现实);后者是没有该效果的,关门时瞬间闭合。
在这里插入图片描述
在这里插入图片描述
最后我们需要在test.html中添加TweenJS动画的刷新,否则动画是没有效果的:

// 更新控件
function update() {
  stats.update();
  controls.update();
  TWEEN.update(); //刷新动画
}

全部的代码我就不贴了,大家可以回到第三章回顾下,本章只是在第三章的基础上添加了一些内容。

添加库区与文字

在这里我们又需要创建一个自定义的JS文件Modules.js,该文件存放建模相关的内容,本章的库区以及未来要添加的货架货物等都会放在这个文件里面。

/**
 * Modules.js是3D仓库显示模型存放的地方
 *
 * @author 谢宁
 */
/** ***************************************************************** */
//模型材质信息
var planeMat;

/** 初始化材质信息 */
function initMat() {
    planeMat = new THREE.MeshLambertMaterial();

    new THREE.TextureLoader().load( './ThreeJs/images/plane.png', function( map ) {
        planeMat.map = map;
        planeMat.transparent = true;
        planeMat.opacity = 0.8;
        planeMat.needsUpdate = true;
    } );
}

//region 库区
/** 放置虚线框区域和库区名称 */
function addArea(x,z,width,length,scene,name,textColor,font_size,textposition) {
    var geometry = new THREE.PlaneGeometry( width, length );
    var obj = new THREE.Mesh( geometry, planeMat );
    obj.position.set(x,1.5,z);
    obj.rotation.x = -Math.PI / 2.0;
    obj.name = "库区"+"$"+name.split("$")[1];
    scene.add( obj );

    new THREE.FontLoader().load('./ThreeJs/FZYaoTi_Regular.json',function(font){
        ////加入立体文字
        var text= new THREE.TextGeometry(name.split("$")[1],{
            // 设定文字字体
            font:font,
            //尺寸
            size:font_size,
            //厚度
            height:0.01
        });
        text.computeBoundingBox();
        //3D文字材质
        var m = new THREE.MeshStandardMaterial({color:"#" + textColor});
        var mesh = new THREE.Mesh(text,m)
        if(textposition == "左对齐"){
            mesh.position.x = x - width/2 + 10;
        }else if(textposition == "居中"){
            mesh.position.x = x - 15;
        }else if(textposition == "右对齐"){
            mesh.position.x = x + width/2 - 60;
        }
        mesh.position.y = 1.3;
        mesh.position.z = z + length/2 - 20;
        mesh.rotation.x = -Math.PI / 2.0;
        scene.add(mesh);
    });
}
//endregion

首先我们需要初始化库区这个物体的材质,我们使用了兰伯特材质的贴图,贴图就是一张正方形的框框,其他部分都是透明的,大家可以根据自己的喜好PS下。
在这里插入图片描述
再来描述下这个方法的参数,以我现在用的这个为例:x,z是库区的位置,width,length是库区的长度和宽度,scene是场景,name是库区的名字,用美元符号分隔,即 “库区英文ID$库区中文名”,textColor是显示文字的颜色,使用十六进制颜色代码,font_size是字体的大小,textposition是文字的位置,我这里提供了“左对齐”、“居中”、“右对齐”三种方式。

addArea(x,z,width,length,scene,name,textColor,font_size,textposition)
addArea(0,0,500,500,scene,"ID1$库区1号","FF0000",20,"左对齐");

最后我们需要在test.html中修改下init()方法:

// 初始化
 function init() {
   initMat();//初始化材质信息
   initScene();
   initCamera();
   initRenderer();
   initContent();
   initLight();
   initControls();

   addArea(0,0,500,500,scene,"ID1$库区1号","FF0000",20,"左对齐"); //添加库区

   //添加选中时的蒙版
   composer = new THREE.ThreeJs_Composer(renderer, scene, camera); 
   document.addEventListener('resize', onWindowResize, false);
 }

结束语

明天就是国庆节了,预祝大家国庆快乐!本章我们讲解了如何给门添加动画,以及如何添加库位。下一章我们将会推出如何添加货架和货物,敬请期待!
我跟广大学习ThreeJs的初学者一样,仍带着懵懂的心去探索这片新大陆,CSDN上的许多前辈都给了我很多关键的灵感和技术方法,如果大家有兴趣,也可以互相交流成长,欢迎大家指导咨询。PS:大家有兴趣可以点进去我的头像,陆陆续续也写了十来篇了。
链接:使用ThreeJs从零开始构建3D智能仓库——第一章: 点我跳转.
链接:使用ThreeJs从零开始构建3D智能仓库——第二章: 点我跳转.
链接:使用ThreeJs从零开始构建3D智能仓库——第三章: 点我跳转.
链接:使用ThreeJs从零开始构建3D智能仓库——第四章: 点我跳转.
链接:使用ThreeJs从零开始构建3D智能仓库——第五章: 点我跳转.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章