ThreeJS从创建场景到使用功能实例详解

目录
  • 前言
  • 创建场景以及相机
    • 创建一个平面
    • 添加图片
    • 创建线
    • 添加轴线
    • 缩放、定位、以及旋转
    • 添加文字
    • 正交摄像机和透视摄像机的区别
  • 总结

前言

最近公司要做一个2.5D插件,然后自己学旋转角度不太好,然后就使用了THREEJS, 用起来还是比较繁琐的,整体支持不太好,整体都是自己研究,看到写的不好地方勿怪

创建场景以及相机

首先,要创建一个场景,以及一个相机(相机分为透视相机和正交摄像机,区别在后面会解释),代码如下

export default class ThreeComponent extends React.Component<any, any> {
  private mount: any
  private camera: any
  private scene: any
  private renderer: any

  componentDidMount() {
    this.init()
    this.renders()
  }

  init = () => {
    // 相机
    this.camera = new THREE.PerspectiveCamera(30, this.mount.clientWidth / this.mount.clientHeight, 1, 2500)
    this.camera.position.set(500, 800, 1300)
    this.camera.lookAt(30, 0, 0)
    // 场景
    this.scene = new THREE.Scene()
    this.scene.background = new THREE.Color(0x000000)

    this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
    this.renderer.setClearColor(0xEEEEEE, 0.0)
    this.renderer.setPixelRatio(window.devicePixelRatio)
    this.renderer.setSize(this.mount.clientWidth, this.mount.clientHeight)
    this.mount.appendChild(this.renderer.domElement)
    window.addEventListener('resize', () => this.onWindowResize.bind(this))
  }

  onWindowResize = () => {
    this.camera.aspect = this.mount.clientWidth / this.mount.clientHeight
    this.camera.updateProjectionMatrix()

    this.renderer.setSize(this.mount.clientWidth, this.mount.clientHeight)

    this.renders()
  }

  renders = () => {
    this.renderer.render(this.scene, this.camera)
  }

  render() {
    return (
      <div id='canvas'
           style={{ width: '100%', height: '100%' }}
           ref={(mount) => {
             this.mount = mount
           }}/>
    )
  }
}

创建一个平面

相机和平面创建完成,接来下我这边是直接创建一个平面放到场景中,代码如下

    const geometry = new THREE.PlaneGeometry(800, 400)
    // 设置透明以及颜色
    const material = new THREE.MeshBasicMaterial({ color: 0x091A20, transparent: true, opacity: 0.8 })
    const plane = new THREE.Mesh(geometry, material)
    // 这边操作的是旋转还是位置
    plane.rotation.x = 300.1
    plane.rotation.y = 0
    plane.rotation.z = 49.8
    plane.rotation.y = 0
    plane.position.x = 120
    plane.position.y = 200
    this.scene.add(plane)

添加图片

    const image = require('../../assets/images/test.png').default
    // 因为添加图片加载是异步的,所以在load方法中操作,每次加载之后都要执行一遍renders方法,重新渲染场景
    new THREE.TextureLoader().load(image, (texture) => {
      // 设置透明度,以及基础材质的map
      const mat = new THREE.MeshBasicMaterial({ map: texture, transparent: true })
      const geom = new THREE.BoxGeometry(100, 100)
      const mesh = new THREE.Mesh(geom, mat)
      mesh.receiveShadow = true
      mesh.rotation.z = 19.7
      mesh.position.x = 0
      mesh.position.y = -30
      // 往plane平面中添加,这样就可以直接放到plane中,位置就是plane的位置
      plane.add(mesh)
      this.renders()
    })

创建线

首先要说,因为正常ThreeJs的line不能设置线宽,所以要用到的MeshLine,github地址为: MeshLine

// 这里引入MeshLine
import { MeshLine, MeshLineMaterial, MeshLineRaycast } from 'three.meshline'

      const mat = new THREE.MeshBasicMaterial({ map: texture1, transparent: true })
      const boxGeom = new THREE.BoxGeometry(60, 150)
      const mesh = new THREE.Mesh(boxGeom, mat)
      const mat1 = new THREE.MeshBasicMaterial({ map: texture2, transparent: true })
      const boxGeom1 = new THREE.BoxGeometry(60, 150)
      const mesh1 = new THREE.Mesh(boxGeom1, mat1)
      const point = []
      point.push(mesh.position) // mesh的位置
      point.push(mesh1.position)  // mesh1的位置
      // 点对点的线
      const line = new MeshLine()
      line.setPoints(point)
      const lineMaterial = new MeshLineMaterial({
        color: new THREE.Color(0xffffff),
        lineWidth: 10,
        transparent: true,
        opacity: 0.5
      })
      // 添加线
      const lineMesh = new THREE.Mesh(line.geometry, lineMaterial)
      plane.add(mesh)
      plane.add(mesh1)
      plane.add(lineMesh)
      // 更新完之后在执行一遍render,把东西渲染到画布中
      this.renders()

添加轴线

    const axesHelper = new THREE.AxesHelper(800)
    this.scene.add(axesHelper)

缩放、定位、以及旋转

    // 缩放功能对应mesh进行缩放,每个mesh添加后都有固定的position, rotation, scale 属性
    mesh.position.set(x, y, z)
    mesh.rotation.set(x, y, z)
    mesh.scale.set(x, y, z)
    // 也可以这样, scale, rotation 都可以这么设置
    mesh.position.x = 0
    mesh.position.y = 0
    mesh.position.z = 0

添加文字

添加文字使用threeJS官方的添加文字需要导入json文件,而且还需要中文配置,所以使用起来占用内存会比较大,所以当前项目中使用的是Canvas导入文字图片

    //创建canvas
    const canvas = document.getElementById('text-canvas') as HTMLCanvasElement
    const ctx = canvas?.getContext('2d') as any
    canvas.width = 100
    canvas.height = 100
    ctx.fillStyle = 'transparent'
    ctx.fillRect(0, 0, 100, 100)
    ctx.fillStyle = '#FFFFFF'
    ctx.font = `normal ${attr.fontSize ?? 14}px "楷体"`
    ctx.fillText(text.length > 5 ? text.substr(0, 5) + '...' : text, 0, 40)
    // 导出图片路径
    const url = canvas.toDataURL('image/png')
    // 设置图片位置等信息
    new THREE.TextureLoader().load(url, (texture: any) => {
      const textGeom = new THREE.PlaneGeometry(200, 200)
      const mat1 = new THREE.MeshBasicMaterial({
        map: texture,
        transparent: true
      })
      const mesh1 = new THREE.Mesh(textGeom, mat1)
      mesh1.position.set(attr.x, attr.y, attr.z)
      if (attr.rotation !== undefined) {
        mesh1.rotation.set(attr.rotation.x, attr.rotation.y, attr.rotation.z)
      }
      mesh1.scale.set(0.8, 0.8, 0.8)
      if (attr.group !== undefined) {
        attr.group.add(mesh1)
        plane.add(attr.group)
      } else {
        plane.add(mesh1)
      }
      this.renders()
    })

正交摄像机和透视摄像机的区别

这边画图的话我就不画了,这块只是稍微的解释一下,具体的可以看一下搜到的文章:正交相机的应用

简单来说

  • 正交摄像机的特点就是:场景中远处的物体和近处的物体是一样大的
  • 透视摄像机的特点就是:场景中物体遵循近大远小的摆列,如果物体在最近,物体相对就会比较大

下面就是怎么使用这两个相机:

    // 透视摄像机
    this.camera = new THREE.PerspectiveCamera(30, this.mount.clientWidth / this.mount.clientHeight, 1, 2500)

    // 正交摄像机
    this.camera = new THREE.OrthographicCamera(width / -4, width / 4, height / 4, height / -4, -100, 10000)

透视摄像机PerspectiveCamera属性介绍(以下都是个人理解,如果有不清楚的欢迎指出):

  • fov 摄像机视锥体垂直视野角度 (就是从摄像机看视角的角度有多大)
  • aspect 摄像机视锥体长宽比 (通常就是你整个场景的长宽比)
  • near 摄像机视锥体近端面 (就是摄像机最近看到的距离)
  • far 摄像机视锥体远端面 (摄像机最远看到的距离,和near组合起来就相当于你摄像机从某个位置到某个位置的整体能看到的一个面)

正交摄像机OrthographicCamera属性介绍:

  • left 摄像机视锥体左侧面。
  • right 摄像机视锥体右侧面。
  • top 摄像机视锥体上侧面。
  • bottom 摄像机视锥体下侧面。
  • 上面四个属性推荐配置为场景的长款比,如代码所示(使这个等式成立: | left / right | = 1,| top / buttom | = 1),如果不成立,可能看到的效果不太一样
  • near
  • far
  • 以上两个属性通透视摄像机原理

角度计算:

如果设计刚好给你出了一个图,表示3d的位置等,这块需要一个角度计算,就需要改动摄像机的位置,以及lookAt属性:

    this.camera.position.set(x, y, z)
    this.camera.lookAt(x, y, z)

这个属性的设置需要自己设置(目前算法还不太了解,之后可能了解了会更新一下),把自己想象成一个摄像机,摆在哪里看到的效果都是不一样的,然后lookAt就是你眼睛看哪个位置,可以看的偏移一点这样的效果

总结

到此这篇关于ThreeJS从创建场景到使用功能的文章就介绍到这了,更多相关ThreeJS创建场景到使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue页面引入three.js实现3d动画场景操作

    vue中安装Three.js 近来无聊顺便研究一些关于3D图形化库.three.js是JavaScript编写的WebGL第三方库.Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它通过控制相机.视角.材质等相关属性来创造大量3D动画场景. 我们开始引入three.js相关插件. 1.首先利用淘宝镜像,操作命令为: cnpm install three 2.接下来利用npm安装轨道控件插件: 关注我的微信公众号[前端基础教程从0开始],加我微信,可以免费为您解答问题.回复"1&qu

  • Three.js基础学习之场景对象

    前言 本文主要给大家介绍了关于Three.js场景对象的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 通过这一段时间的学习,发现还没有介绍过场景的基本组件.这一节就简单的介绍一下相关的内容: 如果我们想让物体显示出来,首先,我们需要有一个渲染器(new THREE.WebGLRenderer() )来渲染模型和相机. 渲染的模型需要放到场景(THREE.Scene() )对象中,场景对象就是专门放置模型等一系列组件的地方,必须有一个模型和一个光源才可以显示出来模型.

  • three.js中文文档学习之创建场景

    什么是Three.js? 如果你正在读这篇文章,你可能对Three.js有一定的了解,那我们来简单地介绍下Three.js是什么. Three.js是一个库,使得WebGL的3D效果在浏览器中运用很容易.而在原始的WebGL中一个简单的立方体会变成数百Javascript和着色器代码的行,而一个Three.js只需要一点点代码. 本节目标是为 three.js 做简介.我们从使用旋转立方体来搭建场景开始.如果遇到困难需要帮助,页面底部有可参考的源码. 一个场景至少需要的三种类型组件 相机/决定哪

  • Three.JS实现三维场景

    最近在看一些Web3D的内容,觉得如果用纯openGLes写一个简单的3D场景太难了:不过还好,有很多现成的库可以使用. (个人感觉):我知道的经常的是Three.JS和SceneJS.感觉Three.JS资料比较多,貌似好学一些吧:另一个是ScenenJS,感觉官方介绍比较好,适合做一些工程和医学上的模拟,实时性比较好,但是中文资料感觉比较少,不太好学习.我个人看的是Three.JS 学习中用到的一些工具和库:学习中用到一些库,也费了不少时间去整理,下载: 用到的工具:WebStorm,个人感

  • three.js搭建室内场景教程

    公司做商城.消防.用电等项目,需要实现楼层和设备的可视化,以前都是使用其他建模工具创建的整体模型,再使用three.js的加载器加载到场景中,但是这样的加载存在缺陷,比如不能给模型的元素赋属性.不能单个点击元素.渲染单调等.所以本次参考了一些资料,不使用模型倒入,完全使用three.js搭建场景,代码有些粗燥勿怪. 1.创建地板 地板是一个类似盒子,有顶部有底部有侧面,但是不一定是规则的盒子,因此我放弃了常用的BoxGeometry的方式,改用顶点+面的形式创建任意多边形地板,已知多边形底部坐标

  • ThreeJS从创建场景到使用功能实例详解

    目录 前言 创建场景以及相机 创建一个平面 添加图片 创建线 添加轴线 缩放.定位.以及旋转 添加文字 正交摄像机和透视摄像机的区别 总结 前言 最近公司要做一个2.5D插件,然后自己学旋转角度不太好,然后就使用了THREEJS, 用起来还是比较繁琐的,整体支持不太好,整体都是自己研究,看到写的不好地方勿怪 创建场景以及相机 首先,要创建一个场景,以及一个相机(相机分为透视相机和正交摄像机,区别在后面会解释),代码如下 export default class ThreeComponent ex

  • Go开发Gin项目添加jwt功能实例详解

    目录 啥是JWT 为什么要用在你的Gin中使用JWT JWT的基本原理 JWT TOKEN怎么组成 Header Base64URL Payload Signature 解密过程 一些特点(优点和缺点) GIN整合JWT 编写jwtutil GenToken方法 ParseToken方法 编写中间件 使用中间件 测试 其他 啥是JWT JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场

  • FasfDFS整合Java实现文件上传下载功能实例详解

    在上篇文章给大家介绍了FastDFS安装和配置整合Nginx-1.13.3的方法,大家可以点击查看下. 今天使用Java代码实现文件的上传和下载.对此作者提供了Java API支持,下载fastdfs-client-java将源码添加到项目中.或者在Maven项目pom.xml文件中添加依赖 <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</arti

  • php登录超时检测功能实例详解

    php登录超时检测功能实例详解 前言: php登录超时问题,当用户超过一定时间没有操作页面时自动退出登录,原理是通过js进行访问判断的!代码如下(以thinkphp5.0版本为例) 1.创建登录版块控制器: <?php namespace app\manage\control; use \think\Controller; class Main extends Controller{ protected $request; public function _initialize(){ $this

  • C++调用Python基础功能实例详解

    c++调用Python首先安装Python,以win7为例,Python路径为:c:\Python35\,通过mingw编译c++代码. 编写makefile文件,首先要添加包含路径: inc_path += c:/Python35/include 然后添加链接参数: ld_flag += c:/Python35/libs/libpython35.a 在源文件中添加头文件引用: #include "Python.h" Python解释器需要进行初始化,完成任务后需要终止: void s

  • SpringBoot 集成Kaptcha实现验证码功能实例详解

    在一个web应用中验证码是一个常见的元素.不管是防止机器人还是爬虫都有一定的作用,我们是自己编写生产验证码的工具类,也可以使用一些比较方便的验证码工具.在网上收集一些资料之后,今天给大家介绍一下kaptcha的和springboot一起使用的简单例子. 准备工作: 1.你要有一个springboot的hello world的工程,并能正常运行. 2.导入kaptcha的maven: <!-- https://mvnrepository.com/artifact/com.github.penggl

  • 使用Vue-Router 2实现路由功能实例详解

    vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用.vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来.传统的页面应用,是用一些超链接来实现页面切换和跳转的.在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换. 注意:vue-router 2只适用于Vue2.x版本,下面我们是基于vue2.0讲的如何使用vue-router 2实现路由功能. 推荐使用npm安装. npm install v

  • Spring boot的上传图片功能实例详解

    简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. 特点 1. 创建独立的Spring应用程序 2. 嵌入的Tomcat,无需部署WAR文件 3. 简化Maven配置 4. 自动配置Spring 5. 提

  • mui上拉加载功能实例详解

    最近在做移动端的项目,用到了mui的上拉加载,整理如下: 1.需要引入的css.js <link rel="stylesheet" href="common/mui/css/mui.min.css" rel="external nofollow" > <script src="js/jquery-3.2.0.min.js"></script> <script src="com

  • C#动态创建button按钮的方法实例详解

    C#动态创建button按钮的方法实例详解 C#编程中经常需要动态创建,本文主要介绍C#动态创建button按钮的方法,涉及C#按钮属性动态设置的相关技巧,以供借鉴参考.具体实现方法如下: 例子: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.T

随机推荐