【React】【react-globe.gl】3D Objects效果

目录

想要实现的效果

示例地址

实现过程

踩坑

  1. 示例是通过script引入的依赖,但本人需要在react项目中实现该效果。
  2. 按照react-globe.gl官方方法引入总是报错 Can't import the named export 'AmbientLight' from non EcmaScript module (only default export is available)
  3. 原因是通过import Globe from 'react-globe.gl';引入的是.mjs文件,react-globe.gl.mjs
  4. 尝试各种方法都失败,最终通过改为引入.js文件import Globe from "../../node_modules/react-globe.gl/dist/react-globe.gl.min";成功。

安装依赖

package.json版本

javascript 复制代码
    "react-globe.gl": "^2.27.0",
    "satellite.js": "^5.0.0",
    "three": "^0.157.0",
    "three-globe": "^2.30.0",
    "web-vitals": "^2.1.4"

引入页面

javascript 复制代码
import React, { Component, useState, useEffect, useRef, useMemo } from "react";
import Globe from "../../node_modules/react-globe.gl/dist/react-globe.gl.min";
import * as THREE from "three";
import * as satellite from "satellite.js";

function World() {
  const w = window.screen.width * 0.5;
  const h = (window.screen.height - 80) * 0.7;
  const EARTH_RADIUS_KM = 6371; // km
  const SAT_SIZE = 80; // km
  const TIME_STEP = 3 * 1000; // per frame

  const globeEl = useRef();
  const [satData, setSatData] = useState();
  const [globeRadius, setGlobeRadius] = useState();
  const [time, setTime] = useState(new Date());

  useEffect(() => {
    // time ticker
    (function frameTicker() {
      requestAnimationFrame(frameTicker);
      setTime((time) => new Date(+time + TIME_STEP));
    })();
  }, []);

  useEffect(() => {
    // load satellite data
    fetch("//unpkg.com/globe.gl/example/datasets/space-track-leo.txt")
      .then((r) => r.text())
      .then((rawData) => {
        const tleData = rawData
          .replace(/\r/g, "")
          .split(/\n(?=[^12])/)
          .filter((d) => d)
          .map((tle) => tle.split("\n"));
        const satData = tleData
          .map(([name, ...tle]) => ({
            satrec: satellite.twoline2satrec(...tle),
            name: name.trim().replace(/^0 /, ""),
          }))
          // exclude those that can't be propagated
          .filter((d) => !!satellite.propagate(d.satrec, new Date()).position)
          .slice(0, 1500);

        setSatData(satData);
      });
  }, []);

  const objectsData = useMemo(() => {
    if (!satData) return [];

    // Update satellite positions
    const gmst = satellite.gstime(time);
    return satData.map((d) => {
      const eci = satellite.propagate(d.satrec, time);
      if (eci.position) {
        const gdPos = satellite.eciToGeodetic(eci.position, gmst);
        const lat = satellite.radiansToDegrees(gdPos.latitude);
        const lng = satellite.radiansToDegrees(gdPos.longitude);
        const alt = gdPos.height / EARTH_RADIUS_KM;
        return { ...d, lat, lng, alt };
      }
      return d;
    });
  }, [satData, time]);

  const satObject = useMemo(() => {
    if (!globeRadius) return undefined;

    const satGeometry = new THREE.OctahedronGeometry(
      (SAT_SIZE * globeRadius) / EARTH_RADIUS_KM / 2,
      0
    );
    const satMaterial = new THREE.MeshLambertMaterial({
      color: "palegreen",
      transparent: true,
      opacity: 0.7,
    });
    return new THREE.Mesh(satGeometry, satMaterial);
  }, [globeRadius]);

  useEffect(() => {
    setGlobeRadius(globeEl.current.getGlobeRadius());
    globeEl.current.pointOfView({ altitude: 3.5 });
  }, []);
  return (
    <div id="globeViz" className="map_bg">
      <Globe
        width={w}
        height={h}
        backgroundColor="rgba(0,0,0,0)"
        ref={globeEl}
        globeImageUrl="//unpkg.com/three-globe/example/img/earth-blue-marble.jpg"
        objectsData={objectsData}
        objectLabel="name"
        objectLat="lat"
        objectLng="lng"
        objectAltitude="alt"
        objectFacesSurface={false}
        objectThreeObject={satObject}
      />
    </div>
  );
}

class App extends Component {
	...
	render() {
		return (
			...
             <World />
			...
		)
	}
}

export default App;
相关推荐
BY组态4 分钟前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·物联网·iot·web组态·组态
SoaringHeart6 分钟前
Flutter进阶:OverlayEntry 插入图层管理器 NOverlayZIndexManager
前端·flutter
放下华子我只抽RuiKe516 分钟前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架
迁移科技2 小时前
告别人工分拣!迁移科技 AI+3D 视觉让机器人 “看懂” 无序抓取
人工智能·科技·3d·机器人·自动化·视觉检测
IT_陈寒2 小时前
Redis缓存击穿把我整不会了,原来还有这手操作
前端·人工智能·后端
idcu2 小时前
深入 Lyt.js 组件系统:L2 渲染引擎层的核心
前端·typescript
这是程序猿3 小时前
Spring Boot自动配置详解
java·大数据·前端
文心快码BaiduComate3 小时前
干货|Comate Harness Engineering工程实践指南
前端·后端·程序员
还有多久拿退休金3 小时前
一张栈的图,治好你面试答不出 script 阻塞的病
前端·javascript
光辉GuangHui3 小时前
Agent Skill 也需要测试:如何搭建 Skill 评估框架
前端·后端·llm