第七章:交互与控制

7/23/2023 ReactThree.js

在本章节中,我们将学习如何实现React+Three.js应用程序中的交互和控制。我们将了解如何处理React事件与Three.js交互,并利用React组件来创建用户界面的控制器,以便用户可以与场景进行交互。

# 1. React事件处理与Three.js交互

在React+Three.js应用程序中,我们可以利用React的事件处理机制来实现与Three.js场景的交互。通过监听React组件上的事件,我们可以捕获用户的操作,并相应地改变Three.js场景中的元素。

例如,让我们实现一个按钮,点击按钮时使自定义几何体旋转:

import React, { useRef, useEffect, useState } from 'react';
import * as THREE from 'three';
import CustomGeometry from './CustomGeometry';

const ThreeScene = () => {
  // ...

  const [isRotating, setIsRotating] = useState(false);

  useEffect(() => {
    // ...

    // 创建自定义几何体和材质
    const customGeometry = new THREE.Geometry();
    // ...

    const customMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
    const customMesh = new THREE.Mesh(customGeometry, customMaterial);
    meshRef.current = customMesh;
    scene.current.add(customMesh);

    // ...

  }, []);

  useEffect(() => {
    // ...

    // 创建动画函数
    const animate = () => {
      if (isAnimating) {
        requestAnimationFrame(animate);

        // 使自定义几何体旋转
        if (isRotating) {
          customMesh.rotation.x += 0.01;
          customMesh.rotation.y += 0.01;
        }

        // 使用渲染器来渲染场景
        renderer.current.render(scene.current, camera.current);
      }
    };

    // 开始动画
    animate();

    // 在组件卸载时,停止动画
    return () => {
      setIsAnimating(false);
    };
  }, [isAnimating, isRotating]);

  // ...

  const handleRotationToggle = () => {
    setIsRotating((prevRotating) => !prevRotating);
  };

  return (
    <div>
      <div ref={sceneRef} />
      <button onClick={toggleWireframe}>切换显示模式</button>
      <input
        type="range"
        min="0"
        max="2"
        step="0.1"
        value={pointLightIntensity}
        onChange={handleIntensityChange}
      />
      <button onClick={toggleAnimation}>{isAnimating ? '暂停动画' : '开始动画'}</button>
      <button onClick={handleRotationToggle}>{isRotating ? '停止旋转' : '开始旋转'}</button>
    </div>
  );
};

export default ThreeScene;
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

在上述代码中,我们使用useState钩子来跟踪旋转状态。我们添加了一个按钮,并通过handleRotationToggle函数来切换旋转状态。在动画函数中,我们根据旋转状态来判断是否使自定义几何体旋转。

通过这样的实现,我们可以通过点击按钮来控制自定义几何体的旋转,实现了React事件处理与Three.js交互。

# 2. 使用React组件控制器

在React+Three.js应用程序中,我们可以利用React组件来创建用户界面的控制器,以便用户可以更方便地与场景进行交互。

例如,让我们创建一个控制器组件,包含用于调整自定义几何体位置和缩放的滑动条:

import React, { useRef, useEffect, useState } from 'react';
import * as THREE from 'three';
import CustomGeometry from './CustomGeometry';

const ControlPanel = ({ onPositionChange, onScaleChange }) => {
  return (
    <div>
      <div>
        <label>X位置:</label>
        <input
          type="range"
          min="-2"
          max="2"
          step="0.1"
          name="x"
          onChange={onPositionChange}
        />
      </div>
      <div>
        <label>Y位置:</label>
        <input
          type="range"
          min="-2"
          max="2"
          step="0.1"
          name="y"
          onChange={onPositionChange}
        />
      </div>
      <div>
        <label>Z位置:</label>
        <input
          type="range"
          min="-2"
          max="2"
          step="0.1"
          name="z"
          onChange={onPositionChange}
        />
      </div>
      <div>
        <label>X缩放:</label>
        <input
          type="range"
          min="0.5"
          max="2"
          step="0.1"
          name="x"
          onChange={onScaleChange}
        />
      </div>
      <div>
        <label>Y缩放:</label>
        <input
          type="range"
          min="0.5"
          max="2"
          step="0.1"
          name="y"
          onChange={onScaleChange}
        />
      </div>
      <div>
        <label>Z缩放:</label>
        <input
          type="range"
          min="0.5"
          max="2"
          step="0.1"
          name="z"
          onChange={onScaleChange}
        />
      </div>
    </div>
  );
};

const ThreeScene = () => {
  // ...

  // 使用useState来跟踪自定义几何体的位置和缩放
  const [position, setPosition] = useState({ x: 0, y: 0, z: 0 });
  const [scale, setScale] = useState({ x: 1, y: 1, z: 1 });

  useEffect(() => {
    // ...

    // 创建自定义几何体和材质
    const customGeometry = new THREE.Geometry();
    // ...

    const customMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
    const customMesh = new THREE.Mesh(customGeometry, customMaterial);
    meshRef.current = customMesh;
    scene.current.add(customMesh);

    // ...

  }, []);

  useEffect(() => {
    // ...

    // 创建动画函数
    const animate = () => {
      if (isAnimating) {
        requestAnimationFrame(animate);

        // 使自定义几何体旋转
        if

 (isRotating) {
          customMesh.rotation.x += 0.01;
          customMesh.rotation.y += 0.01;
        }

        // 使用渲染器来渲染场景
        renderer.current.render(scene.current, camera.current);
      }
    };

    // 开始动画
    animate();

    // 在组件卸载时,停止动画
    return () => {
      setIsAnimating(false);
    };
  }, [isAnimating, isRotating]);

  // ...

  const handlePositionChange = (event) => {
    const { name, value } = event.target;
    setPosition((prevPosition) => ({
      ...prevPosition,
      [name]: parseFloat(value),
    }));
  };

  const handleScaleChange = (event) => {
    const { name, value } = event.target;
    setScale((prevScale) => ({
      ...prevScale,
      [name]: parseFloat(value),
    }));
  };

  return (
    <div>
      <div ref={sceneRef} />
      <button onClick={toggleWireframe}>切换显示模式</button>
      <input
        type="range"
        min="0"
        max="2"
        step="0.1"
        value={pointLightIntensity}
        onChange={handleIntensityChange}
      />
      <button onClick={toggleAnimation}>{isAnimating ? '暂停动画' : '开始动画'}</button>
      <button onClick={handleRotationToggle}>{isRotating ? '停止旋转' : '开始旋转'}</button>
      <ControlPanel onPositionChange={handlePositionChange} onScaleChange={handleScaleChange} />
    </div>
  );
};

export default ThreeScene;
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

在上述代码中,我们创建了一个名为ControlPanel的React组件,用于展示用于调整自定义几何体位置和缩放的滑动条。我们将onPositionChangeonScaleChange函数作为属性传递给ControlPanel组件,用于处理滑动条值的变化。

ThreeScene组件中,我们通过useState钩子来跟踪自定义几何体的位置和缩放。我们在handlePositionChangehandleScaleChange函数中更新位置和缩放状态,并将这些函数作为属性传递给ControlPanel组件。

通过这样的实现,我们可以使用ControlPanel组件来调整自定义几何体的位置和缩放,实现了使用React组件控制器的交互与控制。

在本章节中,我们学习了如何实现React事件处理与Three.js交互,并利用React组件来创建用户界面的控制器。通过这些技术,我们可以实现更加丰富和灵活的用户交互体验。在下一章节中,我们将总结本教程并提供一些额外的学习资源,帮助您继续深入学习React和Three.js的应用。敬请期待!

编辑时间: 7/22/2023, 10:30:56 AM