【问题标题】:Rotate Globe.gl globe (with react-three-fiber or otherwise) in React在 React 中旋转 Globe.gl 地球仪(使用 react-three-fiber 或其他方式)
【发布时间】:2021-05-22 18:38:17
【问题描述】:

我正在关注来自 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,
    name,
    city,
    country,
    iata,
    icao,
    lat,
    lng,
    alt,
    timezone,
    dst,
    tz,
    type,
    source,
  });
  const routeParse = ([
    airline,
    airlineId,
    srcIata,
    srcAirportId,
    dstIata,
    dstAirportId,
    codeshare,
    stops,
    equipment,
  ]) => ({
    airline,
    airlineId,
    srcIata,
    srcAirportId,
    dstIata,
    dstAirportId,
    codeshare,
    stops,
    equipment,
  });

  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, ${OPACITY})`,
      ]}
      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 地球仪?

【问题讨论】:

  • 如果您从未在Box 中使用过GlobeHome,为什么还要创建它?
  • 我不是吗? GlobeHome 是创建地球的函数。我从Globe.js 导出它并将其导入为Globe,然后进入Box 函数。然后我尝试在 App 中渲染 Box 函数。希望这可以澄清
  • 我的错,我没看到。你正在使用它。该错误意味着您在代码中的某个位置尝试使用名为THREE.Div 的东西,但这在库中本身并不存在。也许你,或者react-three-fiber 在创建它之前尝试使用THREE.Div
  • 也许吧。我会检查并跟进

标签: reactjs three.js 3d react-three-fiber webgl-globe


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2021-08-27
    • 2020-11-13
    • 2022-12-24
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 2020-10-31
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多