TypeScript進階開發——ThreeJs基礎實例,從入坑到入門,Demo實例記錄


  前言

  我們前面使用的是自己編寫的ts,以及自己手動引入的jquery,由於第三方庫采用的是直接引入js,沒有d.ts聲明文件,開發起來很累,所以一般情況下我們使用npm引入第三方的庫,本文記錄使用npm,typescript開發threejs3D項目,搭建基礎實例,為以后開發具體業務做准備

 

  項目結構

  

   依舊是熟悉的SpringBoot項目,不同以往的是使用了npm管理工具來下載依賴js庫,類似maven,同時為了解決typescript編譯后引入npm庫的路徑有問題,導致瀏覽器報錯的問題,我們采用的webpack打包工具來打包  PS:webpack依賴的文件真的是多,全都安裝完后,好幾百M

  下面簡單說一下如何初始化npm、webpack,以及下載jquery、three等js庫

 

  npm的使用

  初始化

  cmd先打開到項目的 threejs\src\main\resources\static 路徑,使用npm init命令,回答一系列問題(當然也可以全部按照默認值),初始化成npm項目

  得到node_modules目錄以及package.json文件

  當我們使用打包命令,會提示我們還缺少那些依賴,這時候我們按照提示去下載就可以了

  有一點要注意,package.json文件的name值不能用typescript,我們改成

  "name": "typescript-threejs",

  腳本命令

  "scripts": {
    "tsc": "tsc -w",//監控文件,有改動時實時編譯ts
    "build": "webpack",//打包
    "dev": "webpack -w"//監控文件,有改動時實時打包
  },

  webpack.config.js配置

const path = require('path');
module.exports = {
    entry : {
        main : './src/controller/Main.ts'
    },
    devtool : 'inline-source-map',
    mode : 'development',
    module : {
        rules : [ {
            test : /\.ts$/,
            use : 'ts-loader',
            exclude : /node_modules/
        } ]
    },
    resolve : {
        extensions : [ '.ts', '.js' ]
    },
    output : {
        filename : '[name].js',
        path : path.resolve(__dirname, './dist/')
    },
    plugins : [
    ],
    optimization: {
        splitChunks: {
            chunks: "all",
            minSize: 30000,
            minChunks: 1,
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            automaticNameDelimiter: '-',
            name: true,
            cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10
                },
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    }
};

 

 

  使用 npm install 命令就可以下載第三方插件

 

  下載jquery的聲明文件

  在node_modules目錄下面j就可以看到npm下載下來的庫

 

  如何引入

  使用typescript編譯成js,路徑不正確,瀏覽器報錯

 

 

  使用webpack編譯、打包成js,路徑正確

 

  threejs

  threejs,是一個JavaScript編寫的WebGL第三方庫。

  官網:https://threejs.org/

  官方文檔:https://threejs.org/docs/index.html#manual/zh/introduction/Creating-a-scene

  官方提供的各種例子:https://threejs.org/examples/

  官方GitHub:https://github.com/mrdoob/three.js

     網友克隆的官網,gitee國內鏡像,網速較快:http://break_egg.gitee.io/three.js/

  這里還有一個大神的博客,有比較豐富的例子可以參考:https://www.wjceo.com/

 

  通過查閱官網文檔、以及參考大量的例子進行學習,我們開始three.js之旅,采用的是npm引入的方式引入three

 

   路徑結構介紹

 

  渲染器有三個WebGLRenderer、CSS2DRenderer、CSS3DRenderer,后面這兩個是為了能夠使用CSS2DObject、CSS3DObject對象作為Label,注意,使用了多個渲染器后,我們的控制器要控制的是CSS3DRenderer.domElement,控制它可以同時控制到WebGLRenderer的對象

   

  同時,3D的渲染器DOM要加絕對定位,要不然DOM的東西顯示不出來(為了統一,2D的我也加了),然后webGL的canvas也加樣式,position: absolute;

   

  然后在初始化場景時,不停的渲染,注意,有一個地方不停的渲染就可以了,多了影響性能

   

  封裝原生發射射線的方式監聽對象的鼠標事件,有個地方要注意,射線只能檢測到Mesh對象,Group組對象是檢測不到了

 

  更新監聽事件方法:

    /**
     * 添加cSS3DRenderer.domElement監聽對象事件,利用原生射線原理,被射線檢測到自身節點或者子節點則觸發監聽事件
     */
    public addEventListener(listenerObj: THREE.Object3D, even: string, callback: (object: THREE.Object3D) => void): void {
        let thid = this;

        //把具體的事件添加到對象,然后再綁定到dom,這樣做的目的是為了方便后期移除
        listenerObj[even] = function (event) {
            //阻止冒泡
            event.preventDefault();

            //光線投射
            let raycaster = new THREE.Raycaster();
            let mouse = new THREE.Vector2();

            mouse.x = (event["clientX"] / thid.cSS3DRenderer.domElement.clientWidth) * 2 - 1;
            mouse.y = -(event["clientY"] / thid.cSS3DRenderer.domElement.clientHeight) * 2 + 1;

            raycaster.setFromCamera(mouse, thid.camera);
            // 需要被監聽的對象要存儲在intersectObjects中,對象本身就是一個group,所以不能直接檢測射線(三維世界中點擊事件需要檢測射線),
            // 其下children里面有許多mesh,才是要被檢測的目標。
            let intersects;
            if (listenerObj.type == "Mesh") {
                intersects = raycaster.intersectObjects([listenerObj], false);
            } else {
                intersects = raycaster.intersectObjects(listenerObj.children, true);
            }
            if (intersects.length > 0) {
                // 回調函數,返回被監聽對象本身
                if (callback) callback(listenerObj);
            }
        };

        //threejs原生事件監聽 mousedown
        this.cSS3DRenderer.domElement.addEventListener(even, listenerObj[even], false);
    }
    /**
     * 移除cSS3DRenderer.domElement監聽對象事件
     */
    public removeEventListener(listenerObj: THREE.Object3D, even: string,): void {
        this.cSS3DRenderer.domElement.removeEventListener(even, listenerObj[even]);
    }

 

   

 

  同時還封裝了一個動畫效果,按屏幕刷新率調用,每次調用++一定的值,每次回調函數返回,從0到1遞增,等於1的時候結束遞歸調用

 

   還有一個是鏡頭的巡檢

 

 

  其他地方就不一一介紹了,大家自己看代碼

 

  效果演示

   地球模仿的是:https://wa.qq.com/xplan/earth/index.html?_wv=1

  地球外部有一層漂浮的雲層(大氣層),效果比較逼真

 

 

  

  雲層模仿的是: http://www.sucai58.com/plus/demo.php?aid=132 

  雲海又八千多個PlaneGeometry對象組成,推動鏡頭營造穿越雲層的效果,作為地球場景到園區場景的過渡動畫

  園區是加載了官方例子的obj模型(站立的男人)以及fbx模型(跳舞的女人),跳舞的動畫是模型自帶的,中間那兩個是普通的BoxGeometry對象(錄GIF的軟件錄帶綠色的東西效果好難看啊,我就不放上來了...)

 

 

 

 

 

   更多效果自己運行查看

 

   補充

  1、npm install 包的時候報錯

  解決:給npm降級或者升級

  降級 : npm install -g npm@5.4.0  //@后面是具體版本號

  升級 : npm install -g npm //升級到最新版本

  如果還不行就清除緩存再次安裝

  npm cache clean -f

 

  

 2、threejs移動的時候老是報錯

  在three.module.js做一下小調整,非空才調用.call方法

 

  后記

  學習Three.js是因為公司的3D技術儲備從原先的Twaver轉用其他的庫,公司大佬在考察Unity3D跟Three.js后決定用后者,Three.js是開源免費的,而Twaver跟Unity3D是要收錢的,這個例子就是我的學習Demo,主要是參考了官網的例子以及效果演示中提到的那兩個列子,Demo例子大體上已經封裝實現了加載OBJ、FBX、原生對象、2D、3Dlabel等,封裝對象鼠標事件的監聽,鏡頭動畫封裝,基本上滿足業務的開發

  當然還有很多不足的地方,比如事件監聽是我們直接封裝的檢測射線方法,經過測試發現一個bug,我們已經把地球從場景中移除,但點擊地球的位置依舊能觸發地球的監聽事件

 

  TypeScript進階開發——ThreeJs基礎實例就暫時記錄到這里,以后在補充

 

  2019-09-05補充:

  1、解決事件綁定問題,原因:雖然我們已經將對象從場景中移除,但事件監聽還在,所以還是能夠觸發

 

   2、眼尖的同學可以發現了,我們之前的雲層過渡動畫卡頓、同時還有類似“馬賽克”的情況出現,卡頓是因為我們創建的雲對象太多了,而馬賽克是因為默認啟用了深度測試,我們關掉就可以解決

 

 

 

 

   我們關閉了深度測試、減少了一半的雲對象,最后看一下效果(流暢了很多~)

 

   

 

 

 

  代碼開源

  注:node_modules文件夾和里面的各種庫文件我就不提交了,幾百M太大了,大家按照上面的步驟用npm命令初始化、下載就可以了

 

  代碼已經開源、托管到我的GitHub、碼雲:

  GitHub:https://github.com/huanzi-qch/threejs

  碼雲:https://gitee.com/huanzi-qch/threejs

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM