vasturiano / three-globe

WebGL Globe Data Visualization as a ThreeJS reusable 3D object
https://vasturiano.github.io/three-globe/example/links/
MIT License
1.26k stars 149 forks source link

The correct way to import with react / next JS #27

Closed ahmed-adly-khalil closed 3 years ago

ahmed-adly-khalil commented 3 years ago

Hello, I'm so sorry to open this, however I have spent the past 8 hours trying to get it done with next JS with no luck.

I have the following great example fully working in an HTML file

Screen Shot 2021-04-04 at 3 28 01 PM and here is the code for the html file:

<head>
  <title>2</title>
  <script src="//unpkg.com/three"></script>
  <script src="//unpkg.com/three/examples/js/controls/TrackballControls.js"></script>
  <script src="//unpkg.com/three-globe"></script>
  <!--<script src="../../dist/three-globe.js"></script>-->
</head>

<body>
  <div id="globeViz"></div>

  <script>
    const Globe = new ThreeGlobe().globeImageUrl("g7.png");
    //.bumpImageUrl("//unpkg.com/three-globe/example/img/earth-topology.png");

    // custom globe material
    const globeMaterial = Globe.globeMaterial();
    globeMaterial.bumpScale = 10;
    new THREE.TextureLoader().load(
      "//unpkg.com/three-globe/example/img/earth-water.png",
      (texture) => {
        globeMaterial.specularMap = texture;
        globeMaterial.specular = new THREE.Color("lightgreen");
        globeMaterial.shininess = 25;
      }
    );

    // Setup renderer
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.getElementById("globeViz").appendChild(renderer.domElement);

    // Setup scene
    const scene = new THREE.Scene();
    scene.add(Globe);
    scene.add(new THREE.AmbientLight(0xbbbbbb));
    scene.add(new THREE.DirectionalLight(0xffffff, 0.2));

    // Setup camera
    const camera = new THREE.PerspectiveCamera();
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    camera.position.z = 500;

    // Add camera controls
    const tbControls = new THREE.TrackballControls(camera, renderer.domElement);
    tbControls.minDistance = 101;
    tbControls.rotateSpeed = 5;
    tbControls.zoomSpeed = 0.8;

    // Kick-off renderer
    function animate() {
      // IIFE
      // Frame cycle
      tbControls.update();
      Globe.rotation.y += 0.005;
      renderer.render(scene, camera);
      requestAnimationFrame(animate);
    }
    animate();
  </script>
</body>

Now i need to move this to next JS, and I want to use three-globe not react-globe.gl as this one gives me the needed control to do customization.

Here is the code for my next JS component.

import { useEffect } from 'react';
import dynamic from 'next/dynamic';
const ThreeGlobe = dynamic(() => import('three-globe').then(mod => mod.ThreeGlobe), { ssr: false })

export default function GlobeComponent() {

    useEffect(async () => {
        const myGlobe = new ThreeGlobe();

    }, []);

    return (
        <div>  </div>
    )
};

and it gives this error whatever i try to do Screen Shot 2021-04-04 at 3 31 21 PM

I think it might be something with how kapsule-class.js is implemented but i can't wrap my head around it.

Thank you so much.

ahmed-adly-khalil commented 3 years ago

I found a solution for anyone who will face this in the future:

import { useEffect } from 'react';

export default function GlobeComponent() {

    useEffect(async () => {

        const ThreeGlobe = (await import('three-globe')).default
        const myGlobe = new ThreeGlobe()
        console.log(myGlobe);

    }, []);

    return (
        <div>  </div>
    )
};