如何将 Threejs 连接到 React?
Posted
技术标签:
【中文标题】如何将 Threejs 连接到 React?【英文标题】:How to connect Threejs to React? 【发布时间】:2017-05-06 00:31:12 【问题描述】:我使用 React 并使用画布。我想将画布更改为 WebGL(Threejs 库)。如何将此库连接到 React?
我有一些元素,例如
<div ref="threejs"></div>
如何使它成为 Threejs 库调用的字段? PS:。我不想使用 react-threejs 之类的扩展
【问题讨论】:
在componentDidMount
中,您可以访问DOM 引用this.refs.threejs
并使用.appendChild(threeRenderer.domElement)
之类的东西
进一步阅读生命周期方法,如componentDidMount
: facebook.github.io/react/docs/…
查看我的回答如何在 React 中映射第 3 方库:***.com/a/40350880/1333836 在您的情况下应该看起来类似。
【参考方案1】:
以下是如何设置的示例 (see demo):
import React, Component from 'react'
import * as THREE from 'three'
class Scene extends Component
constructor(props)
super(props)
this.start = this.start.bind(this)
this.stop = this.stop.bind(this)
this.animate = this.animate.bind(this)
componentDidMount()
const width = this.mount.clientWidth
const height = this.mount.clientHeight
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
75,
width / height,
0.1,
1000
)
const renderer = new THREE.WebGLRenderer( antialias: true )
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial( color: '#433F81' )
const cube = new THREE.Mesh(geometry, material)
camera.position.z = 4
scene.add(cube)
renderer.setClearColor('#000000')
renderer.setSize(width, height)
this.scene = scene
this.camera = camera
this.renderer = renderer
this.material = material
this.cube = cube
this.mount.appendChild(this.renderer.domElement)
this.start()
componentWillUnmount()
this.stop()
this.mount.removeChild(this.renderer.domElement)
start()
if (!this.frameId)
this.frameId = requestAnimationFrame(this.animate)
stop()
cancelAnimationFrame(this.frameId)
animate()
this.cube.rotation.x += 0.01
this.cube.rotation.y += 0.01
this.renderScene()
this.frameId = window.requestAnimationFrame(this.animate)
renderScene()
this.renderer.render(this.scene, this.camera)
render()
return (
<div
style= width: '400px', height: '400px'
ref=(mount) => this.mount = mount
/>
)
export default Scene
您可能还对full screen example 感兴趣(请参阅GitHub)。
Here's an example using React Hooks 而不是一个类。
【讨论】:
想通了才发现这个,应该多点赞! 您能解释一下让示例在远程计算机上运行的所有过程吗?我只是了解纯 javascript。谢谢你:) 未将 self (this) 对象绑定到动画函数确实会在看到此示例之前引起问题。【参考方案2】:您可以使用react-three-fiber
npm install three @react-three/fiber
用法
import React from 'react';
import React3 from 'react-three-renderer';
import * as THREE from 'three';
import ReactDOM from 'react-dom';
class Simple extends React.Component
constructor(props, context)
super(props, context);
// construct the position vector here, because if we use 'new' within render,
// React will think that things have changed when they have not.
this.cameraPosition = new THREE.Vector3(0, 0, 5);
this.state =
cubeRotation: new THREE.Euler(),
;
this._onAnimate = () =>
// we will get this callback every frame
// pretend cubeRotation is immutable.
// this helps with updates and pure rendering.
// React will be sure that the rotation has now updated.
this.setState(
cubeRotation: new THREE.Euler(
this.state.cubeRotation.x + 0.1,
this.state.cubeRotation.y + 0.1,
0
),
);
;
render()
const width = window.innerWidth; // canvas width
const height = window.innerHeight; // canvas height
return (<React3
mainCamera="camera" // this points to the perspectiveCamera which has the name set to "camera" below
width=width
height=height
onAnimate=this._onAnimate
>
<scene>
<perspectiveCamera
name="camera"
fov=75
aspect=width / height
near=0.1
far=1000
position=this.cameraPosition
/>
<mesh
rotation=this.state.cubeRotation
>
<boxGeometry
width=1
height=1
depth=1
/>
<meshBasicMaterial
color=0x00ff00
/>
</mesh>
</scene>
</React3>);
ReactDOM.render(<Simple/>, document.body);
【讨论】:
I don't want to use extensions like react-threejs
是否有示例会改变 Euler
对象,而不是每次发生更改时都创建一个新实例?
@pailhead 通知 react 状态已经改变,你必须调用 setState 方法。 React 将旧值与新值进行比较,如果检测到更改,则会发生新的渲染。新旧比较是“浅”的(不是“深”,即通过引用比较数组和对象)。欧拉的突变不会被 React 检测到。
请注意,React setState 方法是异步的。根据当前状态更新状态不是一个好主意。请参阅 ***.com/a/48224805/731548 了解正确的做法。
@cquezel 可以存储一个更原始的值,例如 - 最后一次更改的时间戳。我相信这会导致检测到更改。想知道有没有这样的例子。【参考方案3】:
我已经将 three.js 的第一个示例转换为 React 的东西。 希望这会有所帮助 从“反应”导入反应; 导入'./App.css'; 从“三”导入 * 作为三;
class App extends React.Component
constructor(props)
super(props)
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.renderer = new THREE.WebGL1Renderer();
this.renderer.setSize( window.innerWidth, window.innerHeight );
this.geometry = new THREE.BoxGeometry();
this.material = new THREE.MeshBasicMaterial( color: 0x32a852);
this.cube = new THREE.Mesh( this.geometry, this.material)
animate = () =>
requestAnimationFrame(this.animate)
this.cube.rotation.x += 0.01;
this.cube.rotation.y += 0.01;
this.renderer.render(this.scene, this.camera);
componentDidMount()
document.body.appendChild( this.renderer.domElement );
this.scene.add( this.cube );
this.camera.position.z = 5;
this.animate()
render()
return(
<body id='document-body-01'>
</body>
);
export default App;
所以想法是这三个组件可以分解为构造函数、动画函数和componentdidmount。 我相信 this.varname 可以放在任何地方。 我觉得constructor是个好地方。 这样也可以设置其他示例。
【讨论】:
【参考方案4】:我推荐你使用三纤&三drei库。
然后尝试使用<Canvas></Canvas>
,您可以使用 React 的 useRef
钩子与画布对话。
https://docs.pmnd.rs/react-three-fiber/getting-started/introduction
这些文档非常适合入门,请务必查看它们!
【讨论】:
除了发布的链接之外,如果您提供基本示例会很好。以上是关于如何将 Threejs 连接到 React?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 React Native Promise 连接到 Swift
如何使用 Spring Boot jwt 将身份验证系统连接到 React.js