在 React 中旋转 Globe.gl 地球使用 react-three-fiber 或其他方式

问题描述

我正在关注 Globe.gl 中的此 example 以实现以下 output。我想使用 react-three-fiber 旋转这个地球仪,即使用 example 中的方法

这是我的Globe.js

import React from "react";
import * as d3 from "d3-dsv";
import indexBy from "index-array-by";
import Globe from "react-globe.gl";

import earth from "../../public/images/earth-dark.png";
import background from "../../public/images/globeBackground.png";

function GlobeHome() {
  const { useState,useEffect,useRef } = React;
  const globeEl = useRef();
  const [airports,setAirports] = useState([]);
  const [routes,setRoutes] = useState([]);
  
  const COUNTRY = "United States";
  const OPACITY = 0.125;
  const airportParse = ([
    airportId,name,city,country,iata,icao,lat,lng,alt,timezone,dst,tz,type,source,]) => ({
    airportId,});
  const routeParse = ([
    airline,airlineId,srcIata,srcAirportId,dstIata,dstAirportId,codeshare,stops,equipment,]) => ({
    airline,});

  useEffect(() => {
    Promise.all([
      fetch(
        "https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat"
      )
        .then((res) => res.text())
        .then((d) => d3.csvParseRows(d,airportParse)),fetch(
        "https://raw.githubusercontent.com/jpatokal/openflights/master/data/routes.dat"
      )
        .then((res) => res.text())
        .then((d) => d3.csvParseRows(d,routeParse)),]).then(([airports,routes]) => {
      const byIata = indexBy(airports,"iata",false);

      const filteredRoutes = routes
        .filter(
          (d) =>
            byIata.hasOwnProperty(d.srcIata) && byIata.hasOwnProperty(d.dstIata)
        )
        .filter((d) => d.stops === "0")
        .map((d) =>
          Object.assign(d,{
            srcAirport: byIata[d.srcIata],dstAirport: byIata[d.dstIata],})
        )
        .filter(
          (d) =>
            d.srcAirport.country === COUNTRY && d.dstAirport.country !== COUNTRY
        );

      setAirports(airports);
      setRoutes(filteredRoutes);
    });
  },[]);

  useEffect(() => {
    globeEl.current.pointOfView({ lat: 42,lng: -71,altitude: 2 });
  },[]);

  return (
    <Globe
      ref={globeEl}
      width={1000}
      height={1000}
      showGlobe={true}
      globeImageUrl={earth}
      backgroundImageUrl={background}
      arcsData={routes}
      arcStartLat={(d) => +d.srcAirport.lat}
      arcStartLng={(d) => +d.srcAirport.lng}
      arcEndLat={(d) => +d.dstAirport.lat}
      arcEndLng={(d) => +d.dstAirport.lng}
      arcDashLength={0.25}
      arcDashGap={1}
      arcDashInitialGap={() => Math.random()}
      arcDashAnimateTime={4000}
      arcColor={(d) => [
        `rgba(48,64,77,${OPACITY})`,`rgba(191,204,214,]}
      arcsTransitionDuration={0}
      pointsData={airports}
      pointColor={() => "white"}
      pointAltitude={0}
      poinTradius={0.03}
      pointsMerge={true}
    />
  );
}

export default GlobeHome;

然后我将其导入到 Boxes.js 中:

import React,{ useRef,useState } from "react";
import { Canvas,useFrame } from "react-three-fiber";
import Globe from './Globe'

function Box(props) {
  // This reference will give us direct access to the mesh
  const mesh = useRef();
  // Set up state for the hovered and active state
  const [hovered,setHover] = useState(false);
  const [active,setActive] = useState(false);
  // Rotate mesh every frame,this is outside of React without overhead
  useFrame(() => {
    mesh.current.rotation.x = mesh.current.rotation.y += 0.01;
  });
  return (
    <mesh
      {...props}
      ref={mesh}
    >
      <Globe />
    </mesh>
  );
}

export default function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <spotLight position={[10,10,10]} angle={0.15} penumbra={1} />
      <pointLight position={[-10,-10,-10]} />
      <Box />
    </Canvas>
  );
}

使用这种方法会给我以下错误

Uncaught "Div" is not part of the THREE namespace! Did you forget to extend it?

关于调试的想法?有没有更好的方法来旋转这个 Globe.gl 地球仪?

解决方法

我也遇到了这个问题。问题是您将 Globe 组件作为 Box 组件的属性传递,该组件是一个网格。然后 Box 组件位于 Canvas 组件中。该库要求您将 Globe 组件作为标准 React 组件放置在 Canvas 组件之外。我能够通过将 App 组件更改为仅返回 及其属性而不是其他任何内容来解决逻辑中的问题。