前言

  我们前面使用的是自己编写的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

  这里还有一个大神的博客,有比较丰富的例子可以参考: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

TypeScript进阶开发——ThreeJs基础实例,从入坑到入门的更多相关文章

  1. cozmo 入坑日记及开发环境搭建

    前几日,朋友在群里发了一个机器人的小视频,视频里机器人可以对话,可以推箱子,开心以后会哈哈大笑,非常有趣. 详细了解里一下,这是个叫 cozmo 的智能机器人,可以配合 SDK 用 python 编程 ...

  2. [Abp vNext 入坑分享] - 前言

    一·背景 Abp vnext是 ABP 框架作者所发起一个完全基于 ASP .NET Core框架,截至2020年4月份已经升级到2.5.0版本,根据经验2.0版本以后可以放心的使用在生产环境.类似a ...

  3. 基于Nodejs生态圈的TypeScript+React开发入门教程

    基于Nodejs生态圈的TypeScript+React开发入门教程   概述 本教程旨在为基于Nodejs npm生态圈的前端程序开发提供入门讲解. Nodejs是什么 Nodejs是一个高性能Ja ...

  4. Python进阶:函数式编程实例(附代码)

    Python进阶:函数式编程实例(附代码) 上篇文章"几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏"中用到了一些列表解析.生成器.map.filter.lam ...

  5. oracle入坑日记<二>认识oracle(含sqlplus基础使用)

    1.SID(数据库实例) 1.1. oracle安装的时候有一项叫[全局数据库名]的填写项,这个就是oracle的SID也是数据库的唯一标识符: 1.2.一个oracle数据库有且只有一个SID(一般 ...

  6. Web开发——HTML基础

    文档资料参考: 参考:MDN官网 参考:http://www.runoob.com,W3School 参考:https://developer.mozilla.org/zh-CN/docs/Learn ...

  7. python进阶08 MySQL基础补充

    python进阶08 MySQL基础补充 本次课程都是基于三张表格的使用 一.子查询 #如何找到‘张三’的成绩 #思路:先找到张三的学号,在拿这个张三的学号到成绩表里面去匹配,得出成绩 #如何用一条查 ...

  8. C#基础知识1-深入理解值类型和引用类型

    C#值类型和引用类型这个概念在刚学习的时候应该就知道了.但是我们并没有深入的去理解它.越是基础知识其实才是最有用的.对代码的优化,代码质量的提升都有帮助.通过整理本文章,对很多知识也起到了巩固的作用吧 ...

  9. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

随机推荐

  1. 恢复在iterm2中当滚动光标时候触发滚动历史记录的问题

    在Iterm2中,如果你上下滚动光标(上下滑动触摸板.或者滚动鼠标滚轮),通常情况下是触发了屏幕内容上下滚动. 但是在某些异常情况下,却触发了命令行历史记录的上下滚动,效果和你连续按了多次键盘的上下键 ...

  2. Java oop 多态

      1.多态指对象的多种形态:引用多态与方法多态   注意: A:继承是多态的实现基础 B:方法重写也是多态的体现   2.引用多态 A:父类的引用可以指向本类的对象:父类 对象名 = new 父类( ...

  3. springBoot综合开发

    作者:纯洁的微笑出处:www.ityouknow.com 版权所有,欢迎保留原文链接进行转载:) 上篇文章介绍了Spring boot初级教程:spring boot(一):入门篇,方便大家快速入门. ...

  4. 【Java】Map

    今天用到了键-值对,于是想起了 Java 的 Map,由于之前并不很熟悉,就看了下源码,如下: /* * Copyright (c) 1997, 2006, Oracle and/or its aff ...

  5. Java代码计算运行时间

    突然想准确的测试一下Java代码的执行时间,在网上找了一会.发现基本有以下两种方法:第一种是以毫秒为单位计算的. Java代码 //伪代码 long startTime=System.currentT ...

  6. git的使用(一)

    git   —version  展示git的版本 tanya ~$ git --version git version 2.22.0 最小配置   git config —global user.na ...

  7. SpringMVC学习笔记之---深入使用

    SpringMVC深入使用 (一)基于XML配置的使用 (1)配置 1.SpringMVC基础配置 2.XML配置Controller,HandlerMapping组件映射 3.XML配置ViewRe ...

  8. Java:控制反转(IoC)与依赖注入(DI)

    很长一段时间里,我对控制反转和依赖注入这两个概念很模糊,闭上眼睛想一想,总有一种眩晕的感觉.但为了成为一名优秀的 Java 工程师,我花了一周的时间,彻底把它们搞清楚了. 01.紧耦合 在我们编码的过 ...

  9. java实现发短信功能---腾讯云短信

    目录 java实现发短信功能 前言 开发环境 腾讯云 ---短信 代码 效果 结束语 java实现发短信功能 前言 如今发短信功能已经成为互联网公司的标配,本篇文章将一步步实现java发送短信 考察了 ...

  10. Eclipse+CXF框架开发Web服务实战

    一. 说明 采用CXF框架开发webservice. 所用软件及版本如下.  操作系统:Window XP SP3.  JDK:JDK1.6.0_07,http://www.oracle.com/ ...