0

我正在做一个有趣的项目,以帮助提高我对 ReactJS 和 ThreeJS 的认识和理解,但是遇到了将数据从父类传递到子类中的函数的问题。现在我的项目如下所示: App.js

import React, {Component} from 'react';

import {Globe, Building, BuildingBody} from './components';
import styles from './App.module.css';
import { fetchData } from './assets/api';

class App extends Component {
    state = {
      data: {},
      state: '',
      isMounted: true,
  }

  componentDidMount() {
      const fetchedData = fetchData();
      this.setState({ data: fetchedData});
      
  }

  handleStateChange = (state) => {
      const fetchedData = fetchData(state);
      this.setState({data: fetchedData, state: state})
  }
  render() {
    const { data, state, isMounted=true } = this.state;
    return (
      <div className={styles.container}>
        <div className={styles.dataContainer}>
          <Building handleStateChange={this.handleStateChange.bind(this)}/>
          <BuildingBody data = {data} state={state} />
        </div>
        <Globe data = {data} state={state}/>
      </div>
    );
  }
}

export default App;

我的 ThreeJS 部分如下所示: Globe.jsx

import React, { Component } from 'react';
import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';

import earthmap from '../../assets/images/earthmap4k.jpg';
import earthbump from '../../assets/images/earthbump4k.jpg';
import earthspec from '../../assets/images/earthspec4k.jpg';
import particle from '../../assets/images/particle.jpg';
import clouds from '../../assets/images/earthhiresclouds4K.jpg';

class Globe extends Component {
    constructor(props) {
        super (props);
        this.state = {
            state: props.state,
            data: props.data
        }
    }
    
    componentDidMount() {
        console.log(this.state.data)
        console.log(this.state.state)
        this.createScene();
        this.addSceneObjects();
        this.startAnimation();
        window.addEventListener('resize', this.handleWindowResize);
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this.handleWindowResize);
        window.cancelAnimationFrame(this.requestID);
        this.controls.dispose();
    }

    createScene = () => {
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera( 75, 720 / 480, 0.1, 1000 );
        this.controls = new OrbitControls(this.camera, this.mount);
        this.controls.enableZoom = false
        
        this.renderer = new THREE.WebGLRenderer({ antialiasing: true });
        this.renderer.setSize( 720, 480 );

        this.mount.appendChild( this.renderer.domElement );
        this.camera.position.z = 20;
    };

    addSceneObjects = () => {
        this.addLight();
        this.addEarth();
        this.addCoord();
    };

    addLight = () => {
        const lights = [];
        lights[0] = new THREE.PointLight(0xffffff, .3, 0);
        lights[1] = new THREE.PointLight(0xffffff, .4, 0);
        lights[2] = new THREE.PointLight(0xffffff, .7, 0);
        lights[3] = new THREE.AmbientLight( 0x706570 );

        lights[0].position.set(0, 200, 0);
        lights[1].position.set(200, 100, 400);
        lights[2].position.set(-200, -200, -50);

        this.scene.add(lights[0]);
        this.scene.add(lights[1]);
        this.scene.add(lights[2]);
        this.scene.add(lights[3]);
    };

    addEarth = () => {
        const earthMap = new THREE.TextureLoader().load( earthmap );
        const earthBumpMap = new THREE.TextureLoader().load( earthbump);
        const earthSpecMap = new THREE.TextureLoader().load( earthspec);

        const earthGeometry = new THREE.SphereGeometry( 10, 32, 32 );
        const earthMaterial = new THREE.MeshPhongMaterial({
            map: earthMap,
            bumpMap: earthBumpMap,
            bumpScale: 0.10,
            specularMap: earthSpecMap,
            specular: new THREE.Color('grey')
        });

        this.earthSphere = new THREE.Mesh( earthGeometry, earthMaterial );
        this.scene.add( this.earthSphere );

        const earthGeo = new THREE.SphereGeometry(10, 36, 36 );
        const cloudsTexture = THREE.ImageUtils.loadTexture( clouds );
        const materialClouds = new THREE.MeshLambertMaterial({
            color: 0xffffff, 
            map: cloudsTexture, 
            transparent:true, 
            opacity:0.4
        });

        this.earthClouds = new THREE.Mesh( earthGeo, materialClouds );
        this.earthClouds.scale.set( 1.015, 1.015, 1.015 );
        this.earthSphere.add( this.earthClouds );
    };

    addCoord = () => {
        this.particleMat = new THREE.PointsMaterial({
            color: 'rgb(255, 255, 255)',
            size: 0.25,
            //map: new THREE.TextureLoader().load(particle),
            //transparent: true,
            //blending: THREE.AdditiveBlending,
            //depthWrite: false
        });

        this.particleGeo = new THREE.SphereGeometry(10, 64, 64);

        this.particleGeo.vertices.forEach(function(vertex) {
            const lat = 31.688372;
            const lon = -106.405023;
            const radius = 10;
            const phi   = (90-lat)*(Math.PI/180);
            const theta = (lon+180)*(Math.PI/180);
            vertex.x = -((radius) * Math.sin(phi)*Math.cos(theta));
            vertex.z = ((radius) * Math.sin(phi)*Math.sin(theta));
            vertex.y = ((radius) * Math.cos(phi));
        });

        this.particleSystem = new THREE.Points(
            this.particleGeo,
            this.particleMat
        );

        this.particleSystem.name = 'particleSystem';

        this.earthClouds.add(this.particleSystem);
    };

    startAnimation = () => {
        this.earthSphere.rotation.y += 0.0009;
        //this.earthClouds.rotation.y += 0.001;
        this.requestID = window.requestAnimationFrame(this.startAnimation);
        //requestAnimationFrame(this.startAnimation);
    
        this.controls.update();

        this.renderer.render( this.scene, this.camera );
    };

    handleWindowResize = () => {
        const width = this.mount.innerWidth;
        const height = this.mount.innerHeight;

        this.renderer.setSize(width, height);
        this.camera.aspect = width / height;

        this.camera.updateProjectionMatrix();
    };

    render() {
        console.log(this.props.data)
        console.log(this.props.state)
        return (
        <>
            <div ref={ref => (this.mount = ref)} data = {this.props.data} state = {this.props.state}>
                
            </div>
        </>
        )
    }
}

export default Globe;

App.js中的数据确实会传递到render()我的Globe.jsx的函数中。但是,我想获取该数据并将其传递到Globe.jsx主体中,以便使用

this.particleGeo.vertices.forEach(function(vertex) {
            const lat = **INSERT DATA.latitude**;
            const lon = **INSERT DATA.longitude**;
            const radius = 10;
            const phi   = (90-lat)*(Math.PI/180);
            const theta = (lon+180)*(Math.PI/180);
            vertex.x = -((radius) * Math.sin(phi)*Math.cos(theta));
            vertex.z = ((radius) * Math.sin(phi)*Math.sin(theta));
            vertex.y = ((radius) * Math.cos(phi));
        });

但我目前在完成这项任务时迷失了方向。我知道可以访问作为函数的组件中的数据,但是当尝试将我的Globe.jsx转换为函数而不是类时,我的代码会中断(在更改this.state为变量/let/等之后)。如果大家能帮帮我,我将不胜感激。

4

1 回答 1

0

您可以在函数内部使用 this.props 访问道具:

addCoord = () => {
    const data = this.props.data;
   ....
}
于 2020-07-28T18:31:52.470 回答