中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ThreeJS從創建場景到使用功能實例代碼分析

發布時間:2022-08-24 11:27:26 來源:億速云 閱讀:143 作者:iii 欄目:開發技術

本篇內容主要講解“ThreeJS從創建場景到使用功能實例代碼分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“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 mesh2 = new THREE.Mesh(boxGeom1, mat1)
      const point = []
      point.push(mesh.position) // mesh的位置
      point.push(mesh2.position)  // mesh2的位置
      // 點對點的線
      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(mesh2)
      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 mesh2 = new THREE.Mesh(textGeom, mat1)
      mesh2.position.set(attr.x, attr.y, attr.z)
      if (attr.rotation !== undefined) {
        mesh2.rotation.set(attr.rotation.x, attr.rotation.y, attr.rotation.z)
      }
      mesh2.scale.set(0.8, 0.8, 0.8)
      if (attr.group !== undefined) {
        attr.group.add(mesh2)
        plane.add(attr.group)
      } else {
        plane.add(mesh2)
      }
      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從創建場景到使用功能實例代碼分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

桂林市| 连城县| 康定县| 珲春市| 揭阳市| 巴彦县| 湾仔区| 志丹县| 绿春县| 应城市| 黔西| 潮州市| 离岛区| 兰考县| 闸北区| 东乡| 滨海县| 贞丰县| 凤山市| 磐石市| 慈溪市| 仪征市| 江阴市| 文成县| 阜城县| 宽甸| 梁河县| 喜德县| 东安县| 垦利县| 高密市| 民权县| 灵丘县| 田阳县| 平阴县| 三河市| 澎湖县| 绥化市| 曲靖市| 贡山| 土默特右旗|