最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ThreeJS從創(chuàng)建場景到使用功能實(shí)例詳解

 更新時(shí)間:2022年08月21日 08:44:55   作者:LixHu  
threejs是一個(gè)用于在瀏覽器中繪制3D圖像的JS庫,它是基于webgl實(shí)現(xiàn)了,包括了webgl1和webgl2的渲染引擎,下面這篇文章主要給大家介紹了關(guān)于ThreeJS從創(chuàng)建場景到使用功能的相關(guān)資料,需要的朋友可以參考下

前言

最近公司要做一個(gè)2.5D插件,然后自己學(xué)旋轉(zhuǎn)角度不太好,然后就使用了THREEJS, 用起來還是比較繁瑣的,整體支持不太好,整體都是自己研究,看到寫的不好地方勿怪

創(chuàng)建場景以及相機(jī)

首先,要創(chuàng)建一個(gè)場景,以及一個(gè)相機(jī)(相機(jī)分為透視相機(jī)和正交攝像機(jī),區(qū)別在后面會解釋),代碼如下

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 = () => {
    // 相機(jī)
    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
           }}/>
    )
  }
}

創(chuàng)建一個(gè)平面

相機(jī)和平面創(chuàng)建完成,接來下我這邊是直接創(chuàng)建一個(gè)平面放到場景中,代碼如下

    const geometry = new THREE.PlaneGeometry(800, 400)
    // 設(shè)置透明以及顏色
    const material = new THREE.MeshBasicMaterial({ color: 0x091A20, transparent: true, opacity: 0.8 })
    const plane = new THREE.Mesh(geometry, material)
    // 這邊操作的是旋轉(zhuǎn)還是位置
    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
    // 因?yàn)樘砑訄D片加載是異步的,所以在load方法中操作,每次加載之后都要執(zhí)行一遍renders方法,重新渲染場景
    new THREE.TextureLoader().load(image, (texture) => {
      // 設(shè)置透明度,以及基礎(chǔ)材質(zhì)的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()
    })

創(chuàng)建線

首先要說,因?yàn)檎hreeJs的line不能設(shè)置線寬,所以要用到的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的位置
      // 點(diǎn)對點(diǎn)的線
      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)
      // 更新完之后在執(zhí)行一遍render,把東西渲染到畫布中
      this.renders()

添加軸線

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

縮放、定位、以及旋轉(zhuǎn)

    // 縮放功能對應(yīng)mesh進(jìn)行縮放,每個(gè)mesh添加后都有固定的position, rotation, scale 屬性
    mesh.position.set(x, y, z)
    mesh.rotation.set(x, y, z)
    mesh.scale.set(x, y, z)
    // 也可以這樣, scale, rotation 都可以這么設(shè)置
    mesh.position.x = 0 
    mesh.position.y = 0
    mesh.position.z = 0

添加文字

添加文字使用threeJS官方的添加文字需要導(dǎo)入json文件,而且還需要中文配置,所以使用起來占用內(nèi)存會比較大,所以當(dāng)前項(xiàng)目中使用的是Canvas導(dǎo)入文字圖片

    //創(chuàng)建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)
    // 導(dǎo)出圖片路徑
    const url = canvas.toDataURL('image/png')
    // 設(shè)置圖片位置等信息
    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()
    })

正交攝像機(jī)和透視攝像機(jī)的區(qū)別

這邊畫圖的話我就不畫了,這塊只是稍微的解釋一下,具體的可以看一下搜到的文章:正交相機(jī)的應(yīng)用

簡單來說

  • 正交攝像機(jī)的特點(diǎn)就是:場景中遠(yuǎn)處的物體和近處的物體是一樣大的
  • 透視攝像機(jī)的特點(diǎn)就是:場景中物體遵循近大遠(yuǎn)小的擺列,如果物體在最近,物體相對就會比較大

下面就是怎么使用這兩個(gè)相機(jī):

    // 透視攝像機(jī)
    this.camera = new THREE.PerspectiveCamera(30, this.mount.clientWidth / this.mount.clientHeight, 1, 2500)

    // 正交攝像機(jī)
    this.camera = new THREE.OrthographicCamera(width / -4, width / 4, height / 4, height / -4, -100, 10000)

透視攝像機(jī)PerspectiveCamera屬性介紹(以下都是個(gè)人理解,如果有不清楚的歡迎指出):

  • fov 攝像機(jī)視錐體垂直視野角度 (就是從攝像機(jī)看視角的角度有多大)
  • aspect 攝像機(jī)視錐體長寬比 (通常就是你整個(gè)場景的長寬比)
  • near 攝像機(jī)視錐體近端面 (就是攝像機(jī)最近看到的距離)
  • far 攝像機(jī)視錐體遠(yuǎn)端面 (攝像機(jī)最遠(yuǎn)看到的距離,和near組合起來就相當(dāng)于你攝像機(jī)從某個(gè)位置到某個(gè)位置的整體能看到的一個(gè)面)

正交攝像機(jī)OrthographicCamera屬性介紹:

  • left 攝像機(jī)視錐體左側(cè)面。
  • right 攝像機(jī)視錐體右側(cè)面。
  • top 攝像機(jī)視錐體上側(cè)面。
  • bottom 攝像機(jī)視錐體下側(cè)面。
  • 上面四個(gè)屬性推薦配置為場景的長款比,如代碼所示(使這個(gè)等式成立: | left / right | = 1,| top / buttom | = 1),如果不成立,可能看到的效果不太一樣
  • near
  • far
  • 以上兩個(gè)屬性通透視攝像機(jī)原理

角度計(jì)算:

如果設(shè)計(jì)剛好給你出了一個(gè)圖,表示3d的位置等,這塊需要一個(gè)角度計(jì)算,就需要改動攝像機(jī)的位置,以及l(fā)ookAt屬性:

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

這個(gè)屬性的設(shè)置需要自己設(shè)置(目前算法還不太了解,之后可能了解了會更新一下),把自己想象成一個(gè)攝像機(jī),擺在哪里看到的效果都是不一樣的,然后lookAt就是你眼睛看哪個(gè)位置,可以看的偏移一點(diǎn)這樣的效果

總結(jié)

到此這篇關(guān)于ThreeJS從創(chuàng)建場景到使用功能的文章就介紹到這了,更多相關(guān)ThreeJS創(chuàng)建場景到使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS發(fā)起HTTP請求的多種方式總結(jié)

    JS發(fā)起HTTP請求的多種方式總結(jié)

    這篇文章主要為大家詳細(xì)介紹了JavaScript發(fā)起HTTP請求的多種方式,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • 兼容IE與Firefox的js 復(fù)制代碼

    兼容IE與Firefox的js 復(fù)制代碼

    這是一段點(diǎn)擊復(fù)制的代碼,現(xiàn)在我的頁面里不僅有1個(gè)鏈接需要用到這段代碼。請哪位好心人指教一下應(yīng)該怎么用ID對應(yīng)的方式來改寫這段js,使它實(shí)現(xiàn)一個(gè)點(diǎn)擊復(fù)制對應(yīng)1個(gè)相應(yīng)內(nèi)容
    2009-12-12
  • javascript setAttribute, getAttribute 在不同瀏覽器上的不同表現(xiàn)

    javascript setAttribute, getAttribute 在不同瀏覽器上的不同表現(xiàn)

    該方法把指定的屬性設(shè)置為指定的值。如果不存在具有指定名稱的屬性,該方法將創(chuàng)建一個(gè)新屬性。
    2010-08-08
  • 原生js實(shí)現(xiàn)查詢天氣小應(yīng)用

    原生js實(shí)現(xiàn)查詢天氣小應(yīng)用

    這篇文章主要為大家詳細(xì)介紹了原生js實(shí)現(xiàn)查詢天氣的小應(yīng)用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • ECharts入門教程

    ECharts入門教程

    ECharts 是一個(gè)使用JavaScript實(shí)現(xiàn)的開源可視化庫,涵蓋各行業(yè)圖表,滿足各種需求。這篇文章介紹了ECharts的基礎(chǔ)知識,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • JavaScript解析URL參數(shù)示例代碼

    JavaScript解析URL參數(shù)示例代碼

    通過js解析URL參數(shù),本文創(chuàng)建了一個(gè)js類,并引用Request.QueryString,感興趣的朋友可以參考下,希望對大家有所幫助
    2013-08-08
  • webpack學(xué)習(xí)教程之publicPath路徑問題詳解

    webpack學(xué)習(xí)教程之publicPath路徑問題詳解

    這篇文章主要給大家介紹了webpack學(xué)習(xí)教程之publicPath路徑問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-06-06
  • JavaScript使用yield模擬多線程的方法

    JavaScript使用yield模擬多線程的方法

    這篇文章主要介紹了JavaScript使用yield模擬多線程的方法,實(shí)例分析了javascript多線程的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • 5個(gè)最佳的Javascript日期處理類庫分享

    5個(gè)最佳的Javascript日期處理類庫分享

    在大家日常網(wǎng)站開發(fā)和web應(yīng)用開發(fā)中,我們往往需要有效的調(diào)用Javascript處理日期和時(shí)間格式相關(guān)的函數(shù),在Javascript中已經(jīng)包含了部分最基本的內(nèi)建處理方法
    2012-04-04
  • 深入學(xué)習(xí)JavaScript執(zhí)行上下文

    深入學(xué)習(xí)JavaScript執(zhí)行上下文

    這篇文章主要介紹了深入學(xué)習(xí)JavaScript執(zhí)行上下文,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下,希望對你的學(xué)習(xí)有所幫助
    2022-08-08

最新評論

晋江市| 南开区| 波密县| 腾冲县| 铜山县| 梓潼县| 大宁县| 丰台区| 江永县| 西城区| 蚌埠市| 丹棱县| 岗巴县| 伊春市| 邢台县| 察隅县| 福海县| 南雄市| 上思县| 鄢陵县| 禹州市| 乌审旗| 宁陕县| 营山县| 调兵山市| 社旗县| 忻州市| 陆河县| 滁州市| 元朗区| 湖南省| 邳州市| 攀枝花市| 奉新县| 南木林县| 灌南县| 平邑县| 遵化市| 临泉县| 菏泽市| 临邑县|