使用typescript构建three.js项目

版权声明:本文为作者的原创文章,未经允许不得转载。 https://blog.csdn.net/lin5165352/article/details/88555054

使用typescript构建three.js项目

1.初始化一个npm项目

新建一个文件夹,打开控制台输入npm初始化命令,然后一路enter,最后Y一下。文件夹中就多了一个package.json的配置文件。

npm init

2.安装webpack

参考这个文章,里面配置和插件都可以直接用webpack入门使用教程
分别安装了:webpack ,webpack-cli 以及html-webpack-plugin ,webpack-dev-server。

"devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "ts-loader": "^5.3.3",
    "typescript": "^3.3.3333",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.2.1"
  }

3.安装typescript

https://www.tslang.cn/docs/handbook/tsconfig-json.html

需要安装ts-loader和typescript。还有一个配置文件夹,可以用命令自动生成一个,默认的就要行。
tsc --init 初始化一个tsconfig.json
关于配置问题可以参考这篇文章:tsconfig.json配置说明

4.安装three和@types/three

three和@types/three是必须安装的。
npm install --save three
npm install --save-dev @types/three

5.一个简单的three场景

three开发的基本套路如下:

  1. 引入three库文件
  2. 创建scene、camera、renderer。
  3. 配置camera、renderer。
  4. 设置render和animate。
  5. 把渲染结果添加到body中。

下面就演示一个这个基本套路,为了证明程序运行正确,在场景中添加了一个AxesHelper。
下面的代码中有两个地方因为this指向问题,采用了箭头函数。在函数中引用了自身,会存在作用域问题。可以对比一下编译后的代码,发现普通的函数是写在原型prototype中,而箭头函数则直接当成属性写在函数本身上。
项目从js转到ts,这个作用域问题非常的常见。简单的处理方式就是用箭头函数代替function

animate = ()=>{
requestAnimationFrame(this.animate)
}

scene.ts

//源代码
import * as THREE from "three"
export default class Threescene{
    scene:THREE.Scene
    camera:THREE.PerspectiveCamera
    renderer:THREE.WebGLRenderer
    constructor(){
        this.scene = new THREE.Scene()
        this.camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,2000)
        this.renderer = new THREE.WebGLRenderer()
        this.init()
        window.addEventListener('resize',this.onWindowResize,false)
    }
    private init(){
        this.camera.position.set(-40,40,40)
        this.camera.lookAt(this.scene.position)
        this.renderer.setClearColor(0x222222)
        this.renderer.setSize(window.innerWidth,window.innerHeight)
        document.body.appendChild( this.renderer.domElement );
        this.scene.add(new THREE.AxesHelper(10))       
        this.animate()
    }
    private onWindowResize = ()=>{
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize( window.innerWidth, window.innerHeight );       
    }
    private render(){
        this.renderer.render(this.scene,this.camera)
    }
    private animate = ()=>{
        requestAnimationFrame(this.animate)
        this.render()
    }
}

//编译后部分代码
var Threescene = /** @class */ (function () {
    function Threescene() {
        var _this = this;
        this.onWindowResize = function () {
            _this.camera.aspect = window.innerWidth / window.innerHeight;
            _this.camera.updateProjectionMatrix();
            _this.renderer.setSize(window.innerWidth, window.innerHeight);
        };
        this.animate = function () {
            requestAnimationFrame(_this.animate);
            _this.render();
        };
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
        this.renderer = new THREE.WebGLRenderer();
        this.init();
        window.addEventListener('resize', this.onWindowResize, false);
    }
    Threescene.prototype.init = function () {
        this.camera.position.set(-40, 40, 40);
        this.camera.lookAt(this.scene.position);
        this.renderer.setClearColor(0x222222);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(this.renderer.domElement);
        this.scene.add(new THREE.AxesHelper(10));
        this.animate();
    };
    Threescene.prototype.render = function () {
        this.renderer.render(this.scene, this.camera);
    };
    return Threescene;
}());

index.ts

import ThreeScee from "./util/scene"
import "./assets/css/index.css"

new ThreeScee()

程序运行后会在场景中显示一个AxesHelper。
在这里插入图片描述

6.添加orbitcontrols相机控制器

npm install --save three-orbitcontrols
这个坑真多,坑的我无语了。 three-orbitcontrols没有@type文件,官方也不出,而且也不在核心three库中,不知道官方几个意思。
安装了three-orbitcontrols后,去看看他的源码,发现采用的是module.export,而不是export,所以出现了问题。这个需要require进来的,是commonjs的方式吧,export是es6的方式,不统一。说白了就是three-orbitcontrols不是three.js亲生的吧。
module.exports = exports.default = THREE.OrbitControls;
在这里插入图片描述这样引入:import * as OrbitControls from “three-orbitcontrols” 或者 import OrbitControls from "three-orbitcontrols"会提示无法找到模块“three-orbitcontrols”的声明文件。
可以新建个.d.ts文件来屏蔽这个警告:declare module ‘three-orbitcontrols’
*** as** 要不要加?我不知道,有的时候加了报错,有的时候不加报错,我无语了。
还有同样的配置,一个项目只能any,不加as,一个加不加都行,还可以用THREE.OrbitControls的类型。(没排查去原因)
controls: any
controls: THREE.OrbitControls

还有一种简单的处理方式,自己改造一下orbitcontrols.js文件,变成inport和export的形式,作为资源文件引入进来。
这个坑不准备继续踩了,估计不久就会统一修复的。

7.添加项目中引入css和图片

css 需要"css-loader",“style-loader”,分别安装一下。配置项也需要修改一下。
在这里插入图片描述
之后我们就可以使用import "./assets/css/index.css"来引入css文件了。给body加个样式来屏蔽滚动条。

body {			
margin: 0px;
overflow: hidden;

}

8.添加图片和其他资源

图片资源有两种处理方式,一直是打包到js文件中,一直是拷贝到指定目录中。
webpack打包图片需要url-loader,

{
    test: /\.(png|jpg)$/,
    loader: 'url-loader?limit=819200&name=images/[hash:8].[name].[ext]' 
}

拷贝文件可以使用copy-webpack-plugin插件。
参考文章:https://blog.csdn.net/lin5165352/article/details/85267088
场景中使用的三维模型,比如obj,fbx,glft等,也可以使用这个拷贝插件拷贝过去,方便使用。
当然你也可以不安装这个插件,自己手动拷贝过去,这样你在使用webpack-dev-server开发的时候才会找到资源。

9.其他配置问题

9.1 安装tween.js

这个函数库是用来做动画用的,使用频率非常高。
记得安装的名称是@tweenjs/tween.js,而不是tween.js。
@tweenjs/tween.js --npm i @tweenjs/tween.js

10.项目GitHub地址

https://github.com/scqilin/three.js-typescript

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lin5165352/article/details/88555054