使用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智能倉庫——第五章: 點我跳轉.

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