• react中使用threejs小试牛刀


    搭建本地开发环境

    npx create-react-app react-three-demo
    
    • 1
    • 删除掉新项目中 src/ 文件夹下的所有文件。(不要删除整个 src 文件夹,删除里面的源文件。)

    • 安装路由依赖包和threejs依赖包

    # tips: 注意版本兼容问题
    npm install react-router@5 react-router-dom@5
    
    npm install --save three
    
    • 1
    • 2
    • 3
    • 4
    • 按照下面目录结构创建文件
    -public
    └─src
        ├─assets
        │  └─styles
        ├─routers
        │  └─index.js
        └─views
        │  ├─home.js
        │  └─demo.js
        ├─index.js // 入口文件
        ├─app.js // 主文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    组件和路由文件

    • 路由文件
    import { Route } from 'react-router-dom'
    import Index from '../views/index'
    import Demo from '../views/demo'
    
    // 路由配置
    const Routes = [
      {
        path: '/',
        exact: true,
        component: Index
      },
      {
        path: '/Demo',
        exact: true,
        component: Demo
      }
    ]
    
    function AppRouter() {
      return (
        <main>
          {Routes.map((item, index) => {
            return <Route key={index} path={item.path} exact={item.exact} component={item.component}></Route>
          })}
        </main>
      )
    }
    
    export default AppRouter
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 入口文件index.js
    import React from 'react'
    import ReactDOM from 'react-dom/client'
    
    import './assets/styles/base.css'
    import App from './App'
    
    const root = ReactDOM.createRoot(document.getElementById('root'))
    // 注意,不要使用严格模式去渲染,否则会导致 componentDidMount 钩子执行两次
    root.render(<App />)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • app.js
    import { BrowserRouter as Router, Link } from 'react-router-dom'
    import AppRouter from './routers'
    
    function App() {
      return (
        <Router>
          <div className="App">
            <nav>
              <Link to="/">首页</Link>
              <Link to="/Demo">demo</Link>
            </nav>
    
            <AppRouter></AppRouter>
          </div>
        </Router>
      )
    }
    
    export default App
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 首页 home.js
    import { Component } from 'react'
    import * as THREE from 'three'
    // import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
    
    export default class Index extends Component {
      render() {
        return <div id="stage"></div>
      }
    
      /**
       * @Description: 组件挂载完成
       * @return {*}
       */
      componentDidMount() {
        this.init()
        this.animate()
      }
    
      /**
       * @Description: 初始化
       * @return {*}
       */
      init = () => {
        this.scene = new THREE.Scene()
        this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - 33), 0.1, 1000)
    
        this.renderer = new THREE.WebGLRenderer()
        this.renderer.setSize(window.innerWidth, window.innerHeight - 33)
        document.getElementById('stage').appendChild(this.renderer.domElement)
    
        const geometry = new THREE.BoxGeometry(1, 1, 1)
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
        this.cube = new THREE.Mesh(geometry, material)
        this.scene.add(this.cube)
    
        this.camera.position.z = 5
      }
    
      /**
       * @Description: 旋转动画
       * @return {*}
       */
      animate = () => {
        requestAnimationFrame(this.animate)
        this.cube.rotation.x += 0.01
        this.cube.rotation.y += 0.01
        this.renderer.render(this.scene, this.camera)
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    package.json文件

    {
      "name": "react-three-demo",
      "version": "0.1.0",
      "private": true,
      "scripts": {
        "dev": "set PORT=8888 && react-scripts start",
        "build": "react-scripts build"
      },
      "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "react-router": "^5.3.3",
        "react-router-dom": "^5.3.3",
        "react-scripts": "5.0.1",
        "three": "^0.143.0",
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    备注

    搞这个小demo的过程中遇到一些问题,总结如下:

    1. nodejs版本要足够新,否则可能创建项目不成功

    2. npx create-react-app创建项目报错(不报错的忽略)

      npm ERR! code ENOLOCAL
      npm ERR! Could not install from "Files\nodejs\node_cache\_npx\1452" as it does not contain a package.json file.
      
      npm ERR! A complete log of this run can be found in:
      npm ERR!     C:\Program Files\nodejs\node_cache\_logs\2022-08-04T14_46_10_318Z-debug.log
      Install for create-react-app@latest failed with code 1
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      解决方法:
      检查本地用户下的 .npmrc 文件配置,去掉config配置,重新创建项目即可。
      如果还不行那就重新安装node吧
      
      • 1
      • 2
      • 3
    3. 路由报错,页面空白

      Uncaught Error: Invariant failed: You should not use  outside a 
      
      • 1
      那可能是react-router和react-router-dom的版本不兼容,或者是路由位置放错了。
      本文使用的 v5 版本,写法可以参考本文路由文件也可自己尝试其他方式。
      
      • 1
      • 2
    4. threejs创建的3D图形,canvas渲染出现两个

      // 注意入口文件中使用的是严格模式,导致 componentDidMount 钩子执行两次,init函数执行两次造成的
      // 解决方法:要么去掉严格模式,要不操作dom控制只有一个canvas元素,本文使用第一种方法
      root.render(
        
          
        
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      // 解决方法一
      root.render(<App />)
      
      • 1
      • 2
    5. 使用threejs 做demo过程中注意,方法使用箭头函数方便定义和使用变量,定义变量可以直接放在当前实例上。

  • 相关阅读:
    Spring 核心思想
    如何将本地项目推送到gitee仓库
    JAVA基础(四十四)——集合之Collection的Set接口
    任务调度之ScheduledThreadPoolExecutor源码分析
    Word控件Spire.Doc 【段落处理】教程(七):如如何通过在 C# 中附加 HTML 代码来设置 word 项目符号样式
    从全局视角看数据结构
    【分享】小红书采集图片下载到本地
    策略模式在社会中的应用
    Bootstrap的CSS类积累学习
    单元测试一(实践)-云计算2023.11-云南农业大学
  • 原文地址:https://blog.csdn.net/weixin_44539392/article/details/126164959