react + three.js 學(xué)習(xí)之路

最近給了個(gè)需求,要求學(xué)習(xí)react + three.js 以后要是實(shí)現(xiàn)相應(yīng)的3d制作內(nèi)容 (最開始是講解,在結(jié)尾會(huì)附上全部代碼)
第一步還是安裝three.js

npm i three -S

three.js的官網(wǎng)中有相應(yīng)的內(nèi)容
引入three.js

import * as THREE from 'three'

當(dāng)我們使用的時(shí)候就可以寫成

const sence = new THREE.sence()

跟著官網(wǎng)的教程完成基礎(chǔ)的內(nèi)容實(shí)現(xiàn)還是很簡(jiǎn)單的。 但是要基于react 就還是要有一些修改。
首先獲取dom 的時(shí)候 可以使用 ref

          <div
                id= "canvas"
                style={{ width: '600px', height: '600px',background:'#888' }}
                ref={(mount) => { this.mount = mount }} 
            />

看到官網(wǎng)我們知道 要想呈現(xiàn)一個(gè)three.js的內(nèi)容我們需要 場(chǎng)景,相機(jī),和渲染器,
我們通過一個(gè)init() 的方法來實(shí)現(xiàn)內(nèi)容的顯示,然后在 compomentDidMount方法中調(diào)用他

componentDidMount() {
  this.init()
}
    
init = () => { //使用this是因?yàn)槲覀冃枰褂胻his.mount來渲染數(shù)據(jù)
        const scene =  new THREE.Scene() //創(chuàng)建場(chǎng)景
        const camera = new THREE.PerspectiveCamera( 75, this.mount.clientWidth / this.mount.clientHeight, 0.1, 1000 );
        //創(chuàng)建相機(jī)  這些參數(shù)在官網(wǎng)中都有指出  第一個(gè)參數(shù) 75 -> 視野角度(單位:度)  第二個(gè)參數(shù)是長(zhǎng)寬比 第三個(gè)是近截面 第四個(gè)是遠(yuǎn)截面
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        //創(chuàng)建渲染器。講道理我還沒有看這個(gè)參數(shù)是什么意思。 但是官網(wǎng)中有一個(gè)測(cè)試瀏覽器是否可以使用WebGL的方法,需要用到的可看一下
        this.scene = scene 
        this.camera = camera
        this.renderer = renderer
        //這三個(gè)賦值是為了方便我們把創(chuàng)建立方體或者其他元素的方法拆分出去,不讓代碼顯得太長(zhǎng)
        renderer.setSize(this.mount.clientWidth, this.mount.clientHeight );
        //將渲染器的長(zhǎng)寬 設(shè)置為我們要顯示的容器長(zhǎng)寬
        this.mount.appendChild( renderer.domElement );
        //將整個(gè)場(chǎng)景推入我們要顯示的元素中
        camera.position.z = 5; 
        // 我們生成的元素默認(rèn)和相機(jī)的位置是重復(fù)的,我們需要將相機(jī)移開,這樣我們才可以看到渲染的內(nèi)容
        this.createCube()
        this.animate()
}

在場(chǎng)景創(chuàng)建好之后,我們需要在場(chǎng)景之中繪制我們需要的內(nèi)容 我們按照官網(wǎng)先繪制一個(gè)立方體 cube,在 init之中引用 creatCube

creatCube = () => {
      const geometry = new THREE.BoxGeometry( 1, 2, 1, 4 );//繪制一個(gè)立方體,擦?xí)喈?dāng)于定點(diǎn)位置 (three自帶的對(duì)象)
      const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
      //定義材質(zhì) 我們這里用簡(jiǎn)單的顏色 , 其他的屬性可以寫入對(duì)象,就可以更改材質(zhì)
      const cube = new THREE.Mesh( geometry, material );
      //我們用到網(wǎng)格將 定義的材質(zhì)用到定義的立方題上生成cube
      this.cube = cube //同樣 為了方便我們?cè)趯懛椒ǖ臅r(shí)候用到cube做此操作
      this.scene.add( cube );//將我們生成的cube放到場(chǎng)景中 
}

此時(shí)我們看到的場(chǎng)景是一片綠色的方塊,為了顯示出我們生成的是3d 的立方體 我們運(yùn)用animate讓他動(dòng)起來 在init中引用

animate = () => {
      requestAnimationFrame( this.animate ); //像計(jì)時(shí)器一樣重復(fù)的渲染
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01; // 立方體進(jìn)行 的操作
      this.renderer.render( this.scene, this.camera );
}

接下來是官網(wǎng)有一個(gè)繪制線的教程
我就不做講解了。 在全部代碼中有體現(xiàn)
所以全部的代碼如下

import React, { Component } from 'react';
import * as THREE from 'three';
import Orbitcontrols from 'three-orbitcontrols';
import  './index.less'

class Three extends Component {
   
    componentDidMount() {
        this.init()
    }
    
    init = () => {
        const scene =  new THREE.Scene()
        const camera = new THREE.PerspectiveCamera( 75, this.mount.clientWidth / this.mount.clientHeight, 0.1, 1000 );
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        this.scene = scene
        this.camera = camera
        this.renderer = renderer
        renderer.setSize(this.mount.clientWidth, this.mount.clientHeight );
        this.mount.appendChild( renderer.domElement );
        camera.position.z = 5;
      
        this.createCube()
        this.createLine()
        this.animate();
        
    }

    createCube = () => {
      const geometry = new THREE.BoxGeometry( 1, 2, 1, 4 );
      const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
      const cube = new THREE.Mesh( geometry, material );
      this.cube = cube
      this.scene.add( cube );
    }

    createLine = () => {
      const material = new THREE.LineBasicMaterial({color: 0x0f00ff}) //定義線的材質(zhì)
      const geometry = new THREE.Geometry()
      geometry.vertices.push(new THREE.Vector3(-2, 0, 0))
      geometry.vertices.push(new THREE.Vector3( 0, 2, 0) ); //相當(dāng)于是從 將前兩個(gè)坐標(biāo)連成一條線
      // geometry.vertices.push(new THREE.Vector3( 2, 0, 0) );
      const line = new THREE.Line(geometry, material)
      this.line = line
      line.position.x = -1
      line.position.y = 2
      this.scene.add(line)
    }

    animate =() => {
      requestAnimationFrame( this.animate );
      this.cube.rotation.x += 0.01;
      this.cube.rotation.y += 0.01;
      this.line.rotation.x += 0.02
      this.renderer.render( this.scene, this.camera );
    }

    componentWillUnmount() {
        this.mount.removeChild(this.renderer.domElement)
      }
    render() {
        return (
            <div
                id= "canvas"
                style={{ width: '600px', height: '600px',background:'#888' }}
                ref={(mount) => { this.mount = mount }}
            />
        );
    }
}
//   ReactDOM.render(<Scene />, document.getElementById('canvas'))

export default Three;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容