(一) Three.js And TypeScript

1. 概述

本文主要介紹以下三個部分:

  • 配置開發(fā)環(huán)境(vs code, git and nodejs)
  • TypeScript快速入門
  • 初始化Three.js項目工程

本文代碼倉庫地址:https://github.com/ue007/three.ts

2. 配置開發(fā)環(huán)境

3. TypeScript快速入門

代碼地址:https://github.com/ue007/three.ts/tree/main/01-HelloTypeScript

3.1 TypeScript介紹

TypeScript 是 JavaScript 的一個超集,支持 ECMAScript 6 標(biāo)準(zhǔn)(ES6 教程)。

TypeScript 由微軟開發(fā)的自由和開源的編程語言。

TypeScript 設(shè)計目標(biāo)是開發(fā)大型應(yīng)用,它可以編譯成純 JavaScript,編譯出來的 JavaScript 可以運行在任何瀏覽器上。

3.1.1 JavaScript 與 TypeScript 的區(qū)別

TypeScript 是 JavaScript 的超集,擴展了 JavaScript 的語法,因此現(xiàn)有的 JavaScript 代碼可與 TypeScript 一起工作無需任何修改,TypeScript 通過類型注解提供編譯時的靜態(tài)類型檢查。

TypeScript 可處理已有的 JavaScript 代碼,并只對其中的 TypeScript 代碼進(jìn)行編譯。

[圖片上傳失敗...(image-45c071-1618983989118)]

[圖片上傳失敗...(image-2d3302-1618983989118)]

3.1.2 為什么選擇TypeScript?

開發(fā)者選擇使用TypeScript語言至少有以下幾點原因:

能夠更早地發(fā)現(xiàn)代碼中的錯誤。
能夠幫助提高生產(chǎn)力。
支持JavaScript語言的最新特性并且使用了與JavaScript語言相同的語法和語義。

3.2 安裝TypeScript

打開終端,全局安裝typescript:

npm install -g typescript

查看typescript版本

tsc -v

3.3 創(chuàng)建foo.js文件

代碼地址:https://github.com/ue007/three.ts/01-HelloThree

創(chuàng)建foo.js文件,并輸入代碼:

function foo(bar) {
    return "Hello, " + bar;
}

let baz = "ThreeJs With TypeScript";

console.log(foo(baz));

直接在Node環(huán)境下執(zhí)行,在控制臺輸入:

node foo.js

輸出內(nèi)容:

Hello, ThreeJs With TypeScript

3.4 創(chuàng)建foo.ts文件

下面使用ts方式,等效輸出foo.js文件。

[圖片上傳失敗...(image-d9e811-1618983989118)]

首先,將foo.js文件重命名為foo.ts。

其次,在控制臺,輸入如下命令:

tsc foo.ts

編譯完成之后,會對應(yīng)生成foo.js文件,并在node環(huán)境下執(zhí)行命令:

node foo.js

同樣輸出如下結(jié)果:

Hello, ThreeJs With TypeScript

3.5 Interfaces介紹

在TypeScript中,接口(Interfaces)和類型聲明(Type Declarations)提供了幾乎完全相同的功能。接口/類型是用于類型檢查的結(jié)構(gòu)。接口/類型定義了對象可以擁有的屬性和類型。

替換foo.ts文件中代碼如下:

interface Quux {
  quuz: string;
  corge: number;
}

function foo(bar: Quux) {
  return 'Hello, ' + bar.quuz + ' ' + bar.corge;
}

let baz: Quux = {
  quuz: 'ABC',
  corge: 123,
};

console.log(foo(baz));
 

執(zhí)行命令:

tsc foo.ts
node foo.js

在Node環(huán)境中執(zhí)行結(jié)果:

Hello, ABC 123

3.6 Classes介紹

類(Classes),本質(zhì)上是對象在實現(xiàn)時應(yīng)該是什么樣的藍(lán)圖。一個類可以有初始化的屬性和方法來幫助創(chuàng)建和修改對象。

定義一個Grault類,代碼如下:

class Grault {
  private garply: string;

  constructor(quux: Quux, waldo: number[]) {
    this.garply = quux.quuz + ' ' + quux.corge + ' ' + waldo;
  }

  public getGarply() {
    return this.garply;
  }
}

interface Quux {
  quuz: string;
  corge: number;
}

let baz = { quuz: 'ABC', corge: 123 };

let fred: Grault = new Grault(baz, [1, 2, 3]);

console.log(fred.getGarply());

執(zhí)行命令:

tsc foo.ts
node foo.js

在Node環(huán)境中執(zhí)行結(jié)果:

ABC 123 1,2,3

3.7 在瀏覽器中運行

創(chuàng)建foo.html文件,并寫入如下代碼:

<!DOCTYPE html>
<html>

<head>
    <title>TypeScript Crash Course</title>
</head>

<body>
    <script src="foo.js"></script>
</body>

</html>

在foo.ts文件中添加如下代碼:

class Grault {
  private garply: string;

  constructor(quux: Quux, waldo: number[]) {
    this.garply = quux.quuz + ' ' + quux.corge + ' ' + waldo;
  }

  public getGarply() {
    return this.garply;
  }
}

interface Quux {
  quuz: string;
  corge: number;
}

let baz = { quuz: 'ABC', corge: 123 };

let fred: Grault = new Grault(baz, [1, 2, 3]);

console.log(fred.getGarply());

try {
  document.body.innerHTML = fred.getGarply();
} catch (e) {}

使用vscode編輯器打開Live Server服務(wù)器,在瀏覽器中查看foo.html頁面,效果如下:

[圖片上傳失敗...(image-a27854-1618983989118)]

4. 初始化Three.js項目

接下來,我們將創(chuàng)建Three.js項目模板。代碼地址:https://github.com/ue007/three.ts/tree/main/02-HelloThreeTS

4.1 創(chuàng)建工程目錄

mkdir 02-HelloThreeTS

4.2 初始化工程

使用npm進(jìn)行初始化

npm init

一直回車,直至初始化完成,在目錄下會生成package.json文件。

4.3 安裝Three.js依賴庫

執(zhí)行命令:

cnpm install @types/three --save-dev // 具有類型生命的three版本

4.4 創(chuàng)建目錄結(jié)構(gòu)

按照如下目錄結(jié)構(gòu),創(chuàng)建文件和目錄:

|-- Three.js-TypeScript-Tutorial
    |-- dist
        |-- client
            |-- index.html
        |-- server
    |-- node_modules
        |-- three
            |-- (Several extra files and folders containing the Three.js source code)
    |-- src
        |-- client
        |-- server
    |-- package.json
    |-- package-lock.json

其中dist/client/index.html文件內(nèi)容如下:

<!DOCTYPE html>
<html>

<head>
    <title>Three.js TypeScript Tutorials</title>
</head>

<body>
    <script type="module" src="client.js"></script>
</body>

</html>

4.5 添加初始化代碼

4.5.1 client.ts

在src/client.ts文件中,添加如下代碼:

const scene: THREE.Scene = new THREE.Scene();

const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const geometry: THREE.BoxGeometry = new THREE.BoxGeometry();
const material: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({
  color: 0x00ff00,
  wireframe: true,
});

const cube: THREE.Mesh = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 2;

var animate = function () {
  requestAnimationFrame(animate);

  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  renderer.render(scene, camera);
};

animate();

在src/client文件夾中,創(chuàng)建tsconfig.json文件,并插入如下代碼:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "ES6",
        "outDir": "../../dist/client",
        "moduleResolution": "node"
    },
    "include": [
        "**/*.ts"
    ]
}

4.5.2 server.ts

在src/server目錄下,創(chuàng)建server.ts文件,并插入如下代碼:

const port: number = 3000

class App {
    private server: http.Server
    private port: number

    constructor(port: number) {
        this.port = port
        const app = express()
        app.use(express.static(path.join(__dirname, '../client')))

        this.server = new http.Server(app);
    }

    public Start() {
        this.server.listen(this.port, () => {
            console.log( `Server listening on port ${this.port}.` )
        })
    }
}

new App(port).Start()

在src/server文件夾中,創(chuàng)建tsconfig.json文件,并插入如下代碼:

{
    "compilerOptions": {
        "target": "ES2019",
        "module": "commonjs",
        "outDir": "../../dist/server",
        "sourceMap": true,
        "esModuleInterop": true
    },
    "include": [
        "**/*.ts"
    ]
}

4.5.3 目錄結(jié)構(gòu)

創(chuàng)建完成之后的目錄結(jié)構(gòu)如下:

|-- Three.js-TypeScript-Tutorial
    |-- dist
        |-- client
            |-- index.html
        |-- server
    |-- node_modules
        |-- three
            |-- (Several extra files and folders containing the Three.js source code)
    |-- src
        |-- client
            |-- client.ts
            |-- tsconfig.json
        |-- server
            |-- server.ts
            |-- tsconfig.json
    |-- package.json
    |-- package-lock.json

4.6 引入依賴

上面代碼,我們會發(fā)現(xiàn),在編輯器中會提示錯誤,如不能找到對應(yīng)的namespace等等,這是因為還沒有引入對應(yīng)的依賴。

4.6.1 client side

創(chuàng)建client.ts文件,代碼如下:

import * as THREE from '/build/three.module.js'
import { OrbitControls } from '/jsm/controls/OrbitControls'

const scene: THREE.Scene = new THREE.Scene()

const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

const controls = new OrbitControls(camera, renderer.domElement)

const geometry: THREE.BoxGeometry = new THREE.BoxGeometry()
const material: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true })

const cube: THREE.Mesh = new THREE.Mesh(geometry, material)
scene.add(cube)

camera.position.z = 2

var animate = function () {

    requestAnimationFrame(animate)

    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    controls.update()

    renderer.render(scene, camera)

}; 

animate(); 

創(chuàng)建tsconfig.json文件,代碼如下:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "ES6",
        "outDir": "../../dist/client",
        "baseUrl": ".",
        "paths": {
            "/build/three.module.js": ["../../node_modules/@types/three"],
            "/jsm/*": ["../../node_modules/@types/three/examples/jsm/*"],
        },
        "moduleResolution": "node"
    },
    "include": [
        "**/*.ts"
    ]
}

執(zhí)行編譯腳本:

tsc -p .\src\client\

4.6.2 server side

在server.ts文件開頭,引入如下代碼:

import express from "express"
import path from "path"
import http from "http"

安裝依賴:

cnpm install @types/node --save-dev
cnpm install @types/express --save-dev
cnpm install express --save-dev

完整代碼如下:

import express from "express"
import path from "path"
import http from "http"

const port: number = 3000

class App {
    private server: http.Server
    private port: number

    constructor(port: number) {
        this.port = port
        const app = express()
        app.use(express.static(path.join(__dirname, '../client')))
        app.use('/build/three.module.js', express.static(path.join(__dirname, '../../node_modules/three/build/three.module.js')))
        app.use('/jsm/controls/OrbitControls', express.static(path.join(__dirname, '../../node_modules/three/examples/jsm/controls/OrbitControls.js')))

        this.server = new http.Server(app);
    }

    public Start() {
        this.server.listen(this.port, () => {
            console.log( `Server listening on port ${this.port}.` )
        })
    }
}

new App(port).Start()

編譯server.ts文件,命令如下:

tsc -p ./src/server

對應(yīng)會在dist/server目錄下,生成server.js文件和server.js.map文件。

執(zhí)行腳本,啟動服務(wù)器:

node .\dist\server\server.js 

在瀏覽器中,打開地址:localhost:3000

img

4.7 配置TSC Watch

繼續(xù)配置項目,使得源代碼在發(fā)生任何更改的時候,重新編譯, 添加-w表示watch狀態(tài)。

tsc -p src/server/ -w 

4.8 配置Nodemon

nodemon nodemon是一種工具,可以自動檢測到目錄中的文件更改時通過重新啟動應(yīng)用程序來調(diào)試基于node.js的應(yīng)用程序。

安裝nodemon:

npm install --save-dev nodemon

啟動服務(wù):

npx nodemon dist/server/server.js

4.9 一鍵啟動

我們可以創(chuàng)建一個命令來同時啟動兩個進(jìn)程,而不是一直輸入這些compile和nodemon命令。

安裝concurrently:

npm install --save-dev concurrently

在package.json文件中添加腳本:

"dev" : "concurrently -k \"tsc -p ./src/server -w\" \"nodemon ./dist/server/server.js\"",

執(zhí)行命令:

npm run dev

打開瀏覽器,輸入地址:localhost:3000,效果如下:

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 當(dāng)使用第三方庫時,我們需要引用它的聲明文件,才能獲得對應(yīng)的代碼補全、接口提示等功能。這是因為前端第三方庫大多都是非...
    CondorHero閱讀 5,129評論 1 5
  • THREE.js 是javascript的一個三維庫,Github網(wǎng)址https://github.com/mrd...
    圣_狒司機閱讀 2,296評論 0 1
  • 1. HTML 1. 必考:你是如何理解 HTML 語義化的? 荒野階段:最開始是 PHP 后端寫 HTML,不會...
    Qingelin閱讀 758評論 0 0
  • Three.js是一個偉大的開源WebGL庫,WebGL允許JavaScript操作GPU,在瀏覽器端實現(xiàn)真正意義...
    無言以越閱讀 3,093評論 3 19
  • 這一章主要總結(jié)TypeScript的用法和項目常用配置 編譯上下文 用來給文件分組,告訴 TypeScript 哪...
    Terryzh閱讀 2,134評論 0 0

友情鏈接更多精彩內(nèi)容