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

来源:脚本之家  责任编辑:小易  
目录
前言创建场景以及相机创建一个平面添加图片创建线添加轴线缩放、定位、以及旋转添加文字正交摄像机和透视摄像机的区别总结

前言

最近公司要做一个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),如果不成立,可能看到的效果不太一样nearfar以上两个属性通透视摄像机原理

角度计算:

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

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

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

总结

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

您可能感兴趣的文章:vue页面引入three.js实现3d动画场景操作three.js搭建室内场景教程Three.JS实现三维场景three.js中文文档学习之创建场景Three.js基础学习之场景对象

  • 本文相关:
  • 基于element-ui?动态换肤的代码详解
  • 2014 年最热门的21款javascript框架推荐
  • js css3实现图片拖拽效果
  • js中创建对象的几种方式示例介绍
  • js实现判断对象是否为空对象的5种方法
  • 微信小程序使用echarts和分包的完整步骤
  • javascript 格式化数字、金额、千分位、保留几位小数、舍入舍去
  • javascript跨域方法汇总
  • ionic2自定义cordova插件开发以及使用(android)
  • 前端如何实现动画过渡效果
  • threejs为什么不火
  • threejs为什么不火
  • threejs为什么不火?
  • three.js 怎么创建地图
  • three.js如何让场景中模型跟随鼠标旋转呀
  • Threejs怎么才可以对每一个mesh绑定事件
  • three.js难吗?
  • three.js ThingJS Hightopo Babylon.js 有什么差别
  • Three.js源码阅读笔记(基础的核心Core对象)
  • 小白请教一下大神们 怎么用three.js加载obj模型
  • Three.js源码阅读笔记(物体是如何组织的)
  • three.js的控件api在哪
  • three trackballcontrols.js怎么设置相机位置
  • 有没有比较好的用three.js写的云的效果
  • 怎么样对three.js进行本地化部署
  • keyboardstate 实在three.js库中吗
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascriptjavascript技巧正交相机的应用vue页面引入three.js实现3d动画场景操作three.js搭建室内场景教程three.js实现三维场景three.js中文文档学习之创建场景three.js基础学习之场景对象基于element-ui?动态换肤的代码详解2014 年最热门的21款javascript框架推荐js css3实现图片拖拽效果js中创建对象的几种方式示例介绍js实现判断对象是否为空对象的5种方法微信小程序使用echarts和分包的完整步骤javascript 格式化数字、金额、千分位、保留几位小数、舍入舍去javascript跨域方法汇总ionic2自定义cordova插件开发以及使用(android)前端如何实现动画过渡效果js删除数组里的某个元素方法js刷新页面方法大全js中settimeout()的用法详解js页面跳转常用的几种方式js截取字符串常用方法详细整理js数组与字符串的相互转换方法js保留两位小数方法总结js设置cookie、读取cookie、删除cookiejs打开新窗口的2种方式js 将json字符串转换为json对象的方法解析面向切面编程(aop)的理解探讨跨域请求资源的几种方式(总结)如何利用moment处理时间戳并计算时间的差值微信小程序实现搜索商品和历史记录的功能js实现五星好评案例js trim函数 去空格函数与正则集锦javascript白色简洁计算器css 二级菜单 实现代码集合 修正版微信小程序实现双层嵌套菜单栏js修改css样式style浅谈
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved